0007-Partition-wise-join-tests.patch
application/octet-stream
Filename: 0007-Partition-wise-join-tests.patch
Type: application/octet-stream
Part: 6
Patch
Format: format-patch
Series: patch 0007
Subject: Partition-wise join tests.
| File | + | − |
|---|---|---|
| src/test/regress/expected/partition_join.out | 4114 | 0 |
| src/test/regress/parallel_schedule | 1 | 1 |
| src/test/regress/serial_schedule | 1 | 0 |
| src/test/regress/sql/partition_join.sql | 515 | 0 |
From 82e4452ff549ede9f34684d363f66291a3bb632b Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Tue, 7 Feb 2017 11:57:30 +0530
Subject: [PATCH 07/11] Partition-wise join tests.
This file does not contain tests for joins between multi-leveled partitioned
tables. Those will be added later.
---
src/test/regress/expected/partition_join.out | 4114 ++++++++++++++++++++++++++
src/test/regress/parallel_schedule | 2 +-
src/test/regress/serial_schedule | 1 +
src/test/regress/sql/partition_join.sql | 515 ++++
4 files changed, 4631 insertions(+), 1 deletion(-)
create mode 100644 src/test/regress/expected/partition_join.out
create mode 100644 src/test/regress/sql/partition_join.sql
diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out
new file mode 100644
index 0000000..18238fa
--- /dev/null
+++ b/src/test/regress/expected/partition_join.out
@@ -0,0 +1,4114 @@
+--
+-- PARTITION_JOIN
+-- Test partition-wise join between partitioned tables
+--
+--
+-- partitioned by a single column
+--
+CREATE TABLE prt1 (a int, b int, c varchar) PARTITION BY RANGE(a);
+CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (250);
+CREATE TABLE prt1_p3 PARTITION OF prt1 FOR VALUES FROM (500) TO (600);
+CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (250) TO (500);
+INSERT INTO prt1 SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt1;
+ANALYZE prt1_p1;
+ANALYZE prt1_p2;
+ANALYZE prt1_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uprt1 AS SELECT * FROM prt1;
+CREATE TABLE prt2 (a int, b int, c varchar) PARTITION BY RANGE(b);
+CREATE TABLE prt2_p1 PARTITION OF prt2 FOR VALUES FROM (0) TO (250);
+CREATE TABLE prt2_p2 PARTITION OF prt2 FOR VALUES FROM (250) TO (500);
+CREATE TABLE prt2_p3 PARTITION OF prt2 FOR VALUES FROM (500) TO (600);
+INSERT INTO prt2 SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+ANALYZE prt2;
+ANALYZE prt2_p1;
+ANALYZE prt2_p2;
+ANALYZE prt2_p3;
+CREATE TABLE uprt2 AS SELECT * FROM prt2;
+-- inner join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ 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)
+ -> Seq Scan on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t1.a, t1.c
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Hash Join
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ Hash Cond: (t2_1.b = t1_2.a)
+ -> Seq Scan on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t1_2.a, t1_2.c
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Hash Join
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ Hash Cond: (t2_2.b = t1_1.a)
+ -> Seq Scan on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t1_1.a, t1_1.c
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+(34 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150
+ 300 | 0300 | 300 | 0300
+ 450 | 0450 | 450 | 0450
+(4 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1, uprt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150
+ 300 | 0300 | 300 | 0300
+ 450 | 0450 | 450 | 0450
+(4 rows)
+
+-- left outer join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ 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)
+ -> Seq Scan on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t1.a, t1.c
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ Hash Cond: (t2_1.b = t1_2.a)
+ -> Seq Scan on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t1_2.a, t1_2.c
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Hash Right Join
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ Hash Cond: (t2_2.b = t1_1.a)
+ -> Seq Scan on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t1_1.a, t1_1.c
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+(34 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 50 | 0050 | |
+ 100 | 0100 | |
+ 150 | 0150 | 150 | 0150
+ 200 | 0200 | |
+ 250 | 0250 | |
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 | |
+ 400 | 0400 | |
+ 450 | 0450 | 450 | 0450
+ 500 | 0500 | |
+ 550 | 0550 | |
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 50 | 0050 | |
+ 100 | 0100 | |
+ 150 | 0150 | 150 | 0150
+ 200 | 0200 | |
+ 250 | 0250 | |
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 | |
+ 400 | 0400 | |
+ 450 | 0450 | 450 | 0450
+ 500 | 0500 | |
+ 550 | 0550 | |
+(12 rows)
+
+-- right outer join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+ QUERY PLAN
+---------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c
+ Sort Key: t1.a, t2.b
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c
+ -> Append
+ -> Hash Right Join
+ Output: t2.b, t2.c, t1.a, t1.c
+ Hash Cond: (t1.a = t2.b)
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ -> Hash
+ Output: t2.b, t2.c
+ -> Seq Scan on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ Filter: ((t2.b % 25) = 0)
+ -> Hash Right Join
+ Output: t2_1.b, t2_1.c, t1_2.a, t1_2.c
+ Hash Cond: (t1_2.a = t2_1.b)
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ -> Hash
+ Output: t2_1.b, t2_1.c
+ -> Seq Scan on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ Filter: ((t2_1.b % 25) = 0)
+ -> Hash Right Join
+ Output: t2_2.b, t2_2.c, t1_1.a, t1_1.c
+ Hash Cond: (t1_1.a = t2_2.b)
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ -> Hash
+ Output: t2_2.b, t2_2.c
+ -> Seq Scan on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ Filter: ((t2_2.b % 25) = 0)
+(36 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150
+ 300 | 0300 | 300 | 0300
+ 450 | 0450 | 450 | 0450
+ | | 75 | 0075
+ | | 225 | 0225
+ | | 375 | 0375
+ | | 525 | 0525
+(8 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150
+ 300 | 0300 | 300 | 0300
+ 450 | 0450 | 450 | 0450
+ | | 75 | 0075
+ | | 225 | 0225
+ | | 375 | 0375
+ | | 525 | 0525
+(8 rows)
+
+-- full outer join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+ QUERY PLAN
+------------------------------------------------------------------
+ Sort
+ Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c
+ Sort Key: prt1_p1.a, prt2_p1.b
+ -> Append
+ -> Hash Full Join
+ Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c
+ Hash Cond: (prt1_p1.a = prt2_p1.b)
+ -> Seq Scan on public.prt1_p1
+ Output: prt1_p1.a, prt1_p1.c
+ Filter: ((prt1_p1.a % 25) = 0)
+ -> Hash
+ Output: prt2_p1.b, prt2_p1.c
+ -> Seq Scan on public.prt2_p1
+ Output: prt2_p1.b, prt2_p1.c
+ Filter: ((prt2_p1.b % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c
+ Hash Cond: (prt1_p2.a = prt2_p2.b)
+ -> Seq Scan on public.prt1_p2
+ Output: prt1_p2.a, prt1_p2.c
+ Filter: ((prt1_p2.a % 25) = 0)
+ -> Hash
+ Output: prt2_p2.b, prt2_p2.c
+ -> Seq Scan on public.prt2_p2
+ Output: prt2_p2.b, prt2_p2.c
+ Filter: ((prt2_p2.b % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_p3.a, prt1_p3.c, prt2_p3.b, prt2_p3.c
+ Hash Cond: (prt1_p3.a = prt2_p3.b)
+ -> Seq Scan on public.prt1_p3
+ Output: prt1_p3.a, prt1_p3.c
+ Filter: ((prt1_p3.a % 25) = 0)
+ -> Hash
+ Output: prt2_p3.b, prt2_p3.c
+ -> Seq Scan on public.prt2_p3
+ Output: prt2_p3.b, prt2_p3.c
+ Filter: ((prt2_p3.b % 25) = 0)
+(37 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 50 | 0050 | |
+ 100 | 0100 | |
+ 150 | 0150 | 150 | 0150
+ 200 | 0200 | |
+ 250 | 0250 | |
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 | |
+ 400 | 0400 | |
+ 450 | 0450 | 450 | 0450
+ 500 | 0500 | |
+ 550 | 0550 | |
+ | | 75 | 0075
+ | | 225 | 0225
+ | | 375 | 0375
+ | | 525 | 0525
+(16 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 50 | 0050 | |
+ 100 | 0100 | |
+ 150 | 0150 | 150 | 0150
+ 200 | 0200 | |
+ 250 | 0250 | |
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 | |
+ 400 | 0400 | |
+ 450 | 0450 | 450 | 0450
+ 500 | 0500 | |
+ 550 | 0550 | |
+ | | 75 | 0075
+ | | 225 | 0225
+ | | 375 | 0375
+ | | 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 t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b;
+ QUERY PLAN
+------------------------------------------------------------------
+ Sort
+ Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c
+ Sort Key: prt1_p1.a, prt2_p1.b
+ -> Append
+ -> Hash Full Join
+ Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c
+ Hash Cond: (prt1_p1.a = prt2_p1.b)
+ Filter: (((50) = prt1_p1.b) OR ((75) = prt2_p1.b))
+ -> Seq Scan on public.prt1_p1
+ Output: prt1_p1.a, prt1_p1.c, prt1_p1.b, 50
+ Filter: ((prt1_p1.a % 25) = 0)
+ -> Hash
+ Output: prt2_p1.b, prt2_p1.c, (75)
+ -> Seq Scan on public.prt2_p1
+ Output: prt2_p1.b, prt2_p1.c, 75
+ Filter: ((prt2_p1.b % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c
+ Hash Cond: (prt1_p2.a = prt2_p2.b)
+ Filter: (((50) = prt1_p2.b) OR ((75) = prt2_p2.b))
+ -> Seq Scan on public.prt1_p2
+ Output: prt1_p2.a, prt1_p2.c, prt1_p2.b, 50
+ Filter: ((prt1_p2.a % 25) = 0)
+ -> Hash
+ Output: prt2_p2.b, prt2_p2.c, (75)
+ -> Seq Scan on public.prt2_p2
+ Output: prt2_p2.b, prt2_p2.c, 75
+ Filter: ((prt2_p2.b % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_p3.a, prt1_p3.c, prt2_p3.b, prt2_p3.c
+ Hash Cond: (prt1_p3.a = prt2_p3.b)
+ Filter: (((50) = prt1_p3.b) OR ((75) = prt2_p3.b))
+ -> Seq Scan on public.prt1_p3
+ Output: prt1_p3.a, prt1_p3.c, prt1_p3.b, 50
+ Filter: ((prt1_p3.a % 25) = 0)
+ -> Hash
+ Output: prt2_p3.b, prt2_p3.c, (75)
+ -> Seq Scan on public.prt2_p3
+ Output: prt2_p3.b, prt2_p3.c, 75
+ Filter: ((prt2_p3.b % 25) = 0)
+(40 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b;
+ a | c | b | c
+----+------+----+------
+ 50 | 0050 | |
+ | | 75 | 0075
+(2 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b;
+ a | c | b | c
+----+------+----+------
+ 50 | 0050 | |
+ | | 75 | 0075
+(2 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+ QUERY PLAN
+------------------------------------------------------------------------------------
+ Sort
+ Output: prt1_p1.a, prt1_p1.c, (25), prt2_p1.b, prt2_p1.c, (50)
+ Sort Key: prt1_p1.a, prt2_p1.b
+ -> Result
+ Output: prt1_p1.a, prt1_p1.c, (25), prt2_p1.b, prt2_p1.c, (50)
+ -> Append
+ -> Hash Full Join
+ Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c, (25), (50)
+ Hash Cond: (prt1_p1.a = prt2_p1.b)
+ -> Seq Scan on public.prt1_p1
+ Output: prt1_p1.a, prt1_p1.c, 25
+ Filter: ((prt1_p1.a % 25) = 0)
+ -> Hash
+ Output: prt2_p1.b, prt2_p1.c, (50)
+ -> Seq Scan on public.prt2_p1
+ Output: prt2_p1.b, prt2_p1.c, 50
+ Filter: ((prt2_p1.b % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c, (25), (50)
+ Hash Cond: (prt1_p2.a = prt2_p2.b)
+ -> Seq Scan on public.prt1_p2
+ Output: prt1_p2.a, prt1_p2.c, 25
+ Filter: ((prt1_p2.a % 25) = 0)
+ -> Hash
+ Output: prt2_p2.b, prt2_p2.c, (50)
+ -> Seq Scan on public.prt2_p2
+ Output: prt2_p2.b, prt2_p2.c, 50
+ Filter: ((prt2_p2.b % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_p3.a, prt1_p3.c, prt2_p3.b, prt2_p3.c, (25), (50)
+ Hash Cond: (prt1_p3.a = prt2_p3.b)
+ -> Seq Scan on public.prt1_p3
+ Output: prt1_p3.a, prt1_p3.c, 25
+ Filter: ((prt1_p3.a % 25) = 0)
+ -> Hash
+ Output: prt2_p3.b, prt2_p3.c, (50)
+ -> Seq Scan on public.prt2_p3
+ Output: prt2_p3.b, prt2_p3.c, 50
+ Filter: ((prt2_p3.b % 25) = 0)
+(39 rows)
+
+SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+ a | c | phv | b | c | phv
+-----+------+-----+-----+------+-----
+ 0 | 0000 | 25 | 0 | 0000 | 50
+ 50 | 0050 | 25 | | |
+ 100 | 0100 | 25 | | |
+ 150 | 0150 | 25 | 150 | 0150 | 50
+ 200 | 0200 | 25 | | |
+ 250 | 0250 | 25 | | |
+ 300 | 0300 | 25 | 300 | 0300 | 50
+ 350 | 0350 | 25 | | |
+ 400 | 0400 | 25 | | |
+ 450 | 0450 | 25 | 450 | 0450 | 50
+ 500 | 0500 | 25 | | |
+ 550 | 0550 | 25 | | |
+ | | | 75 | 0075 | 50
+ | | | 225 | 0225 | 50
+ | | | 375 | 0375 | 50
+ | | | 525 | 0525 | 50
+(16 rows)
+
+SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+ a | c | phv | b | c | phv
+-----+------+-----+-----+------+-----
+ 0 | 0000 | 25 | 0 | 0000 | 50
+ 50 | 0050 | 25 | | |
+ 100 | 0100 | 25 | | |
+ 150 | 0150 | 25 | 150 | 0150 | 50
+ 200 | 0200 | 25 | | |
+ 250 | 0250 | 25 | | |
+ 300 | 0300 | 25 | 300 | 0300 | 50
+ 350 | 0350 | 25 | | |
+ 400 | 0400 | 25 | | |
+ 450 | 0450 | 25 | 450 | 0450 | 50
+ 500 | 0500 | 25 | | |
+ 550 | 0550 | 25 | | |
+ | | | 75 | 0075 | 50
+ | | | 225 | 0225 | 50
+ | | | 375 | 0375 | 50
+ | | | 525 | 0525 | 50
+(16 rows)
+
+-- Join with pruned partitions from joining relations
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ 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)
+ -> Seq Scan on public.prt2_p2 t2
+ Output: t2.b, t2.c
+ Filter: (t2.b > 250)
+ -> Hash
+ Output: t1.a, t1.c
+ -> Seq Scan on public.prt1_p2 t1
+ Output: t1.a, t1.c
+ Filter: ((t1.a < 450) AND ((t1.a % 25) = 0))
+(15 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.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 t1, uprt2 t2 WHERE t1.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)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ QUERY PLAN
+----------------------------------------------------------------------------------
+ Sort
+ Output: prt1_p1.a, prt1_p1.c, b, c
+ Sort Key: prt1_p1.a, b
+ -> Append
+ -> Nested Loop Left Join
+ Output: prt1_p1.a, prt1_p1.c, b, c
+ Join Filter: (prt1_p1.a = b)
+ -> Seq Scan on public.prt1_p1
+ Output: prt1_p1.a, prt1_p1.c
+ Filter: ((prt1_p1.a < 450) AND ((prt1_p1.a % 25) = 0))
+ -> Result
+ Output: b, c
+ One-Time Filter: false
+ -> Hash Right Join
+ Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c
+ Hash Cond: (prt2_p2.b = prt1_p2.a)
+ -> Seq Scan on public.prt2_p2
+ Output: prt2_p2.b, prt2_p2.c
+ Filter: (prt2_p2.b > 250)
+ -> Hash
+ Output: prt1_p2.a, prt1_p2.c
+ -> Seq Scan on public.prt1_p2
+ Output: prt1_p2.a, prt1_p2.c
+ Filter: ((prt1_p2.a < 450) AND ((prt1_p2.a % 25) = 0))
+(24 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.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 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM uprt2 WHERE b > 250) t2 ON t1.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)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ QUERY PLAN
+----------------------------------------------------------------------------------------
+ Sort
+ Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c
+ Sort Key: prt1_p2.a, prt2_p2.b
+ -> Result
+ Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c
+ -> Append
+ -> Hash Right Join
+ Output: prt2_p2.b, prt2_p2.c, prt1_p2.a, prt1_p2.c
+ Hash Cond: (prt1_p2.a = prt2_p2.b)
+ -> Seq Scan on public.prt1_p2
+ Output: prt1_p2.a, prt1_p2.c
+ Filter: (prt1_p2.a < 450)
+ -> Hash
+ Output: prt2_p2.b, prt2_p2.c
+ -> Seq Scan on public.prt2_p2
+ Output: prt2_p2.b, prt2_p2.c
+ Filter: ((prt2_p2.b > 250) AND ((prt2_p2.a % 25) = 0))
+ -> Nested Loop Left Join
+ Output: prt2_p3.b, prt2_p3.c, a, c
+ Join Filter: (a = prt2_p3.b)
+ -> Seq Scan on public.prt2_p3
+ Output: prt2_p3.b, prt2_p3.c
+ Filter: ((prt2_p3.b > 250) AND ((prt2_p3.a % 25) = 0))
+ -> Result
+ Output: a, c
+ One-Time Filter: false
+(26 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.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 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM uprt2 WHERE b > 250) t2 ON t1.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)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b ORDER BY t1.a, t2.b;
+ QUERY PLAN
+----------------------------------------------------------------------------------
+ Sort
+ Output: prt1_p1.a, prt1_p1.c, b, c
+ Sort Key: prt1_p1.a, b
+ -> Append
+ -> Hash Full Join
+ Output: prt1_p1.a, prt1_p1.c, b, c
+ Hash Cond: (prt1_p1.a = b)
+ -> Seq Scan on public.prt1_p1
+ Output: prt1_p1.a, prt1_p1.c
+ Filter: ((prt1_p1.a < 450) AND ((prt1_p1.a % 25) = 0))
+ -> Hash
+ Output: b, c
+ -> Result
+ Output: b, c
+ One-Time Filter: false
+ -> Hash Full Join
+ Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c
+ Hash Cond: (prt1_p2.a = prt2_p2.b)
+ -> Seq Scan on public.prt1_p2
+ Output: prt1_p2.a, prt1_p2.c
+ Filter: ((prt1_p2.a < 450) AND ((prt1_p2.a % 25) = 0))
+ -> Hash
+ Output: prt2_p2.b, prt2_p2.c
+ -> Seq Scan on public.prt2_p2
+ Output: prt2_p2.b, prt2_p2.c
+ Filter: ((prt2_p2.b > 250) AND ((prt2_p2.b % 25) = 0))
+ -> Hash Full Join
+ Output: a, c, prt2_p3.b, prt2_p3.c
+ Hash Cond: (prt2_p3.b = a)
+ -> Seq Scan on public.prt2_p3
+ Output: prt2_p3.b, prt2_p3.c
+ Filter: ((prt2_p3.b > 250) AND ((prt2_p3.b % 25) = 0))
+ -> Hash
+ Output: a, c
+ -> Result
+ Output: a, c
+ One-Time Filter: false
+(37 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.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 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.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)
+
+-- Semi-join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+ QUERY PLAN
+----------------------------------------------------
+ Merge Append
+ Sort Key: t1.a
+ -> Merge Semi Join
+ Output: t1.a, t1.b, t1.c
+ Merge Cond: (t1.a = t1_3.b)
+ -> Sort
+ Output: t1.a, t1.b, t1.c
+ Sort Key: t1.a
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Sort
+ Output: t1_3.b
+ Sort Key: t1_3.b
+ -> Seq Scan on public.prt2_p1 t1_3
+ Output: t1_3.b
+ Filter: ((t1_3.b % 25) = 0)
+ -> Merge Semi Join
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Merge Cond: (t1_2.a = t1_4.b)
+ -> Sort
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Sort Key: t1_2.a
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Sort
+ Output: t1_4.b
+ Sort Key: t1_4.b
+ -> Seq Scan on public.prt2_p2 t1_4
+ Output: t1_4.b
+ Filter: ((t1_4.b % 25) = 0)
+ -> Merge Semi Join
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Merge Cond: (t1_1.a = t1_5.b)
+ -> Sort
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Sort Key: t1_1.a
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Sort
+ Output: t1_5.b
+ Sort Key: t1_5.b
+ -> Seq Scan on public.prt2_p3 t1_5
+ Output: t1_5.b
+ Filter: ((t1_5.b % 25) = 0)
+(47 rows)
+
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 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)
+
+SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 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)
+
+-- lateral reference
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ QUERY PLAN
+-----------------------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a
+ Sort Key: t1.a
+ -> Result
+ Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a
+ -> Append
+ -> Nested Loop Left Join
+ Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a))
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Hash Join
+ Output: t2.a, t3.a, LEAST(t1.a, t2.a, t3.a)
+ Hash Cond: (t3.b = t2.a)
+ -> Seq Scan on public.prt2_p1 t3
+ Output: t3.a, t3.b
+ -> Hash
+ Output: t2.a
+ -> Seq Scan on public.prt1_p1 t2
+ Output: t2.a
+ Filter: (t1.a = t2.a)
+ -> Nested Loop Left Join
+ Output: t1_2.a, t1_2.b, t1_2.c, t2_2.a, t3_1.a, (LEAST(t1_2.a, t2_2.a, t3_1.a))
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Hash Join
+ Output: t2_2.a, t3_1.a, LEAST(t1_2.a, t2_2.a, t3_1.a)
+ Hash Cond: (t3_1.b = t2_2.a)
+ -> Seq Scan on public.prt2_p2 t3_1
+ Output: t3_1.a, t3_1.b
+ -> Hash
+ Output: t2_2.a
+ -> Seq Scan on public.prt1_p2 t2_2
+ Output: t2_2.a
+ Filter: (t1_2.a = t2_2.a)
+ -> Nested Loop Left Join
+ Output: t1_1.a, t1_1.b, t1_1.c, t2_1.a, t3_2.a, (LEAST(t1_1.a, t2_1.a, t3_2.a))
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Hash Join
+ Output: t2_1.a, t3_2.a, LEAST(t1_1.a, t2_1.a, t3_2.a)
+ Hash Cond: (t3_2.b = t2_1.a)
+ -> Seq Scan on public.prt2_p3 t3_2
+ Output: t3_2.a, t3_2.b
+ -> Hash
+ Output: t2_1.a
+ -> Seq Scan on public.prt1_p3 t2_1
+ Output: t2_1.a
+ Filter: (t1_1.a = t2_1.a)
+(51 rows)
+
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ a | b | c | t2a | t3a | least
+-----+-----+------+-----+-----+-------
+ 0 | 0 | 0000 | 0 | 0 | 0
+ 50 | 50 | 0050 | | |
+ 100 | 100 | 0100 | | |
+ 150 | 150 | 0150 | 150 | 150 | 150
+ 200 | 200 | 0200 | | |
+ 250 | 250 | 0250 | | |
+ 300 | 300 | 0300 | 300 | 300 | 300
+ 350 | 350 | 0350 | | |
+ 400 | 400 | 0400 | | |
+ 450 | 450 | 0450 | 450 | 450 | 450
+ 500 | 500 | 0500 | | |
+ 550 | 550 | 0550 | | |
+(12 rows)
+
+SELECT * FROM uprt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ a | b | c | t2a | t3a | least
+-----+-----+------+-----+-----+-------
+ 0 | 0 | 0000 | 0 | 0 | 0
+ 50 | 50 | 0050 | | |
+ 100 | 100 | 0100 | | |
+ 150 | 150 | 0150 | 150 | 150 | 150
+ 200 | 200 | 0200 | | |
+ 250 | 250 | 0250 | | |
+ 300 | 300 | 0300 | 300 | 300 | 300
+ 350 | 350 | 0350 | | |
+ 400 | 400 | 0400 | | |
+ 450 | 450 | 0450 | 450 | 450 | 450
+ 500 | 500 | 0500 | | |
+ 550 | 550 | 0550 | | |
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ QUERY PLAN
+-------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a
+ Sort Key: t1.a
+ -> Nested Loop Left Join
+ Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a
+ -> Append
+ -> Seq Scan on public.prt1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Seq Scan on public.prt1_p1 t1_1
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Seq Scan on public.prt1_p3 t1_2
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Seq Scan on public.prt1_p2 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.a, LEAST(t1.a, t2.a, t3.a)
+ Hash Cond: (t3.b = t2.a)
+ -> Seq Scan on public.prt2_p1 t3
+ Output: t3.a, t3.b
+ -> Hash
+ Output: t2.a
+ -> Seq Scan on public.prt1_p1 t2
+ Output: t2.a
+ Filter: (t1.b = t2.a)
+ -> Hash Join
+ Output: t2_2.a, t3_1.a, LEAST(t1.a, t2_2.a, t3_1.a)
+ Hash Cond: (t3_1.b = t2_2.a)
+ -> Seq Scan on public.prt2_p2 t3_1
+ Output: t3_1.a, t3_1.b
+ -> Hash
+ Output: t2_2.a
+ -> Seq Scan on public.prt1_p2 t2_2
+ Output: t2_2.a
+ Filter: (t1.b = t2_2.a)
+ -> Hash Join
+ Output: t2_1.a, t3_2.a, LEAST(t1.a, t2_1.a, t3_2.a)
+ Hash Cond: (t3_2.b = t2_1.a)
+ -> Seq Scan on public.prt2_p3 t3_2
+ Output: t3_2.a, t3_2.b
+ -> Hash
+ Output: t2_1.a
+ -> Seq Scan on public.prt1_p3 t2_1
+ Output: t2_1.a
+ Filter: (t1.b = t2_1.a)
+(49 rows)
+
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ a | b | c | t2a | t3a | least
+-----+-----+------+-----+-----+-------
+ 0 | 0 | 0000 | 0 | 0 | 0
+ 50 | 50 | 0050 | | |
+ 100 | 100 | 0100 | | |
+ 150 | 150 | 0150 | 150 | 150 | 150
+ 200 | 200 | 0200 | | |
+ 250 | 250 | 0250 | | |
+ 300 | 300 | 0300 | 300 | 300 | 300
+ 350 | 350 | 0350 | | |
+ 400 | 400 | 0400 | | |
+ 450 | 450 | 0450 | 450 | 450 | 450
+ 500 | 500 | 0500 | | |
+ 550 | 550 | 0550 | | |
+(12 rows)
+
+SELECT * FROM uprt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ a | b | c | t2a | t3a | least
+-----+-----+------+-----+-----+-------
+ 0 | 0 | 0000 | 0 | 0 | 0
+ 50 | 50 | 0050 | | |
+ 100 | 100 | 0100 | | |
+ 150 | 150 | 0150 | 150 | 150 | 150
+ 200 | 200 | 0200 | | |
+ 250 | 250 | 0250 | | |
+ 300 | 300 | 0300 | 300 | 300 | 300
+ 350 | 350 | 0350 | | |
+ 400 | 400 | 0400 | | |
+ 450 | 450 | 0450 | 450 | 450 | 450
+ 500 | 500 | 0500 | | |
+ 550 | 550 | 0550 | | |
+(12 rows)
+
+--
+-- partitioned by expression
+--
+CREATE TABLE prt1_e (a int, b int, c varchar) PARTITION BY RANGE(((a + b)/2));
+CREATE TABLE prt1_e_p1 PARTITION OF prt1_e FOR VALUES FROM (0) TO (250);
+CREATE TABLE prt1_e_p2 PARTITION OF prt1_e FOR VALUES FROM (250) TO (500);
+CREATE TABLE prt1_e_p3 PARTITION OF prt1_e FOR VALUES FROM (500) TO (600);
+INSERT INTO prt1_e SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt1_e;
+ANALYZE prt1_e_p1;
+ANALYZE prt1_e_p2;
+ANALYZE prt1_e_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uprt1_e AS SELECT * FROM prt1_e;
+CREATE TABLE prt2_e (a int, b int, c varchar) PARTITION BY RANGE(((b + a)/2));
+CREATE TABLE prt2_e_p1 PARTITION OF prt2_e FOR VALUES FROM (0) TO (250);
+CREATE TABLE prt2_e_p2 PARTITION OF prt2_e FOR VALUES FROM (250) TO (500);
+CREATE TABLE prt2_e_p3 PARTITION OF prt2_e FOR VALUES FROM (500) TO (600);
+INSERT INTO prt2_e SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i;
+ANALYZE prt2_e;
+ANALYZE prt2_e_p1;
+ANALYZE prt2_e_p2;
+ANALYZE prt2_e_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uprt2_e AS SELECT * FROM prt2_e;
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1, prt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ QUERY PLAN
+------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c
+ Sort Key: t1.a, t2.b
+ -> Append
+ -> Hash Join
+ Output: t1.a, t1.c, t2.b, t2.c
+ Hash Cond: (((t2.b + t2.a) / 2) = ((t1.a + t1.b) / 2))
+ -> Seq Scan on public.prt2_e_p1 t2
+ Output: t2.b, t2.c, t2.a
+ -> Hash
+ Output: t1.a, t1.c, t1.b
+ -> Seq Scan on public.prt1_e_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 + t2_1.a) / 2) = ((t1_1.a + t1_1.b) / 2))
+ -> Seq Scan on public.prt2_e_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.prt1_e_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 + t2_2.a) / 2) = ((t1_2.a + t1_2.b) / 2))
+ -> Seq Scan on public.prt2_e_p3 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.prt1_e_p3 t1_2
+ Output: t1_2.a, t1_2.c, t1_2.b
+ Filter: ((t1_2.a % 25) = 0)
+(34 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1, prt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150
+ 300 | 0300 | 300 | 0300
+ 450 | 0450 | 450 | 0450
+(4 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_e t1, uprt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150
+ 300 | 0300 | 300 | 0300
+ 450 | 0450 | 450 | 0450
+(4 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1 LEFT JOIN prt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ 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 + t2.a) / 2) = ((t1.a + t1.b) / 2))
+ -> Seq Scan on public.prt2_e_p1 t2
+ Output: t2.b, t2.c, t2.a
+ -> Hash
+ Output: t1.a, t1.c, t1.b
+ -> Seq Scan on public.prt1_e_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 + t2_1.a) / 2) = ((t1_1.a + t1_1.b) / 2))
+ -> Seq Scan on public.prt2_e_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.prt1_e_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 + t2_2.a) / 2) = ((t1_2.a + t1_2.b) / 2))
+ -> Seq Scan on public.prt2_e_p3 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.prt1_e_p3 t1_2
+ Output: t1_2.a, t1_2.c, t1_2.b
+ Filter: ((t1_2.a % 25) = 0)
+(34 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1 LEFT JOIN prt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 50 | 0050 | |
+ 100 | 0100 | |
+ 150 | 0150 | 150 | 0150
+ 200 | 0200 | |
+ 250 | 0250 | |
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 | |
+ 400 | 0400 | |
+ 450 | 0450 | 450 | 0450
+ 500 | 0500 | |
+ 550 | 0550 | |
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_e t1 LEFT JOIN uprt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 50 | 0050 | |
+ 100 | 0100 | |
+ 150 | 0150 | 150 | 0150
+ 200 | 0200 | |
+ 250 | 0250 | |
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 | |
+ 400 | 0400 | |
+ 450 | 0450 | 450 | 0450
+ 500 | 0500 | |
+ 550 | 0550 | |
+(12 rows)
+
+--
+-- N-way join
+--
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ QUERY PLAN
+------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Hash Join
+ Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c
+ Hash Cond: (((t3.a + t3.b) / 2) = t1.a)
+ -> Seq Scan on public.prt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ -> Hash
+ Output: t1.a, t1.c, t2.b, t2.c
+ -> Hash Join
+ Output: t1.a, t1.c, t2.b, t2.c
+ Hash Cond: (t2.b = t1.a)
+ -> Seq Scan on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t1.a, t1.c
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Hash Join
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c
+ Hash Cond: (((t3_1.a + t3_1.b) / 2) = t1_2.a)
+ -> Seq Scan on public.prt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Hash
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ -> Hash Join
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ Hash Cond: (t2_1.b = t1_2.a)
+ -> Seq Scan on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t1_2.a, t1_2.c
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Hash Join
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c
+ Hash Cond: (((t3_2.a + t3_2.b) / 2) = t1_1.a)
+ -> Seq Scan on public.prt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ -> Hash
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ -> Hash Join
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ Hash Cond: (t2_2.b = t1_1.a)
+ -> Seq Scan on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t1_1.a, t1_1.c
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+(57 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+(4 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM uprt1 t1, uprt2 t2, uprt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+(4 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Hash Right Join
+ Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c
+ Hash Cond: (((t3.a + t3.b) / 2) = t1.a)
+ -> Seq Scan on public.prt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ -> Hash
+ Output: t1.a, t1.c, t2.b, t2.c
+ -> Hash Right Join
+ Output: t1.a, t1.c, t2.b, t2.c
+ Hash Cond: (t2.b = t1.a)
+ -> Seq Scan on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t1.a, t1.c
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c
+ Hash Cond: (((t3_1.a + t3_1.b) / 2) = t1_2.a)
+ -> Seq Scan on public.prt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Hash
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ -> Hash Right Join
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ Hash Cond: (t2_1.b = t1_2.a)
+ -> Seq Scan on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t1_2.a, t1_2.c
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Hash Right Join
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c
+ Hash Cond: (((t3_2.a + t3_2.b) / 2) = t1_1.a)
+ -> Seq Scan on public.prt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ -> Hash
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ -> Hash Right Join
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ Hash Cond: (t2_2.b = t1_1.a)
+ -> Seq Scan on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t1_1.a, t1_1.c
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+(57 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | 100 | 0050
+ 100 | 0100 | | | 200 | 0100
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | 400 | 0200
+ 250 | 0250 | | | 500 | 0250
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | 700 | 0350
+ 400 | 0400 | | | 800 | 0400
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | 1000 | 0500
+ 550 | 0550 | | | 1100 | 0550
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) LEFT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | 100 | 0050
+ 100 | 0100 | | | 200 | 0100
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | 400 | 0200
+ 250 | 0250 | | | 500 | 0250
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | 700 | 0350
+ 400 | 0400 | | | 800 | 0400
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | 1000 | 0500
+ 550 | 0550 | | | 1100 | 0550
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Hash Right Join
+ Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c
+ Hash Cond: (((t3.a + t3.b) / 2) = t2.b)
+ -> Seq Scan on public.prt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ -> Hash
+ Output: t1.a, t1.c, t2.b, t2.c
+ -> Hash Right Join
+ Output: t1.a, t1.c, t2.b, t2.c
+ Hash Cond: (t2.b = t1.a)
+ -> Seq Scan on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t1.a, t1.c
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c
+ Hash Cond: (((t3_1.a + t3_1.b) / 2) = t2_1.b)
+ -> Seq Scan on public.prt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Hash
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ -> Hash Right Join
+ Output: t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ Hash Cond: (t2_1.b = t1_2.a)
+ -> Seq Scan on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t1_2.a, t1_2.c
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Hash Right Join
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c
+ Hash Cond: (((t3_2.a + t3_2.b) / 2) = t2_2.b)
+ -> Seq Scan on public.prt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ -> Hash
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ -> Hash Right Join
+ Output: t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ Hash Cond: (t2_2.b = t1_1.a)
+ -> Seq Scan on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t1_1.a, t1_1.c
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+(57 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | |
+ 100 | 0100 | | | |
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | |
+ 250 | 0250 | | | |
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | |
+ 400 | 0400 | | | |
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | |
+ 550 | 0550 | | | |
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) LEFT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | |
+ 100 | 0100 | | | |
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | |
+ 250 | 0250 | | | |
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | |
+ 400 | 0400 | | | |
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | |
+ 550 | 0550 | | | |
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Hash Right Join
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c, t2.b, t2.c
+ Hash Cond: (t2.b = t1.a)
+ -> Seq Scan on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c
+ -> Hash Right Join
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c
+ Hash Cond: (t1.a = ((t3.a + t3.b) / 2))
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ -> Hash
+ Output: t3.a, t3.b, t3.c
+ -> Seq Scan on public.prt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ Filter: ((t3.a % 25) = 0)
+ -> Hash Right Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ Hash Cond: (t2_1.b = t1_2.a)
+ -> Seq Scan on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c
+ -> Hash Right Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c
+ Hash Cond: (t1_2.a = ((t3_1.a + t3_1.b) / 2))
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ -> Hash
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Seq Scan on public.prt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ Filter: ((t3_1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ Hash Cond: (t2_2.b = t1_1.a)
+ -> Seq Scan on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c
+ -> Hash Right Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c
+ Hash Cond: (t1_1.a = ((t3_2.a + t3_2.b) / 2))
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ -> Hash
+ Output: t3_2.a, t3_2.b, t3_2.c
+ -> Seq Scan on public.prt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ Filter: ((t3_2.a % 25) = 0)
+(57 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | 100 | 0050
+ 100 | 0100 | | | 200 | 0100
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | 400 | 0200
+ 250 | 0250 | | | 500 | 0250
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | 700 | 0350
+ 400 | 0400 | | | 800 | 0400
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | 1000 | 0500
+ 550 | 0550 | | | 1100 | 0550
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | 100 | 0050
+ 100 | 0100 | | | 200 | 0100
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | 400 | 0200
+ 250 | 0250 | | | 500 | 0250
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | 700 | 0350
+ 400 | 0400 | | | 800 | 0400
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | 1000 | 0500
+ 550 | 0550 | | | 1100 | 0550
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Hash Right Join
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c, t1.a, t1.c
+ Hash Cond: (t1.a = t2.b)
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ -> Hash
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c
+ -> Hash Right Join
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c
+ Hash Cond: (t2.b = ((t3.a + t3.b) / 2))
+ -> Seq Scan on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t3.a, t3.b, t3.c
+ -> Seq Scan on public.prt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ Filter: ((t3.a % 25) = 0)
+ -> Hash Right Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c, t1_2.a, t1_2.c
+ Hash Cond: (t1_2.a = t2_1.b)
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ -> Hash
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c
+ -> Hash Right Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c
+ Hash Cond: (t2_1.b = ((t3_1.a + t3_1.b) / 2))
+ -> Seq Scan on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Seq Scan on public.prt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ Filter: ((t3_1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c, t1_1.a, t1_1.c
+ Hash Cond: (t1_1.a = t2_2.b)
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ -> Hash
+ Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c
+ -> Hash Right Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c
+ Hash Cond: (t2_2.b = ((t3_2.a + t3_2.b) / 2))
+ -> Seq Scan on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t3_2.a, t3_2.b, t3_2.c
+ -> Seq Scan on public.prt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ Filter: ((t3_2.a % 25) = 0)
+(57 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ | | | | 100 | 0050
+ | | | | 200 | 0100
+ | | | | 400 | 0200
+ | | | | 500 | 0250
+ | | | | 700 | 0350
+ | | | | 800 | 0400
+ | | | | 1000 | 0500
+ | | | | 1100 | 0550
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ | | | | 100 | 0050
+ | | | | 200 | 0100
+ | | | | 400 | 0200
+ | | | | 500 | 0250
+ | | | | 700 | 0350
+ | | | | 800 | 0400
+ | | | | 1000 | 0500
+ | | | | 1100 | 0550
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+---------------------------------------------------------------------------------------------------------------
+ Sort
+ Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c, ((prt1_e_p1.a + prt1_e_p1.b)), prt1_e_p1.c
+ Sort Key: prt1_p1.a, prt2_p1.b, ((prt1_e_p1.a + prt1_e_p1.b))
+ -> Result
+ Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c, (prt1_e_p1.a + prt1_e_p1.b), prt1_e_p1.c
+ -> Append
+ -> Hash Full Join
+ Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c, prt1_e_p1.a, prt1_e_p1.b, prt1_e_p1.c
+ Hash Cond: (prt1_p1.a = ((prt1_e_p1.a + prt1_e_p1.b) / 2))
+ -> Hash Full Join
+ Output: prt1_p1.a, prt1_p1.c, prt2_p1.b, prt2_p1.c
+ Hash Cond: (prt1_p1.a = prt2_p1.b)
+ -> Seq Scan on public.prt1_p1
+ Output: prt1_p1.a, prt1_p1.c
+ Filter: ((prt1_p1.a % 25) = 0)
+ -> Hash
+ Output: prt2_p1.b, prt2_p1.c
+ -> Seq Scan on public.prt2_p1
+ Output: prt2_p1.b, prt2_p1.c
+ Filter: ((prt2_p1.b % 25) = 0)
+ -> Hash
+ Output: prt1_e_p1.a, prt1_e_p1.b, prt1_e_p1.c
+ -> Seq Scan on public.prt1_e_p1
+ Output: prt1_e_p1.a, prt1_e_p1.b, prt1_e_p1.c
+ Filter: ((prt1_e_p1.a % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c, prt1_e_p2.a, prt1_e_p2.b, prt1_e_p2.c
+ Hash Cond: (prt1_p2.a = ((prt1_e_p2.a + prt1_e_p2.b) / 2))
+ -> Hash Full Join
+ Output: prt1_p2.a, prt1_p2.c, prt2_p2.b, prt2_p2.c
+ Hash Cond: (prt1_p2.a = prt2_p2.b)
+ -> Seq Scan on public.prt1_p2
+ Output: prt1_p2.a, prt1_p2.c
+ Filter: ((prt1_p2.a % 25) = 0)
+ -> Hash
+ Output: prt2_p2.b, prt2_p2.c
+ -> Seq Scan on public.prt2_p2
+ Output: prt2_p2.b, prt2_p2.c
+ Filter: ((prt2_p2.b % 25) = 0)
+ -> Hash
+ Output: prt1_e_p2.a, prt1_e_p2.b, prt1_e_p2.c
+ -> Seq Scan on public.prt1_e_p2
+ Output: prt1_e_p2.a, prt1_e_p2.b, prt1_e_p2.c
+ Filter: ((prt1_e_p2.a % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_p3.a, prt1_p3.c, prt2_p3.b, prt2_p3.c, prt1_e_p3.a, prt1_e_p3.b, prt1_e_p3.c
+ Hash Cond: (prt1_p3.a = ((prt1_e_p3.a + prt1_e_p3.b) / 2))
+ -> Hash Full Join
+ Output: prt1_p3.a, prt1_p3.c, prt2_p3.b, prt2_p3.c
+ Hash Cond: (prt1_p3.a = prt2_p3.b)
+ -> Seq Scan on public.prt1_p3
+ Output: prt1_p3.a, prt1_p3.c
+ Filter: ((prt1_p3.a % 25) = 0)
+ -> Hash
+ Output: prt2_p3.b, prt2_p3.c
+ -> Seq Scan on public.prt2_p3
+ Output: prt2_p3.b, prt2_p3.c
+ Filter: ((prt2_p3.b % 25) = 0)
+ -> Hash
+ Output: prt1_e_p3.a, prt1_e_p3.b, prt1_e_p3.c
+ -> Seq Scan on public.prt1_e_p3
+ Output: prt1_e_p3.a, prt1_e_p3.b, prt1_e_p3.c
+ Filter: ((prt1_e_p3.a % 25) = 0)
+(63 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | 100 | 0050
+ 100 | 0100 | | | 200 | 0100
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | 400 | 0200
+ 250 | 0250 | | | 500 | 0250
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | 700 | 0350
+ 400 | 0400 | | | 800 | 0400
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | 1000 | 0500
+ 550 | 0550 | | | 1100 | 0550
+ | | 75 | 0075 | |
+ | | 225 | 0225 | |
+ | | 375 | 0375 | |
+ | | 525 | 0525 | |
+(16 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM uprt1_e WHERE uprt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | 100 | 0050
+ 100 | 0100 | | | 200 | 0100
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | 400 | 0200
+ 250 | 0250 | | | 500 | 0250
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | 700 | 0350
+ 400 | 0400 | | | 800 | 0400
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | 1000 | 0500
+ 550 | 0550 | | | 1100 | 0550
+ | | 75 | 0075 | |
+ | | 225 | 0225 | |
+ | | 375 | 0375 | |
+ | | 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 t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+----------------------------------------------------------------------------------------------------------------------
+ Sort
+ Output: prt1_p1.a, (50), prt2_p1.b, (75), ((prt1_e_p1.a + prt1_e_p1.b)), (50)
+ Sort Key: prt1_p1.a, prt2_p1.b, ((prt1_e_p1.a + prt1_e_p1.b))
+ -> Result
+ Output: prt1_p1.a, (50), prt2_p1.b, (75), (prt1_e_p1.a + prt1_e_p1.b), (50)
+ -> Append
+ -> Hash Full Join
+ Output: prt1_p1.a, prt2_p1.b, prt1_e_p1.a, prt1_e_p1.b, (50), (75), (50)
+ Hash Cond: (prt1_p1.a = ((prt1_e_p1.a + prt1_e_p1.b) / 2))
+ Filter: ((prt1_p1.a = (50)) OR (prt2_p1.b = (75)) OR (((prt1_e_p1.a + prt1_e_p1.b) / 2) = (50)))
+ -> Hash Full Join
+ Output: prt1_p1.a, prt2_p1.b, (50), (75)
+ Hash Cond: (prt1_p1.a = prt2_p1.b)
+ -> Seq Scan on public.prt1_p1
+ Output: prt1_p1.a, 50
+ Filter: ((prt1_p1.a % 25) = 0)
+ -> Hash
+ Output: prt2_p1.b, (75)
+ -> Seq Scan on public.prt2_p1
+ Output: prt2_p1.b, 75
+ Filter: ((prt2_p1.b % 25) = 0)
+ -> Hash
+ Output: prt1_e_p1.a, prt1_e_p1.b, (50)
+ -> Seq Scan on public.prt1_e_p1
+ Output: prt1_e_p1.a, prt1_e_p1.b, 50
+ Filter: ((prt1_e_p1.a % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_p2.a, prt2_p2.b, prt1_e_p2.a, prt1_e_p2.b, (50), (75), (50)
+ Hash Cond: (prt1_p2.a = ((prt1_e_p2.a + prt1_e_p2.b) / 2))
+ Filter: ((prt1_p2.a = (50)) OR (prt2_p2.b = (75)) OR (((prt1_e_p2.a + prt1_e_p2.b) / 2) = (50)))
+ -> Hash Full Join
+ Output: prt1_p2.a, prt2_p2.b, (50), (75)
+ Hash Cond: (prt1_p2.a = prt2_p2.b)
+ -> Seq Scan on public.prt1_p2
+ Output: prt1_p2.a, 50
+ Filter: ((prt1_p2.a % 25) = 0)
+ -> Hash
+ Output: prt2_p2.b, (75)
+ -> Seq Scan on public.prt2_p2
+ Output: prt2_p2.b, 75
+ Filter: ((prt2_p2.b % 25) = 0)
+ -> Hash
+ Output: prt1_e_p2.a, prt1_e_p2.b, (50)
+ -> Seq Scan on public.prt1_e_p2
+ Output: prt1_e_p2.a, prt1_e_p2.b, 50
+ Filter: ((prt1_e_p2.a % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_p3.a, prt2_p3.b, prt1_e_p3.a, prt1_e_p3.b, (50), (75), (50)
+ Hash Cond: (prt1_p3.a = ((prt1_e_p3.a + prt1_e_p3.b) / 2))
+ Filter: ((prt1_p3.a = (50)) OR (prt2_p3.b = (75)) OR (((prt1_e_p3.a + prt1_e_p3.b) / 2) = (50)))
+ -> Hash Full Join
+ Output: prt1_p3.a, prt2_p3.b, (50), (75)
+ Hash Cond: (prt1_p3.a = prt2_p3.b)
+ -> Seq Scan on public.prt1_p3
+ Output: prt1_p3.a, 50
+ Filter: ((prt1_p3.a % 25) = 0)
+ -> Hash
+ Output: prt2_p3.b, (75)
+ -> Seq Scan on public.prt2_p3
+ Output: prt2_p3.b, 75
+ Filter: ((prt2_p3.b % 25) = 0)
+ -> Hash
+ Output: prt1_e_p3.a, prt1_e_p3.b, (50)
+ -> Seq Scan on public.prt1_e_p3
+ Output: prt1_e_p3.a, prt1_e_p3.b, 50
+ Filter: ((prt1_e_p3.a % 25) = 0)
+(66 rows)
+
+SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | phv | b | phv | ?column? | phv
+----+-----+----+-----+----------+-----
+ 50 | 50 | | | 100 | 50
+ | | 75 | 75 | |
+(2 rows)
+
+SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM uprt1_e WHERE uprt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | phv | b | phv | ?column? | phv
+----+-----+----+-----+----------+-----
+ 50 | 50 | | | 100 | 50
+ | | 75 | 75 | |
+(2 rows)
+
+-- Semi-join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.a % 25 = 0 ORDER BY t1.a;
+ QUERY PLAN
+-------------------------------------------------------------------
+ Merge Append
+ Sort Key: t1.a
+ -> Merge Semi Join
+ Output: t1.a, t1.b, t1.c
+ Merge Cond: (t1.a = t1_3.b)
+ -> Sort
+ Output: t1.a, t1.b, t1.c
+ Sort Key: t1.a
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Sort
+ Output: t1_3.b, t2.a, t2.b
+ Sort Key: t1_3.b
+ -> Hash Join
+ Output: t1_3.b, t2.a, t2.b
+ Hash Cond: (((t2.a + t2.b) / 2) = t1_3.b)
+ -> Seq Scan on public.prt1_e_p1 t2
+ Output: t2.a, t2.b
+ -> Hash
+ Output: t1_3.b
+ -> Seq Scan on public.prt2_p1 t1_3
+ Output: t1_3.b
+ Filter: ((t1_3.b % 25) = 0)
+ -> Merge Semi Join
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Merge Cond: (t1_2.a = t1_4.b)
+ -> Sort
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Sort Key: t1_2.a
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Sort
+ Output: t1_4.b, t2_1.a, t2_1.b
+ Sort Key: t1_4.b
+ -> Hash Join
+ Output: t1_4.b, t2_1.a, t2_1.b
+ Hash Cond: (((t2_1.a + t2_1.b) / 2) = t1_4.b)
+ -> Seq Scan on public.prt1_e_p2 t2_1
+ Output: t2_1.a, t2_1.b
+ -> Hash
+ Output: t1_4.b
+ -> Seq Scan on public.prt2_p2 t1_4
+ Output: t1_4.b
+ Filter: ((t1_4.b % 25) = 0)
+ -> Merge Semi Join
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Merge Cond: (t1_1.a = t1_5.b)
+ -> Sort
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Sort Key: t1_1.a
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Sort
+ Output: t1_5.b, t2_2.a, t2_2.b
+ Sort Key: t1_5.b
+ -> Hash Join
+ Output: t1_5.b, t2_2.a, t2_2.b
+ Hash Cond: (((t2_2.a + t2_2.b) / 2) = t1_5.b)
+ -> Seq Scan on public.prt1_e_p3 t2_2
+ Output: t2_2.a, t2_2.b
+ -> Hash
+ Output: t1_5.b
+ -> Seq Scan on public.prt2_p3 t1_5
+ Output: t1_5.b
+ Filter: ((t1_5.b % 25) = 0)
+(68 rows)
+
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) 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)
+
+SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1, uprt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) 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)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+ QUERY PLAN
+-------------------------------------------------------------------
+ Merge Append
+ Sort Key: t1.a
+ -> Merge Semi Join
+ Output: t1.a, t1.b, t1.c
+ Merge Cond: (t1.a = t1_3.b)
+ -> Sort
+ Output: t1.a, t1.b, t1.c
+ Sort Key: t1.a
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Sort
+ Output: t1_3.b, t1_6.a, t1_6.b
+ Sort Key: t1_3.b
+ -> Hash Semi Join
+ Output: t1_3.b, t1_6.a, t1_6.b
+ Hash Cond: (t1_3.b = ((t1_6.a + t1_6.b) / 2))
+ -> Seq Scan on public.prt2_p1 t1_3
+ Output: t1_3.b
+ -> Hash
+ Output: t1_6.a, t1_6.b
+ -> Seq Scan on public.prt1_e_p1 t1_6
+ Output: t1_6.a, t1_6.b
+ Filter: ((t1_6.a % 25) = 0)
+ -> Merge Semi Join
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Merge Cond: (t1_2.a = t1_4.b)
+ -> Sort
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Sort Key: t1_2.a
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Sort
+ Output: t1_4.b, t1_7.a, t1_7.b
+ Sort Key: t1_4.b
+ -> Hash Semi Join
+ Output: t1_4.b, t1_7.a, t1_7.b
+ Hash Cond: (t1_4.b = ((t1_7.a + t1_7.b) / 2))
+ -> Seq Scan on public.prt2_p2 t1_4
+ Output: t1_4.b
+ -> Hash
+ Output: t1_7.a, t1_7.b
+ -> Seq Scan on public.prt1_e_p2 t1_7
+ Output: t1_7.a, t1_7.b
+ Filter: ((t1_7.a % 25) = 0)
+ -> Merge Semi Join
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Merge Cond: (t1_1.a = t1_5.b)
+ -> Sort
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Sort Key: t1_1.a
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Sort
+ Output: t1_5.b, t1_8.a, t1_8.b
+ Sort Key: t1_5.b
+ -> Hash Semi Join
+ Output: t1_5.b, t1_8.a, t1_8.b
+ Hash Cond: (t1_5.b = ((t1_8.a + t1_8.b) / 2))
+ -> Seq Scan on public.prt2_p3 t1_5
+ Output: t1_5.b
+ -> Hash
+ Output: t1_8.a, t1_8.b
+ -> Seq Scan on public.prt1_e_p3 t1_8
+ Output: t1_8.a, t1_8.b
+ Filter: ((t1_8.a % 25) = 0)
+(68 rows)
+
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %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)
+
+SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %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)
+
+-- test merge joins with and without using indexes
+SET enable_hashjoin TO off;
+SET enable_nestloop TO off;
+CREATE INDEX iprt1_p1_a on prt1_p1(a);
+CREATE INDEX iprt1_p2_a on prt1_p2(a);
+CREATE INDEX iprt1_p3_a on prt1_p3(a);
+CREATE INDEX iprt2_p1_b on prt2_p1(b);
+CREATE INDEX iprt2_p2_b on prt2_p2(b);
+CREATE INDEX iprt2_p3_b on prt2_p3(b);
+CREATE INDEX iprt1_e_p1_ab2 on prt1_e_p1(((a+b)/2));
+CREATE INDEX iprt1_e_p2_ab2 on prt1_e_p2(((a+b)/2));
+CREATE INDEX iprt1_e_p3_ab2 on prt1_e_p3(((a+b)/2));
+ANALYZE prt1;
+ANALYZE prt1_p1;
+ANALYZE prt1_p2;
+ANALYZE prt1_p3;
+ANALYZE prt2;
+ANALYZE prt2_p1;
+ANALYZE prt2_p2;
+ANALYZE prt2_p3;
+ANALYZE prt1_e;
+ANALYZE prt1_e_p1;
+ANALYZE prt1_e_p2;
+ANALYZE prt1_e_p3;
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+-----------------------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Merge Left Join
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c, t1.a, t1.c
+ Merge Cond: (t2.b = t1.a)
+ -> Sort
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c
+ Sort Key: t2.b
+ -> Merge Left Join
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c
+ Merge Cond: ((((t3.a + t3.b) / 2)) = t2.b)
+ -> Sort
+ Output: t3.a, t3.b, t3.c, (((t3.a + t3.b) / 2))
+ Sort Key: (((t3.a + t3.b) / 2))
+ -> Seq Scan on public.prt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c, ((t3.a + t3.b) / 2)
+ Filter: ((t3.a % 25) = 0)
+ -> Sort
+ Output: t2.b, t2.c
+ Sort Key: t2.b
+ -> Seq Scan on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Sort
+ Output: t1.a, t1.c
+ Sort Key: t1.a
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ -> Merge Left Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c, t1_2.a, t1_2.c
+ Merge Cond: (t2_1.b = t1_2.a)
+ -> Sort
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c
+ Sort Key: t2_1.b
+ -> Merge Left Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c
+ Merge Cond: ((((t3_1.a + t3_1.b) / 2)) = t2_1.b)
+ -> Sort
+ Output: t3_1.a, t3_1.b, t3_1.c, (((t3_1.a + t3_1.b) / 2))
+ Sort Key: (((t3_1.a + t3_1.b) / 2))
+ -> Seq Scan on public.prt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c, ((t3_1.a + t3_1.b) / 2)
+ Filter: ((t3_1.a % 25) = 0)
+ -> Sort
+ Output: t2_1.b, t2_1.c
+ Sort Key: t2_1.b
+ -> Seq Scan on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Sort
+ Output: t1_2.a, t1_2.c
+ Sort Key: t1_2.a
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ -> Merge Left Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c, t1_1.a, t1_1.c
+ Merge Cond: (t2_2.b = t1_1.a)
+ -> Sort
+ Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c
+ Sort Key: t2_2.b
+ -> Merge Left Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c
+ Merge Cond: ((((t3_2.a + t3_2.b) / 2)) = t2_2.b)
+ -> Sort
+ Output: t3_2.a, t3_2.b, t3_2.c, (((t3_2.a + t3_2.b) / 2))
+ Sort Key: (((t3_2.a + t3_2.b) / 2))
+ -> Seq Scan on public.prt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c, ((t3_2.a + t3_2.b) / 2)
+ Filter: ((t3_2.a % 25) = 0)
+ -> Sort
+ Output: t2_2.b, t2_2.c
+ Sort Key: t2_2.b
+ -> Seq Scan on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Sort
+ Output: t1_1.a, t1_1.c
+ Sort Key: t1_1.a
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+(81 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ | | | | 100 | 0050
+ | | | | 200 | 0100
+ | | | | 400 | 0200
+ | | | | 500 | 0250
+ | | | | 700 | 0350
+ | | | | 800 | 0400
+ | | | | 1000 | 0500
+ | | | | 1100 | 0550
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ | | | | 100 | 0050
+ | | | | 200 | 0100
+ | | | | 400 | 0200
+ | | | | 500 | 0250
+ | | | | 700 | 0350
+ | | | | 800 | 0400
+ | | | | 1000 | 0500
+ | | | | 1100 | 0550
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+ QUERY PLAN
+---------------------------------------------------------------------------------
+ Merge Append
+ Sort Key: t1.a
+ -> Merge Semi Join
+ Output: t1.a, t1.b, t1.c
+ Merge Cond: (t1.a = t1_3.b)
+ -> Sort
+ Output: t1.a, t1.b, t1.c
+ Sort Key: t1.a
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Materialize
+ Output: t1_3.b, t1_6.a, t1_6.b
+ -> Merge Semi Join
+ Output: t1_3.b, t1_6.a, t1_6.b
+ Merge Cond: (t1_3.b = (((t1_6.a + t1_6.b) / 2)))
+ -> Sort
+ Output: t1_3.b
+ Sort Key: t1_3.b
+ -> Seq Scan on public.prt2_p1 t1_3
+ Output: t1_3.b
+ -> Sort
+ Output: t1_6.a, t1_6.b, (((t1_6.a + t1_6.b) / 2))
+ Sort Key: (((t1_6.a + t1_6.b) / 2))
+ -> Seq Scan on public.prt1_e_p1 t1_6
+ Output: t1_6.a, t1_6.b, ((t1_6.a + t1_6.b) / 2)
+ Filter: ((t1_6.a % 25) = 0)
+ -> Merge Semi Join
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Merge Cond: (t1_2.a = t1_4.b)
+ -> Sort
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Sort Key: t1_2.a
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Materialize
+ Output: t1_4.b, t1_7.a, t1_7.b
+ -> Merge Semi Join
+ Output: t1_4.b, t1_7.a, t1_7.b
+ Merge Cond: (t1_4.b = (((t1_7.a + t1_7.b) / 2)))
+ -> Sort
+ Output: t1_4.b
+ Sort Key: t1_4.b
+ -> Seq Scan on public.prt2_p2 t1_4
+ Output: t1_4.b
+ -> Sort
+ Output: t1_7.a, t1_7.b, (((t1_7.a + t1_7.b) / 2))
+ Sort Key: (((t1_7.a + t1_7.b) / 2))
+ -> Seq Scan on public.prt1_e_p2 t1_7
+ Output: t1_7.a, t1_7.b, ((t1_7.a + t1_7.b) / 2)
+ Filter: ((t1_7.a % 25) = 0)
+ -> Merge Semi Join
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Merge Cond: (t1_1.a = t1_5.b)
+ -> Sort
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Sort Key: t1_1.a
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Materialize
+ Output: t1_5.b, t1_8.a, t1_8.b
+ -> Merge Semi Join
+ Output: t1_5.b, t1_8.a, t1_8.b
+ Merge Cond: (t1_5.b = (((t1_8.a + t1_8.b) / 2)))
+ -> Sort
+ Output: t1_5.b
+ Sort Key: t1_5.b
+ -> Seq Scan on public.prt2_p3 t1_5
+ Output: t1_5.b
+ -> Sort
+ Output: t1_8.a, t1_8.b, (((t1_8.a + t1_8.b) / 2))
+ Sort Key: (((t1_8.a + t1_8.b) / 2))
+ -> Seq Scan on public.prt1_e_p3 t1_8
+ Output: t1_8.a, t1_8.b, ((t1_8.a + t1_8.b) / 2)
+ Filter: ((t1_8.a % 25) = 0)
+(77 rows)
+
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %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)
+
+SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %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)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+-----------------------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Merge Left Join
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c, t2.b, t2.c
+ Merge Cond: (t1.a = t2.b)
+ -> Sort
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c
+ Sort Key: t1.a
+ -> Merge Left Join
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c
+ Merge Cond: ((((t3.a + t3.b) / 2)) = t1.a)
+ -> Sort
+ Output: t3.a, t3.b, t3.c, (((t3.a + t3.b) / 2))
+ Sort Key: (((t3.a + t3.b) / 2))
+ -> Seq Scan on public.prt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c, ((t3.a + t3.b) / 2)
+ Filter: ((t3.a % 25) = 0)
+ -> Sort
+ Output: t1.a, t1.c
+ Sort Key: t1.a
+ -> Seq Scan on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ -> Sort
+ Output: t2.b, t2.c
+ Sort Key: t2.b
+ -> Seq Scan on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Merge Left Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ Merge Cond: (t1_2.a = t2_1.b)
+ -> Sort
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c
+ Sort Key: t1_2.a
+ -> Merge Left Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c
+ Merge Cond: ((((t3_1.a + t3_1.b) / 2)) = t1_2.a)
+ -> Sort
+ Output: t3_1.a, t3_1.b, t3_1.c, (((t3_1.a + t3_1.b) / 2))
+ Sort Key: (((t3_1.a + t3_1.b) / 2))
+ -> Seq Scan on public.prt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c, ((t3_1.a + t3_1.b) / 2)
+ Filter: ((t3_1.a % 25) = 0)
+ -> Sort
+ Output: t1_2.a, t1_2.c
+ Sort Key: t1_2.a
+ -> Seq Scan on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ -> Sort
+ Output: t2_1.b, t2_1.c
+ Sort Key: t2_1.b
+ -> Seq Scan on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Merge Left Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ Merge Cond: (t1_1.a = t2_2.b)
+ -> Sort
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c
+ Sort Key: t1_1.a
+ -> Merge Left Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c
+ Merge Cond: ((((t3_2.a + t3_2.b) / 2)) = t1_1.a)
+ -> Sort
+ Output: t3_2.a, t3_2.b, t3_2.c, (((t3_2.a + t3_2.b) / 2))
+ Sort Key: (((t3_2.a + t3_2.b) / 2))
+ -> Seq Scan on public.prt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c, ((t3_2.a + t3_2.b) / 2)
+ Filter: ((t3_2.a % 25) = 0)
+ -> Sort
+ Output: t1_1.a, t1_1.c
+ Sort Key: t1_1.a
+ -> Seq Scan on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ -> Sort
+ Output: t2_2.b, t2_2.c
+ Sort Key: t2_2.b
+ -> Seq Scan on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+(81 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | 100 | 0050
+ 100 | 0100 | | | 200 | 0100
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | 400 | 0200
+ 250 | 0250 | | | 500 | 0250
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | 700 | 0350
+ 400 | 0400 | | | 800 | 0400
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | 1000 | 0500
+ 550 | 0550 | | | 1100 | 0550
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | 100 | 0050
+ 100 | 0100 | | | 200 | 0100
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | 400 | 0200
+ 250 | 0250 | | | 500 | 0250
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | 700 | 0350
+ 400 | 0400 | | | 800 | 0400
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | 1000 | 0500
+ 550 | 0550 | | | 1100 | 0550
+(12 rows)
+
+SET enable_seqscan TO off;
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+----------------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Merge Left Join
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c, t1.a, t1.c
+ Merge Cond: (t2.b = t1.a)
+ -> Sort
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c
+ Sort Key: t2.b
+ -> Merge Left Join
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c
+ Merge Cond: (((t3.a + t3.b) / 2) = t2.b)
+ -> Index Scan using iprt1_e_p1_ab2 on public.prt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ Filter: ((t3.a % 25) = 0)
+ -> Index Scan using iprt2_p1_b on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Index Scan using iprt1_p1_a on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ -> Merge Left Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c, t1_2.a, t1_2.c
+ Merge Cond: (t2_1.b = t1_2.a)
+ -> Sort
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c
+ Sort Key: t2_1.b
+ -> Merge Left Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c
+ Merge Cond: (((t3_1.a + t3_1.b) / 2) = t2_1.b)
+ -> Index Scan using iprt1_e_p2_ab2 on public.prt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ Filter: ((t3_1.a % 25) = 0)
+ -> Index Scan using iprt2_p2_b on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Index Scan using iprt1_p2_a on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ -> Merge Right Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c, t1_1.a, t1_1.c
+ Merge Cond: (t2_2.b = ((t3_2.a + t3_2.b) / 2))
+ -> Merge Left Join
+ Output: t2_2.b, t2_2.c, t1_1.a, t1_1.c
+ Merge Cond: (t2_2.b = t1_1.a)
+ -> Index Scan using iprt2_p3_b on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Index Scan using iprt1_p3_a on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ -> Index Scan using iprt1_e_p3_ab2 on public.prt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ Filter: ((t3_2.a % 25) = 0)
+(51 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ | | | | 100 | 0050
+ | | | | 200 | 0100
+ | | | | 400 | 0200
+ | | | | 500 | 0250
+ | | | | 700 | 0350
+ | | | | 800 | 0400
+ | | | | 1000 | 0500
+ | | | | 1100 | 0550
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ | | | | 100 | 0050
+ | | | | 200 | 0100
+ | | | | 400 | 0200
+ | | | | 500 | 0250
+ | | | | 700 | 0350
+ | | | | 800 | 0400
+ | | | | 1000 | 0500
+ | | | | 1100 | 0550
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+ QUERY PLAN
+----------------------------------------------------------------------------------
+ Merge Append
+ Sort Key: t1.a
+ -> Merge Semi Join
+ Output: t1.a, t1.b, t1.c
+ Merge Cond: (t1.a = t1_3.b)
+ -> Index Scan using iprt1_p1_a on public.prt1_p1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Materialize
+ Output: t1_3.b, t1_6.a, t1_6.b
+ -> Merge Semi Join
+ Output: t1_3.b, t1_6.a, t1_6.b
+ Merge Cond: (t1_3.b = ((t1_6.a + t1_6.b) / 2))
+ -> Index Only Scan using iprt2_p1_b on public.prt2_p1 t1_3
+ Output: t1_3.b
+ -> Index Scan using iprt1_e_p1_ab2 on public.prt1_e_p1 t1_6
+ Output: t1_6.a, t1_6.b
+ Filter: ((t1_6.a % 25) = 0)
+ -> Merge Semi Join
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Merge Cond: (t1_2.a = t1_4.b)
+ -> Index Scan using iprt1_p2_a on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Materialize
+ Output: t1_4.b, t1_7.a, t1_7.b
+ -> Merge Semi Join
+ Output: t1_4.b, t1_7.a, t1_7.b
+ Merge Cond: (t1_4.b = ((t1_7.a + t1_7.b) / 2))
+ -> Index Only Scan using iprt2_p2_b on public.prt2_p2 t1_4
+ Output: t1_4.b
+ -> Index Scan using iprt1_e_p2_ab2 on public.prt1_e_p2 t1_7
+ Output: t1_7.a, t1_7.b
+ Filter: ((t1_7.a % 25) = 0)
+ -> Merge Semi Join
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Merge Cond: (t1_1.a = t1_5.b)
+ -> Index Scan using iprt1_p3_a on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Materialize
+ Output: t1_5.b, t1_8.a, t1_8.b
+ -> Merge Semi Join
+ Output: t1_5.b, t1_8.a, t1_8.b
+ Merge Cond: (t1_5.b = ((t1_8.a + t1_8.b) / 2))
+ -> Index Only Scan using iprt2_p3_b on public.prt2_p3 t1_5
+ Output: t1_5.b
+ -> Index Scan using iprt1_e_p3_ab2 on public.prt1_e_p3 t1_8
+ Output: t1_8.a, t1_8.b
+ Filter: ((t1_8.a % 25) = 0)
+(50 rows)
+
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %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)
+
+SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %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)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+----------------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Merge Left Join
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c, t2.b, t2.c
+ Merge Cond: (t1.a = t2.b)
+ -> Sort
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c
+ Sort Key: t1.a
+ -> Merge Left Join
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c
+ Merge Cond: (((t3.a + t3.b) / 2) = t1.a)
+ -> Index Scan using iprt1_e_p1_ab2 on public.prt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ Filter: ((t3.a % 25) = 0)
+ -> Index Scan using iprt1_p1_a on public.prt1_p1 t1
+ Output: t1.a, t1.c
+ -> Index Scan using iprt2_p1_b on public.prt2_p1 t2
+ Output: t2.b, t2.c
+ -> Merge Left Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c, t2_1.b, t2_1.c
+ Merge Cond: (t1_2.a = t2_1.b)
+ -> Sort
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c
+ Sort Key: t1_2.a
+ -> Merge Left Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_2.a, t1_2.c
+ Merge Cond: (((t3_1.a + t3_1.b) / 2) = t1_2.a)
+ -> Index Scan using iprt1_e_p2_ab2 on public.prt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ Filter: ((t3_1.a % 25) = 0)
+ -> Index Scan using iprt1_p2_a on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.c
+ -> Index Scan using iprt2_p2_b on public.prt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Merge Left Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c, t2_2.b, t2_2.c
+ Merge Cond: (t1_1.a = t2_2.b)
+ -> Sort
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c
+ Sort Key: t1_1.a
+ -> Merge Left Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_1.a, t1_1.c
+ Merge Cond: (((t3_2.a + t3_2.b) / 2) = t1_1.a)
+ -> Index Scan using iprt1_e_p3_ab2 on public.prt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ Filter: ((t3_2.a % 25) = 0)
+ -> Index Scan using iprt1_p3_a on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.c
+ -> Index Scan using iprt2_p3_b on public.prt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+(54 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | 100 | 0050
+ 100 | 0100 | | | 200 | 0100
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | 400 | 0200
+ 250 | 0250 | | | 500 | 0250
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | 700 | 0350
+ 400 | 0400 | | | 800 | 0400
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | 1000 | 0500
+ 550 | 0550 | | | 1100 | 0550
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+------
+ 0 | 0000 | 0 | 0000 | 0 | 0000
+ 50 | 0050 | | | 100 | 0050
+ 100 | 0100 | | | 200 | 0100
+ 150 | 0150 | 150 | 0150 | 300 | 0150
+ 200 | 0200 | | | 400 | 0200
+ 250 | 0250 | | | 500 | 0250
+ 300 | 0300 | 300 | 0300 | 600 | 0300
+ 350 | 0350 | | | 700 | 0350
+ 400 | 0400 | | | 800 | 0400
+ 450 | 0450 | 450 | 0450 | 900 | 0450
+ 500 | 0500 | | | 1000 | 0500
+ 550 | 0550 | | | 1100 | 0550
+(12 rows)
+
+-- lateral references and parameterized paths
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ QUERY PLAN
+-----------------------------------------------------------------------------------------------
+ Result
+ Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a
+ -> Merge Append
+ Sort Key: t1.a
+ -> Nested Loop Left Join
+ Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a))
+ -> Index Scan using iprt1_p1_a on public.prt1_p1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Merge Join
+ Output: t2.a, t3.a, LEAST(t1.a, t2.a, t3.a)
+ Merge Cond: (t2.a = t3.b)
+ -> Index Only Scan using iprt1_p1_a on public.prt1_p1 t2
+ Output: t2.a
+ Index Cond: (t2.a = t1.a)
+ -> Index Scan using iprt2_p1_b on public.prt2_p1 t3
+ Output: t3.a, t3.b
+ -> Nested Loop Left Join
+ Output: t1_2.a, t1_2.b, t1_2.c, t2_2.a, t3_1.a, (LEAST(t1_2.a, t2_2.a, t3_1.a))
+ -> Index Scan using iprt1_p2_a on public.prt1_p2 t1_2
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Merge Join
+ Output: t2_2.a, t3_1.a, LEAST(t1_2.a, t2_2.a, t3_1.a)
+ Merge Cond: (t2_2.a = t3_1.b)
+ -> Index Only Scan using iprt1_p2_a on public.prt1_p2 t2_2
+ Output: t2_2.a
+ Index Cond: (t2_2.a = t1_2.a)
+ -> Index Scan using iprt2_p2_b on public.prt2_p2 t3_1
+ Output: t3_1.a, t3_1.b
+ -> Nested Loop Left Join
+ Output: t1_1.a, t1_1.b, t1_1.c, t2_1.a, t3_2.a, (LEAST(t1_1.a, t2_1.a, t3_2.a))
+ -> Index Scan using iprt1_p3_a on public.prt1_p3 t1_1
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Merge Join
+ Output: t2_1.a, t3_2.a, LEAST(t1_1.a, t2_1.a, t3_2.a)
+ Merge Cond: (t2_1.a = t3_2.b)
+ -> Index Only Scan using iprt1_p3_a on public.prt1_p3 t2_1
+ Output: t2_1.a
+ Index Cond: (t2_1.a = t1_1.a)
+ -> Index Scan using iprt2_p3_b on public.prt2_p3 t3_2
+ Output: t3_2.a, t3_2.b
+(43 rows)
+
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ a | b | c | t2a | t3a | least
+-----+-----+------+-----+-----+-------
+ 0 | 0 | 0000 | 0 | 0 | 0
+ 50 | 50 | 0050 | | |
+ 100 | 100 | 0100 | | |
+ 150 | 150 | 0150 | 150 | 150 | 150
+ 200 | 200 | 0200 | | |
+ 250 | 250 | 0250 | | |
+ 300 | 300 | 0300 | 300 | 300 | 300
+ 350 | 350 | 0350 | | |
+ 400 | 400 | 0400 | | |
+ 450 | 450 | 0450 | 450 | 450 | 450
+ 500 | 500 | 0500 | | |
+ 550 | 550 | 0550 | | |
+(12 rows)
+
+SELECT * FROM uprt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ a | b | c | t2a | t3a | least
+-----+-----+------+-----+-----+-------
+ 0 | 0 | 0000 | 0 | 0 | 0
+ 50 | 50 | 0050 | | |
+ 100 | 100 | 0100 | | |
+ 150 | 150 | 0150 | 150 | 150 | 150
+ 200 | 200 | 0200 | | |
+ 250 | 250 | 0250 | | |
+ 300 | 300 | 0300 | 300 | 300 | 300
+ 350 | 350 | 0350 | | |
+ 400 | 400 | 0400 | | |
+ 450 | 450 | 0450 | 450 | 450 | 450
+ 500 | 500 | 0500 | | |
+ 550 | 550 | 0550 | | |
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ QUERY PLAN
+---------------------------------------------------------------------------
+ Nested Loop Left Join
+ Output: t1.a, t1.b, t1.c, t2.a, t3.a, (LEAST(t1.a, t2.a, t3.a)), t1.a
+ -> Merge Append
+ Sort Key: t1.a
+ -> Sort
+ Output: t1.a, t1.b, t1.c
+ Sort Key: t1.a
+ -> Seq Scan on public.prt1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Index Scan using iprt1_p1_a on public.prt1_p1 t1_1
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Index Scan using iprt1_p3_a on public.prt1_p3 t1_2
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+ -> Index Scan using iprt1_p2_a on public.prt1_p2 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.a, LEAST(t1.a, t2.a, t3.a)
+ Merge Cond: (t2.a = t3.b)
+ -> Index Only Scan using iprt1_p1_a on public.prt1_p1 t2
+ Output: t2.a
+ Index Cond: (t2.a = t1.b)
+ -> Index Scan using iprt2_p1_b on public.prt2_p1 t3
+ Output: t3.a, t3.b
+ -> Merge Join
+ Output: t2_2.a, t3_1.a, LEAST(t1.a, t2_2.a, t3_1.a)
+ Merge Cond: (t2_2.a = t3_1.b)
+ -> Index Only Scan using iprt1_p2_a on public.prt1_p2 t2_2
+ Output: t2_2.a
+ Index Cond: (t2_2.a = t1.b)
+ -> Index Scan using iprt2_p2_b on public.prt2_p2 t3_1
+ Output: t3_1.a, t3_1.b
+ -> Merge Join
+ Output: t2_1.a, t3_2.a, LEAST(t1.a, t2_1.a, t3_2.a)
+ Merge Cond: (t2_1.a = t3_2.b)
+ -> Index Only Scan using iprt1_p3_a on public.prt1_p3 t2_1
+ Output: t2_1.a
+ Index Cond: (t2_1.a = t1.b)
+ -> Index Scan using iprt2_p3_b on public.prt2_p3 t3_2
+ Output: t3_2.a, t3_2.b
+(44 rows)
+
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ a | b | c | t2a | t3a | least
+-----+-----+------+-----+-----+-------
+ 0 | 0 | 0000 | 0 | 0 | 0
+ 50 | 50 | 0050 | | |
+ 100 | 100 | 0100 | | |
+ 150 | 150 | 0150 | 150 | 150 | 150
+ 200 | 200 | 0200 | | |
+ 250 | 250 | 0250 | | |
+ 300 | 300 | 0300 | 300 | 300 | 300
+ 350 | 350 | 0350 | | |
+ 400 | 400 | 0400 | | |
+ 450 | 450 | 0450 | 450 | 450 | 450
+ 500 | 500 | 0500 | | |
+ 550 | 550 | 0550 | | |
+(12 rows)
+
+SELECT * FROM uprt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+ a | b | c | t2a | t3a | least
+-----+-----+------+-----+-----+-------
+ 0 | 0 | 0000 | 0 | 0 | 0
+ 50 | 50 | 0050 | | |
+ 100 | 100 | 0100 | | |
+ 150 | 150 | 0150 | 150 | 150 | 150
+ 200 | 200 | 0200 | | |
+ 250 | 250 | 0250 | | |
+ 300 | 300 | 0300 | 300 | 300 | 300
+ 350 | 350 | 0350 | | |
+ 400 | 400 | 0400 | | |
+ 450 | 450 | 0450 | 450 | 450 | 450
+ 500 | 500 | 0500 | | |
+ 550 | 550 | 0550 | | |
+(12 rows)
+
+RESET enable_hashjoin;
+RESET enable_nestloop;
+RESET enable_seqscan;
+--
+-- partitioned by multiple columns
+--
+CREATE TABLE prt1_m (a int, b int, c varchar) PARTITION BY RANGE(a, ((a + b)/2));
+CREATE TABLE prt1_m_p1 PARTITION OF prt1_m FOR VALUES FROM (0, 0) TO (250, 250);
+CREATE TABLE prt1_m_p2 PARTITION OF prt1_m FOR VALUES FROM (250, 250) TO (500, 500);
+CREATE TABLE prt1_m_p3 PARTITION OF prt1_m FOR VALUES FROM (500, 500) TO (600, 600);
+INSERT INTO prt1_m SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt1_m;
+ANALYZE prt1_m_p1;
+ANALYZE prt1_m_p2;
+ANALYZE prt1_m_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uprt1_m AS SELECT * FROM prt1_m;
+CREATE TABLE prt2_m (a int, b int, c varchar) PARTITION BY RANGE(((b + a)/2), b);
+CREATE TABLE prt2_m_p1 PARTITION OF prt2_m FOR VALUES FROM (0, 0) TO (250, 250);
+CREATE TABLE prt2_m_p2 PARTITION OF prt2_m FOR VALUES FROM (250, 250) TO (500, 500);
+CREATE TABLE prt2_m_p3 PARTITION OF prt2_m FOR VALUES FROM (500, 500) TO (600, 600);
+INSERT INTO prt2_m SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i;
+ANALYZE prt2_m;
+ANALYZE prt2_m_p1;
+ANALYZE prt2_m_p2;
+ANALYZE prt2_m_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uprt2_m AS SELECT * FROM prt2_m;
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 RIGHT JOIN prt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+ QUERY PLAN
+------------------------------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c
+ Sort Key: t1.a, t2.b
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c
+ -> Append
+ -> Hash Right Join
+ Output: t2.b, t2.c, t1.a, t1.c
+ Hash Cond: ((((t1.a + t1.b) / 2) = t2.b) AND (t1.a = ((t2.b + t2.a) / 2)))
+ -> Seq Scan on public.prt1_m_p1 t1
+ Output: t1.a, t1.c, t1.b
+ -> Hash
+ Output: t2.b, t2.c, t2.a
+ -> Seq Scan on public.prt2_m_p1 t2
+ Output: t2.b, t2.c, t2.a
+ Filter: ((t2.b % 25) = 0)
+ -> Hash Right Join
+ Output: t2_1.b, t2_1.c, t1_1.a, t1_1.c
+ Hash Cond: ((((t1_1.a + t1_1.b) / 2) = t2_1.b) AND (t1_1.a = ((t2_1.b + t2_1.a) / 2)))
+ -> Seq Scan on public.prt1_m_p2 t1_1
+ Output: t1_1.a, t1_1.c, t1_1.b
+ -> Hash
+ Output: t2_1.b, t2_1.c, t2_1.a
+ -> Seq Scan on public.prt2_m_p2 t2_1
+ Output: t2_1.b, t2_1.c, t2_1.a
+ Filter: ((t2_1.b % 25) = 0)
+ -> Hash Right Join
+ Output: t2_2.b, t2_2.c, t1_2.a, t1_2.c
+ Hash Cond: ((((t1_2.a + t1_2.b) / 2) = t2_2.b) AND (t1_2.a = ((t2_2.b + t2_2.a) / 2)))
+ -> Seq Scan on public.prt1_m_p3 t1_2
+ Output: t1_2.a, t1_2.c, t1_2.b
+ -> Hash
+ Output: t2_2.b, t2_2.c, t2_2.a
+ -> Seq Scan on public.prt2_m_p3 t2_2
+ Output: t2_2.b, t2_2.c, t2_2.a
+ Filter: ((t2_2.b % 25) = 0)
+(36 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 RIGHT JOIN prt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150
+ 300 | 0300 | 300 | 0300
+ 450 | 0450 | 450 | 0450
+ | | 75 | 0075
+ | | 225 | 0225
+ | | 375 | 0375
+ | | 525 | 0525
+(8 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_m t1 RIGHT JOIN uprt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 150 | 0150 | 150 | 0150
+ 300 | 0300 | 300 | 0300
+ 450 | 0450 | 450 | 0450
+ | | 75 | 0075
+ | | 225 | 0225
+ | | 375 | 0375
+ | | 525 | 0525
+(8 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b;
+ QUERY PLAN
+------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+ Output: prt1_m_p1.a, prt1_m_p1.c, prt2_m_p1.b, prt2_m_p1.c
+ Sort Key: prt1_m_p1.a, prt2_m_p1.b
+ -> Append
+ -> Hash Full Join
+ Output: prt1_m_p1.a, prt1_m_p1.c, prt2_m_p1.b, prt2_m_p1.c
+ Hash Cond: ((prt1_m_p1.a = ((prt2_m_p1.b + prt2_m_p1.a) / 2)) AND (((prt1_m_p1.a + prt1_m_p1.b) / 2) = prt2_m_p1.b))
+ -> Seq Scan on public.prt1_m_p1
+ Output: prt1_m_p1.a, prt1_m_p1.c, prt1_m_p1.b
+ Filter: ((prt1_m_p1.a % 25) = 0)
+ -> Hash
+ Output: prt2_m_p1.b, prt2_m_p1.c, prt2_m_p1.a
+ -> Seq Scan on public.prt2_m_p1
+ Output: prt2_m_p1.b, prt2_m_p1.c, prt2_m_p1.a
+ Filter: ((prt2_m_p1.b % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_m_p2.a, prt1_m_p2.c, prt2_m_p2.b, prt2_m_p2.c
+ Hash Cond: ((prt1_m_p2.a = ((prt2_m_p2.b + prt2_m_p2.a) / 2)) AND (((prt1_m_p2.a + prt1_m_p2.b) / 2) = prt2_m_p2.b))
+ -> Seq Scan on public.prt1_m_p2
+ Output: prt1_m_p2.a, prt1_m_p2.c, prt1_m_p2.b
+ Filter: ((prt1_m_p2.a % 25) = 0)
+ -> Hash
+ Output: prt2_m_p2.b, prt2_m_p2.c, prt2_m_p2.a
+ -> Seq Scan on public.prt2_m_p2
+ Output: prt2_m_p2.b, prt2_m_p2.c, prt2_m_p2.a
+ Filter: ((prt2_m_p2.b % 25) = 0)
+ -> Hash Full Join
+ Output: prt1_m_p3.a, prt1_m_p3.c, prt2_m_p3.b, prt2_m_p3.c
+ Hash Cond: ((prt1_m_p3.a = ((prt2_m_p3.b + prt2_m_p3.a) / 2)) AND (((prt1_m_p3.a + prt1_m_p3.b) / 2) = prt2_m_p3.b))
+ -> Seq Scan on public.prt1_m_p3
+ Output: prt1_m_p3.a, prt1_m_p3.c, prt1_m_p3.b
+ Filter: ((prt1_m_p3.a % 25) = 0)
+ -> Hash
+ Output: prt2_m_p3.b, prt2_m_p3.c, prt2_m_p3.a
+ -> Seq Scan on public.prt2_m_p3
+ Output: prt2_m_p3.b, prt2_m_p3.c, prt2_m_p3.a
+ Filter: ((prt2_m_p3.b % 25) = 0)
+(37 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 50 | 0050 | |
+ 100 | 0100 | |
+ 150 | 0150 | 150 | 0150
+ 200 | 0200 | |
+ 250 | 0250 | |
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 | |
+ 400 | 0400 | |
+ 450 | 0450 | 450 | 0450
+ 500 | 0500 | |
+ 550 | 0550 | |
+ | | 75 | 0075
+ | | 225 | 0225
+ | | 375 | 0375
+ | | 525 | 0525
+(16 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_m t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2_m t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b;
+ a | c | b | c
+-----+------+-----+------
+ 0 | 0000 | 0 | 0000
+ 50 | 0050 | |
+ 100 | 0100 | |
+ 150 | 0150 | 150 | 0150
+ 200 | 0200 | |
+ 250 | 0250 | |
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 | |
+ 400 | 0400 | |
+ 450 | 0450 | 450 | 0450
+ 500 | 0500 | |
+ 550 | 0550 | |
+ | | 75 | 0075
+ | | 225 | 0225
+ | | 375 | 0375
+ | | 525 | 0525
+(16 rows)
+
+--
+-- tests for list partitioned tables.
+--
+CREATE TABLE plt1 (a int, b int, c text) PARTITION BY LIST(c);
+CREATE TABLE plt1_p1 PARTITION OF plt1 FOR VALUES IN ('0000', '0003', '0004', '0010');
+CREATE TABLE plt1_p2 PARTITION OF plt1 FOR VALUES IN ('0001', '0005', '0002', '0009');
+CREATE TABLE plt1_p3 PARTITION OF plt1 FOR VALUES IN ('0006', '0007', '0008', '0011');
+INSERT INTO plt1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE plt1;
+ANALYZE plt1_p1;
+ANALYZE plt1_p2;
+ANALYZE plt1_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uplt1 AS SELECT * FROM plt1;
+CREATE TABLE plt2 (a int, b int, c text) PARTITION BY LIST(c);
+CREATE TABLE plt2_p1 PARTITION OF plt2 FOR VALUES IN ('0000', '0003', '0004', '0010');
+CREATE TABLE plt2_p2 PARTITION OF plt2 FOR VALUES IN ('0001', '0005', '0002', '0009');
+CREATE TABLE plt2_p3 PARTITION OF plt2 FOR VALUES IN ('0006', '0007', '0008', '0011');
+INSERT INTO plt2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 3) i;
+ANALYZE plt2;
+ANALYZE plt2_p1;
+ANALYZE plt2_p2;
+ANALYZE plt2_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uplt2 AS SELECT * FROM plt2;
+--
+-- list partitioned by expression
+--
+CREATE TABLE plt1_e (a int, b int, c text) PARTITION BY LIST(ltrim(c, 'A'));
+CREATE TABLE plt1_e_p1 PARTITION OF plt1_e FOR VALUES IN ('0000', '0003', '0004', '0010');
+CREATE TABLE plt1_e_p2 PARTITION OF plt1_e FOR VALUES IN ('0001', '0005', '0002', '0009');
+CREATE TABLE plt1_e_p3 PARTITION OF plt1_e FOR VALUES IN ('0006', '0007', '0008', '0011');
+INSERT INTO plt1_e SELECT i, i, 'A' || to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE plt1_e;
+ANALYZE plt1_e_p1;
+ANALYZE plt1_e_p2;
+ANALYZE plt1_e_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uplt1_e AS SELECT * FROM plt1_e;
+--
+-- N-way join
+--
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c;
+ QUERY PLAN
+------------------------------------------------------------------------------------------
+ Sort
+ Output: (avg(t1.a)), (avg(t2.b)), (avg((t3.a + t3.b))), t1.c, t2.c, t3.c
+ Sort Key: t1.c, t3.c
+ -> HashAggregate
+ Output: avg(t1.a), avg(t2.b), avg((t3.a + t3.b)), t1.c, t2.c, t3.c
+ Group Key: t1.c, t2.c, t3.c
+ -> Result
+ Output: t1.c, t2.c, t3.c, t1.a, t2.b, t3.a, t3.b
+ -> Append
+ -> Hash Join
+ Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c
+ Hash Cond: (t1.c = t2.c)
+ -> Seq Scan on public.plt1_p1 t1
+ Output: t1.a, t1.c
+ -> Hash
+ Output: t2.b, t2.c, t3.a, t3.b, t3.c
+ -> Hash Join
+ Output: t2.b, t2.c, t3.a, t3.b, t3.c
+ Hash Cond: (t2.c = ltrim(t3.c, 'A'::text))
+ -> Seq Scan on public.plt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t3.a, t3.b, t3.c
+ -> Seq Scan on public.plt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ -> Hash Join
+ Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c
+ Hash Cond: (t1_1.c = t2_1.c)
+ -> Seq Scan on public.plt1_p2 t1_1
+ Output: t1_1.a, t1_1.c
+ -> Hash
+ Output: t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c
+ -> Hash Join
+ Output: t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c
+ Hash Cond: (t2_1.c = ltrim(t3_1.c, 'A'::text))
+ -> Seq Scan on public.plt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Seq Scan on public.plt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Hash Join
+ Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c
+ Hash Cond: (t1_2.c = t2_2.c)
+ -> Seq Scan on public.plt1_p3 t1_2
+ Output: t1_2.a, t1_2.c
+ -> Hash
+ Output: t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c
+ -> Hash Join
+ Output: t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c
+ Hash Cond: (t2_2.c = ltrim(t3_2.c, 'A'::text))
+ -> Seq Scan on public.plt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t3_2.a, t3_2.b, t3_2.c
+ -> Seq Scan on public.plt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+(57 rows)
+
+SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c;
+ avg | avg | avg | c | c | c
+----------------------+----------------------+-----------------------+------+------+-------
+ 24.0000000000000000 | 24.0000000000000000 | 48.0000000000000000 | 0000 | 0000 | A0000
+ 74.0000000000000000 | 75.0000000000000000 | 148.0000000000000000 | 0001 | 0001 | A0001
+ 124.0000000000000000 | 124.5000000000000000 | 248.0000000000000000 | 0002 | 0002 | A0002
+ 174.0000000000000000 | 174.0000000000000000 | 348.0000000000000000 | 0003 | 0003 | A0003
+ 224.0000000000000000 | 225.0000000000000000 | 448.0000000000000000 | 0004 | 0004 | A0004
+ 274.0000000000000000 | 274.5000000000000000 | 548.0000000000000000 | 0005 | 0005 | A0005
+ 324.0000000000000000 | 324.0000000000000000 | 648.0000000000000000 | 0006 | 0006 | A0006
+ 374.0000000000000000 | 375.0000000000000000 | 748.0000000000000000 | 0007 | 0007 | A0007
+ 424.0000000000000000 | 424.5000000000000000 | 848.0000000000000000 | 0008 | 0008 | A0008
+ 474.0000000000000000 | 474.0000000000000000 | 948.0000000000000000 | 0009 | 0009 | A0009
+ 524.0000000000000000 | 525.0000000000000000 | 1048.0000000000000000 | 0010 | 0010 | A0010
+ 574.0000000000000000 | 574.5000000000000000 | 1148.0000000000000000 | 0011 | 0011 | A0011
+(12 rows)
+
+SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM uplt1 t1, uplt2 t2, uplt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c;
+ avg | avg | avg | c | c | c
+----------------------+----------------------+-----------------------+------+------+-------
+ 24.0000000000000000 | 24.0000000000000000 | 48.0000000000000000 | 0000 | 0000 | A0000
+ 74.0000000000000000 | 75.0000000000000000 | 148.0000000000000000 | 0001 | 0001 | A0001
+ 124.0000000000000000 | 124.5000000000000000 | 248.0000000000000000 | 0002 | 0002 | A0002
+ 174.0000000000000000 | 174.0000000000000000 | 348.0000000000000000 | 0003 | 0003 | A0003
+ 224.0000000000000000 | 225.0000000000000000 | 448.0000000000000000 | 0004 | 0004 | A0004
+ 274.0000000000000000 | 274.5000000000000000 | 548.0000000000000000 | 0005 | 0005 | A0005
+ 324.0000000000000000 | 324.0000000000000000 | 648.0000000000000000 | 0006 | 0006 | A0006
+ 374.0000000000000000 | 375.0000000000000000 | 748.0000000000000000 | 0007 | 0007 | A0007
+ 424.0000000000000000 | 424.5000000000000000 | 848.0000000000000000 | 0008 | 0008 | A0008
+ 474.0000000000000000 | 474.0000000000000000 | 948.0000000000000000 | 0009 | 0009 | A0009
+ 524.0000000000000000 | 525.0000000000000000 | 1048.0000000000000000 | 0010 | 0010 | A0010
+ 574.0000000000000000 | 574.5000000000000000 | 1148.0000000000000000 | 0011 | 0011 | A0011
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+--------------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Hash Right Join
+ Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c
+ Hash Cond: ((t3.a = t1.a) AND (ltrim(t3.c, 'A'::text) = t1.c))
+ -> Seq Scan on public.plt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ -> Hash
+ Output: t1.a, t1.c, t2.b, t2.c
+ -> Hash Right Join
+ Output: t1.a, t1.c, t2.b, t2.c
+ Hash Cond: ((t2.b = t1.a) AND (t2.c = t1.c))
+ -> Seq Scan on public.plt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t1.a, t1.c
+ -> Seq Scan on public.plt1_p1 t1
+ Output: t1.a, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c
+ Hash Cond: ((t3_1.a = t1_1.a) AND (ltrim(t3_1.c, 'A'::text) = t1_1.c))
+ -> Seq Scan on public.plt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Hash
+ Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c
+ -> 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.c = t1_1.c))
+ -> Seq Scan on public.plt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t1_1.a, t1_1.c
+ -> Seq Scan on public.plt1_p2 t1_1
+ Output: t1_1.a, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c
+ Hash Cond: ((t3_2.a = t1_2.a) AND (ltrim(t3_2.c, 'A'::text) = t1_2.c))
+ -> Seq Scan on public.plt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ -> Hash
+ Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c
+ -> 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.c = t1_2.c))
+ -> Seq Scan on public.plt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t1_2.a, t1_2.c
+ -> Seq Scan on public.plt1_p3 t1_2
+ Output: t1_2.a, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+(57 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+-------
+ 0 | 0000 | 0 | 0000 | 0 | A0000
+ 50 | 0001 | | | 100 | A0001
+ 100 | 0002 | | | 200 | A0002
+ 150 | 0003 | 150 | 0003 | 300 | A0003
+ 200 | 0004 | | | 400 | A0004
+ 250 | 0005 | | | 500 | A0005
+ 300 | 0006 | 300 | 0006 | 600 | A0006
+ 350 | 0007 | | | 700 | A0007
+ 400 | 0008 | | | 800 | A0008
+ 450 | 0009 | 450 | 0009 | 900 | A0009
+ 500 | 0010 | | | 1000 | A0010
+ 550 | 0011 | | | 1100 | A0011
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN uplt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+-------
+ 0 | 0000 | 0 | 0000 | 0 | A0000
+ 50 | 0001 | | | 100 | A0001
+ 100 | 0002 | | | 200 | A0002
+ 150 | 0003 | 150 | 0003 | 300 | A0003
+ 200 | 0004 | | | 400 | A0004
+ 250 | 0005 | | | 500 | A0005
+ 300 | 0006 | 300 | 0006 | 600 | A0006
+ 350 | 0007 | | | 700 | A0007
+ 400 | 0008 | | | 800 | A0008
+ 450 | 0009 | 450 | 0009 | 900 | A0009
+ 500 | 0010 | | | 1000 | A0010
+ 550 | 0011 | | | 1100 | A0011
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+--------------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Hash Right Join
+ Output: t1.a, t1.c, t2.b, t2.c, t3.a, t3.b, t3.c
+ Hash Cond: ((t3.a = t2.b) AND (ltrim(t3.c, 'A'::text) = t2.c))
+ -> Seq Scan on public.plt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ -> Hash
+ Output: t1.a, t1.c, t2.b, t2.c
+ -> Hash Right Join
+ Output: t1.a, t1.c, t2.b, t2.c
+ Hash Cond: ((t2.b = t1.a) AND (t2.c = t1.c))
+ -> Seq Scan on public.plt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t1.a, t1.c
+ -> Seq Scan on public.plt1_p1 t1
+ Output: t1.a, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c, t3_1.a, t3_1.b, t3_1.c
+ Hash Cond: ((t3_1.a = t2_1.b) AND (ltrim(t3_1.c, 'A'::text) = t2_1.c))
+ -> Seq Scan on public.plt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Hash
+ Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c
+ -> 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.c = t1_1.c))
+ -> Seq Scan on public.plt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t1_1.a, t1_1.c
+ -> Seq Scan on public.plt1_p2 t1_1
+ Output: t1_1.a, t1_1.c
+ Filter: ((t1_1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c, t3_2.a, t3_2.b, t3_2.c
+ Hash Cond: ((t3_2.a = t2_2.b) AND (ltrim(t3_2.c, 'A'::text) = t2_2.c))
+ -> Seq Scan on public.plt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ -> Hash
+ Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c
+ -> 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.c = t1_2.c))
+ -> Seq Scan on public.plt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t1_2.a, t1_2.c
+ -> Seq Scan on public.plt1_p3 t1_2
+ Output: t1_2.a, t1_2.c
+ Filter: ((t1_2.a % 25) = 0)
+(57 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+-------
+ 0 | 0000 | 0 | 0000 | 0 | A0000
+ 50 | 0001 | | | |
+ 100 | 0002 | | | |
+ 150 | 0003 | 150 | 0003 | 300 | A0003
+ 200 | 0004 | | | |
+ 250 | 0005 | | | |
+ 300 | 0006 | 300 | 0006 | 600 | A0006
+ 350 | 0007 | | | |
+ 400 | 0008 | | | |
+ 450 | 0009 | 450 | 0009 | 900 | A0009
+ 500 | 0010 | | | |
+ 550 | 0011 | | | |
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN uplt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+-------
+ 0 | 0000 | 0 | 0000 | 0 | A0000
+ 50 | 0001 | | | |
+ 100 | 0002 | | | |
+ 150 | 0003 | 150 | 0003 | 300 | A0003
+ 200 | 0004 | | | |
+ 250 | 0005 | | | |
+ 300 | 0006 | 300 | 0006 | 600 | A0006
+ 350 | 0007 | | | |
+ 400 | 0008 | | | |
+ 450 | 0009 | 450 | 0009 | 900 | A0009
+ 500 | 0010 | | | |
+ 550 | 0011 | | | |
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+--------------------------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Hash Right Join
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c, t2.b, t2.c
+ Hash Cond: ((t2.b = t1.a) AND (t2.c = t1.c))
+ -> Seq Scan on public.plt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c
+ -> Hash Right Join
+ Output: t3.a, t3.b, t3.c, t1.a, t1.c
+ Hash Cond: ((t1.c = ltrim(t3.c, 'A'::text)) AND (t1.a = t3.a))
+ -> Seq Scan on public.plt1_p1 t1
+ Output: t1.a, t1.c
+ -> Hash
+ Output: t3.a, t3.b, t3.c
+ -> Seq Scan on public.plt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ Filter: ((t3.a % 25) = 0)
+ -> Hash Right Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_1.a, t1_1.c, t2_1.b, t2_1.c
+ Hash Cond: ((t2_1.b = t1_1.a) AND (t2_1.c = t1_1.c))
+ -> Seq Scan on public.plt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_1.a, t1_1.c
+ -> Hash Right Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t1_1.a, t1_1.c
+ Hash Cond: ((t1_1.c = ltrim(t3_1.c, 'A'::text)) AND (t1_1.a = t3_1.a))
+ -> Seq Scan on public.plt1_p2 t1_1
+ Output: t1_1.a, t1_1.c
+ -> Hash
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Seq Scan on public.plt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ Filter: ((t3_1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_2.a, t1_2.c, t2_2.b, t2_2.c
+ Hash Cond: ((t2_2.b = t1_2.a) AND (t2_2.c = t1_2.c))
+ -> Seq Scan on public.plt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_2.a, t1_2.c
+ -> Hash Right Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t1_2.a, t1_2.c
+ Hash Cond: ((t1_2.c = ltrim(t3_2.c, 'A'::text)) AND (t1_2.a = t3_2.a))
+ -> Seq Scan on public.plt1_p3 t1_2
+ Output: t1_2.a, t1_2.c
+ -> Hash
+ Output: t3_2.a, t3_2.b, t3_2.c
+ -> Seq Scan on public.plt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ Filter: ((t3_2.a % 25) = 0)
+(57 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+-------
+ 0 | 0000 | 0 | 0000 | 0 | A0000
+ 50 | 0001 | | | 100 | A0001
+ 100 | 0002 | | | 200 | A0002
+ 150 | 0003 | 150 | 0003 | 300 | A0003
+ 200 | 0004 | | | 400 | A0004
+ 250 | 0005 | | | 500 | A0005
+ 300 | 0006 | 300 | 0006 | 600 | A0006
+ 350 | 0007 | | | 700 | A0007
+ 400 | 0008 | | | 800 | A0008
+ 450 | 0009 | 450 | 0009 | 900 | A0009
+ 500 | 0010 | | | 1000 | A0010
+ 550 | 0011 | | | 1100 | A0011
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN uplt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+-------
+ 0 | 0000 | 0 | 0000 | 0 | A0000
+ 50 | 0001 | | | 100 | A0001
+ 100 | 0002 | | | 200 | A0002
+ 150 | 0003 | 150 | 0003 | 300 | A0003
+ 200 | 0004 | | | 400 | A0004
+ 250 | 0005 | | | 500 | A0005
+ 300 | 0006 | 300 | 0006 | 600 | A0006
+ 350 | 0007 | | | 700 | A0007
+ 400 | 0008 | | | 800 | A0008
+ 450 | 0009 | 450 | 0009 | 900 | A0009
+ 500 | 0010 | | | 1000 | A0010
+ 550 | 0011 | | | 1100 | A0011
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+--------------------------------------------------------------------------------------------------------
+ Sort
+ Output: t1.a, t1.c, t2.b, t2.c, ((t3.a + t3.b)), t3.c
+ Sort Key: t1.a, t2.b, ((t3.a + t3.b))
+ -> Result
+ Output: t1.a, t1.c, t2.b, t2.c, (t3.a + t3.b), t3.c
+ -> Append
+ -> Hash Right Join
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c, t1.a, t1.c
+ Hash Cond: ((t1.a = t2.b) AND (t1.c = t2.c))
+ -> Seq Scan on public.plt1_p1 t1
+ Output: t1.a, t1.c
+ -> Hash
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c
+ -> Hash Right Join
+ Output: t3.a, t3.b, t3.c, t2.b, t2.c
+ Hash Cond: ((t2.b = t3.a) AND (t2.c = ltrim(t3.c, 'A'::text)))
+ -> Seq Scan on public.plt2_p1 t2
+ Output: t2.b, t2.c
+ -> Hash
+ Output: t3.a, t3.b, t3.c
+ -> Seq Scan on public.plt1_e_p1 t3
+ Output: t3.a, t3.b, t3.c
+ Filter: ((t3.a % 25) = 0)
+ -> Hash Right Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c, t1_1.a, t1_1.c
+ Hash Cond: ((t1_1.a = t2_1.b) AND (t1_1.c = t2_1.c))
+ -> Seq Scan on public.plt1_p2 t1_1
+ Output: t1_1.a, t1_1.c
+ -> Hash
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c
+ -> Hash Right Join
+ Output: t3_1.a, t3_1.b, t3_1.c, t2_1.b, t2_1.c
+ Hash Cond: ((t2_1.b = t3_1.a) AND (t2_1.c = ltrim(t3_1.c, 'A'::text)))
+ -> Seq Scan on public.plt2_p2 t2_1
+ Output: t2_1.b, t2_1.c
+ -> Hash
+ Output: t3_1.a, t3_1.b, t3_1.c
+ -> Seq Scan on public.plt1_e_p2 t3_1
+ Output: t3_1.a, t3_1.b, t3_1.c
+ Filter: ((t3_1.a % 25) = 0)
+ -> Hash Right Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c, t1_2.a, t1_2.c
+ Hash Cond: ((t1_2.a = t2_2.b) AND (t1_2.c = t2_2.c))
+ -> Seq Scan on public.plt1_p3 t1_2
+ Output: t1_2.a, t1_2.c
+ -> Hash
+ Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c
+ -> Hash Right Join
+ Output: t3_2.a, t3_2.b, t3_2.c, t2_2.b, t2_2.c
+ Hash Cond: ((t2_2.b = t3_2.a) AND (t2_2.c = ltrim(t3_2.c, 'A'::text)))
+ -> Seq Scan on public.plt2_p3 t2_2
+ Output: t2_2.b, t2_2.c
+ -> Hash
+ Output: t3_2.a, t3_2.b, t3_2.c
+ -> Seq Scan on public.plt1_e_p3 t3_2
+ Output: t3_2.a, t3_2.b, t3_2.c
+ Filter: ((t3_2.a % 25) = 0)
+(57 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+-------
+ 0 | 0000 | 0 | 0000 | 0 | A0000
+ 150 | 0003 | 150 | 0003 | 300 | A0003
+ 300 | 0006 | 300 | 0006 | 600 | A0006
+ 450 | 0009 | 450 | 0009 | 900 | A0009
+ | | | | 100 | A0001
+ | | | | 200 | A0002
+ | | | | 400 | A0004
+ | | | | 500 | A0005
+ | | | | 700 | A0007
+ | | | | 800 | A0008
+ | | | | 1000 | A0010
+ | | | | 1100 | A0011
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 RIGHT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN uplt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+-------
+ 0 | 0000 | 0 | 0000 | 0 | A0000
+ 150 | 0003 | 150 | 0003 | 300 | A0003
+ 300 | 0006 | 300 | 0006 | 600 | A0006
+ 450 | 0009 | 450 | 0009 | 900 | A0009
+ | | | | 100 | A0001
+ | | | | 200 | A0002
+ | | | | 400 | A0004
+ | | | | 500 | A0005
+ | | | | 700 | A0007
+ | | | | 800 | A0008
+ | | | | 1000 | A0010
+ | | | | 1100 | A0011
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b;
+ QUERY PLAN
+---------------------------------------------------------------------------------------------------------------
+ Sort
+ Output: plt1_p1.a, plt1_p1.c, plt2_p1.b, plt2_p1.c, ((plt1_e_p1.a + plt1_e_p1.b)), plt1_e_p1.c
+ Sort Key: plt1_p1.a, plt2_p1.b, ((plt1_e_p1.a + plt1_e_p1.b))
+ -> Result
+ Output: plt1_p1.a, plt1_p1.c, plt2_p1.b, plt2_p1.c, (plt1_e_p1.a + plt1_e_p1.b), plt1_e_p1.c
+ -> Append
+ -> Hash Full Join
+ Output: plt1_p1.a, plt1_p1.c, plt2_p1.b, plt2_p1.c, plt1_e_p1.a, plt1_e_p1.b, plt1_e_p1.c
+ Hash Cond: ((plt1_p1.a = plt1_e_p1.a) AND (plt1_p1.c = ltrim(plt1_e_p1.c, 'A'::text)))
+ -> Hash Full Join
+ Output: plt1_p1.a, plt1_p1.c, plt2_p1.b, plt2_p1.c
+ Hash Cond: ((plt1_p1.a = plt2_p1.b) AND (plt1_p1.c = plt2_p1.c))
+ -> Seq Scan on public.plt1_p1
+ Output: plt1_p1.a, plt1_p1.c
+ Filter: ((plt1_p1.a % 25) = 0)
+ -> Hash
+ Output: plt2_p1.b, plt2_p1.c
+ -> Seq Scan on public.plt2_p1
+ Output: plt2_p1.b, plt2_p1.c
+ Filter: ((plt2_p1.b % 25) = 0)
+ -> Hash
+ Output: plt1_e_p1.a, plt1_e_p1.b, plt1_e_p1.c
+ -> Seq Scan on public.plt1_e_p1
+ Output: plt1_e_p1.a, plt1_e_p1.b, plt1_e_p1.c
+ Filter: ((plt1_e_p1.a % 25) = 0)
+ -> Hash Full Join
+ Output: plt1_p2.a, plt1_p2.c, plt2_p2.b, plt2_p2.c, plt1_e_p2.a, plt1_e_p2.b, plt1_e_p2.c
+ Hash Cond: ((plt1_p2.a = plt1_e_p2.a) AND (plt1_p2.c = ltrim(plt1_e_p2.c, 'A'::text)))
+ -> Hash Full Join
+ Output: plt1_p2.a, plt1_p2.c, plt2_p2.b, plt2_p2.c
+ Hash Cond: ((plt1_p2.a = plt2_p2.b) AND (plt1_p2.c = plt2_p2.c))
+ -> Seq Scan on public.plt1_p2
+ Output: plt1_p2.a, plt1_p2.c
+ Filter: ((plt1_p2.a % 25) = 0)
+ -> Hash
+ Output: plt2_p2.b, plt2_p2.c
+ -> Seq Scan on public.plt2_p2
+ Output: plt2_p2.b, plt2_p2.c
+ Filter: ((plt2_p2.b % 25) = 0)
+ -> Hash
+ Output: plt1_e_p2.a, plt1_e_p2.b, plt1_e_p2.c
+ -> Seq Scan on public.plt1_e_p2
+ Output: plt1_e_p2.a, plt1_e_p2.b, plt1_e_p2.c
+ Filter: ((plt1_e_p2.a % 25) = 0)
+ -> Hash Full Join
+ Output: plt1_p3.a, plt1_p3.c, plt2_p3.b, plt2_p3.c, plt1_e_p3.a, plt1_e_p3.b, plt1_e_p3.c
+ Hash Cond: ((plt1_p3.a = plt1_e_p3.a) AND (plt1_p3.c = ltrim(plt1_e_p3.c, 'A'::text)))
+ -> Hash Full Join
+ Output: plt1_p3.a, plt1_p3.c, plt2_p3.b, plt2_p3.c
+ Hash Cond: ((plt1_p3.a = plt2_p3.b) AND (plt1_p3.c = plt2_p3.c))
+ -> Seq Scan on public.plt1_p3
+ Output: plt1_p3.a, plt1_p3.c
+ Filter: ((plt1_p3.a % 25) = 0)
+ -> Hash
+ Output: plt2_p3.b, plt2_p3.c
+ -> Seq Scan on public.plt2_p3
+ Output: plt2_p3.b, plt2_p3.c
+ Filter: ((plt2_p3.b % 25) = 0)
+ -> Hash
+ Output: plt1_e_p3.a, plt1_e_p3.b, plt1_e_p3.c
+ -> Seq Scan on public.plt1_e_p3
+ Output: plt1_e_p3.a, plt1_e_p3.b, plt1_e_p3.c
+ Filter: ((plt1_e_p3.a % 25) = 0)
+(63 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+-------
+ 0 | 0000 | 0 | 0000 | 0 | A0000
+ 50 | 0001 | | | 100 | A0001
+ 100 | 0002 | | | 200 | A0002
+ 150 | 0003 | 150 | 0003 | 300 | A0003
+ 200 | 0004 | | | 400 | A0004
+ 250 | 0005 | | | 500 | A0005
+ 300 | 0006 | 300 | 0006 | 600 | A0006
+ 350 | 0007 | | | 700 | A0007
+ 400 | 0008 | | | 800 | A0008
+ 450 | 0009 | 450 | 0009 | 900 | A0009
+ 500 | 0010 | | | 1000 | A0010
+ 550 | 0011 | | | 1100 | A0011
+ | | 75 | 0001 | |
+ | | 225 | 0004 | |
+ | | 375 | 0007 | |
+ | | 525 | 0010 | |
+(16 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM uplt1 WHERE uplt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uplt2 WHERE uplt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM uplt1_e WHERE uplt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b;
+ a | c | b | c | ?column? | c
+-----+------+-----+------+----------+-------
+ 0 | 0000 | 0 | 0000 | 0 | A0000
+ 50 | 0001 | | | 100 | A0001
+ 100 | 0002 | | | 200 | A0002
+ 150 | 0003 | 150 | 0003 | 300 | A0003
+ 200 | 0004 | | | 400 | A0004
+ 250 | 0005 | | | 500 | A0005
+ 300 | 0006 | 300 | 0006 | 600 | A0006
+ 350 | 0007 | | | 700 | A0007
+ 400 | 0008 | | | 800 | A0008
+ 450 | 0009 | 450 | 0009 | 900 | A0009
+ 500 | 0010 | | | 1000 | A0010
+ 550 | 0011 | | | 1100 | A0011
+ | | 75 | 0001 | |
+ | | 225 | 0004 | |
+ | | 375 | 0007 | |
+ | | 525 | 0010 | |
+(16 rows)
+
+-- Semi-join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1, plt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a;
+ 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 = t1_3.c)
+ -> Seq Scan on public.plt1_p1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Hash Join
+ Output: t1_3.c, t2.c
+ Hash Cond: (t1_3.c = ltrim(t2.c, 'A'::text))
+ -> Seq Scan on public.plt2_p1 t1_3
+ Output: t1_3.c
+ -> Hash
+ Output: t2.c
+ -> Seq Scan on public.plt1_e_p1 t2
+ Output: t2.c
+ -> Nested Loop Semi Join
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Join Filter: (t1_1.c = t1_4.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: t1_4.c, t2_1.c
+ Hash Cond: (t1_4.c = ltrim(t2_1.c, 'A'::text))
+ -> Seq Scan on public.plt2_p2 t1_4
+ Output: t1_4.c
+ -> Hash
+ Output: t2_1.c
+ -> Seq Scan on public.plt1_e_p2 t2_1
+ Output: t2_1.c
+ -> Nested Loop Semi Join
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Join Filter: (t1_2.c = t1_5.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: t1_5.c, t2_2.c
+ Hash Cond: (t1_5.c = ltrim(t2_2.c, 'A'::text))
+ -> Seq Scan on public.plt2_p3 t1_5
+ Output: t1_5.c
+ -> Hash
+ Output: t2_2.c
+ -> Seq Scan on public.plt1_e_p3 t2_2
+ Output: t2_2.c
+(49 rows)
+
+SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1, plt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a;
+ a | b | c
+-----+-----+------
+ 0 | 0 | 0000
+ 50 | 50 | 0001
+ 100 | 100 | 0002
+ 150 | 150 | 0003
+ 200 | 200 | 0004
+ 250 | 250 | 0005
+ 300 | 300 | 0006
+ 350 | 350 | 0007
+ 400 | 400 | 0008
+ 450 | 450 | 0009
+ 500 | 500 | 0010
+ 550 | 550 | 0011
+(12 rows)
+
+SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1, uplt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a;
+ a | b | c
+-----+-----+------
+ 0 | 0 | 0000
+ 50 | 50 | 0001
+ 100 | 100 | 0002
+ 150 | 150 | 0003
+ 200 | 200 | 0004
+ 250 | 250 | 0005
+ 300 | 300 | 0006
+ 350 | 350 | 0007
+ 400 | 400 | 0008
+ 450 | 450 | 0009
+ 500 | 500 | 0010
+ 550 | 550 | 0011
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+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;
+ 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 = t1_3.c)
+ -> Seq Scan on public.plt1_p1 t1
+ Output: t1.a, t1.b, t1.c
+ Filter: ((t1.a % 25) = 0)
+ -> Hash Join
+ Output: t1_3.c, t1_6.c
+ Hash Cond: (t1_3.c = ltrim(t1_6.c, 'A'::text))
+ -> Seq Scan on public.plt2_p1 t1_3
+ Output: t1_3.c
+ -> Hash
+ Output: t1_6.c
+ -> HashAggregate
+ Output: t1_6.c
+ Group Key: ltrim(t1_6.c, 'A'::text)
+ -> Seq Scan on public.plt1_e_p1 t1_6
+ Output: t1_6.c, ltrim(t1_6.c, 'A'::text)
+ Filter: ((t1_6.a % 25) = 0)
+ -> Nested Loop Semi Join
+ Output: t1_1.a, t1_1.b, t1_1.c
+ Join Filter: (t1_1.c = t1_4.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: t1_4.c, t1_7.c
+ Hash Cond: (t1_4.c = ltrim(t1_7.c, 'A'::text))
+ -> Seq Scan on public.plt2_p2 t1_4
+ Output: t1_4.c
+ -> Hash
+ Output: t1_7.c
+ -> HashAggregate
+ Output: t1_7.c
+ Group Key: ltrim(t1_7.c, 'A'::text)
+ -> Seq Scan on public.plt1_e_p2 t1_7
+ Output: t1_7.c, ltrim(t1_7.c, 'A'::text)
+ Filter: ((t1_7.a % 25) = 0)
+ -> Nested Loop Semi Join
+ Output: t1_2.a, t1_2.b, t1_2.c
+ Join Filter: (t1_2.c = t1_5.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: t1_5.c, t1_8.c
+ Hash Cond: (t1_5.c = ltrim(t1_8.c, 'A'::text))
+ -> Seq Scan on public.plt2_p3 t1_5
+ Output: t1_5.c
+ -> Hash
+ Output: t1_8.c
+ -> HashAggregate
+ Output: t1_8.c
+ Group Key: ltrim(t1_8.c, 'A'::text)
+ -> Seq Scan on public.plt1_e_p3 t1_8
+ Output: t1_8.c, ltrim(t1_8.c, 'A'::text)
+ Filter: ((t1_8.a % 25) = 0)
+(61 rows)
+
+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;
+ a | b | c
+-----+-----+------
+ 0 | 0 | 0000
+ 50 | 50 | 0001
+ 100 | 100 | 0002
+ 150 | 150 | 0003
+ 200 | 200 | 0004
+ 250 | 250 | 0005
+ 300 | 300 | 0006
+ 350 | 350 | 0007
+ 400 | 400 | 0008
+ 450 | 450 | 0009
+ 500 | 500 | 0010
+ 550 | 550 | 0011
+(12 rows)
+
+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;
+ a | b | c
+-----+-----+------
+ 0 | 0 | 0000
+ 50 | 50 | 0001
+ 100 | 100 | 0002
+ 150 | 150 | 0003
+ 200 | 200 | 0004
+ 250 | 250 | 0005
+ 300 | 300 | 0006
+ 350 | 350 | 0007
+ 400 | 400 | 0008
+ 450 | 450 | 0009
+ 500 | 500 | 0010
+ 550 | 550 | 0011
+(12 rows)
+
+--
+-- negative testcases
+--
+-- joins where one of the relations is proven empty
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 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)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 LEFT JOIN prt2 t2 ON t1.a = t2.b;
+ QUERY PLAN
+--------------------------------------
+ Result
+ Output: prt1.a, prt1.c, t2.b, t2.c
+ One-Time Filter: false
+(3 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2 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.prt2 t2
+ Output: t2.b, t2.c
+ Filter: ((t2.a % 25) = 0)
+ -> Seq Scan on public.prt2_p1 t2_1
+ Output: t2_1.b, t2_1.c
+ Filter: ((t2_1.a % 25) = 0)
+ -> Seq Scan on public.prt2_p2 t2_2
+ Output: t2_2.b, t2_2.c
+ Filter: ((t2_2.a % 25) = 0)
+ -> Seq Scan on public.prt2_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)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 FULL JOIN prt2 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.prt2 t2
+ Output: t2.b, t2.c
+ Filter: ((t2.a % 25) = 0)
+ -> Seq Scan on public.prt2_p1 t2_1
+ Output: t2_1.b, t2_1.c
+ Filter: ((t2_1.a % 25) = 0)
+ -> Seq Scan on public.prt2_p2 t2_2
+ Output: t2_2.b, t2_2.c
+ Filter: ((t2_2.a % 25) = 0)
+ -> Seq Scan on public.prt2_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)
+
+CREATE TABLE prt1_n (a int, b int, c varchar) PARTITION BY RANGE(c);
+CREATE TABLE prt1_n_p1 PARTITION OF prt1_n FOR VALUES FROM ('0000') TO ('0250');
+CREATE TABLE prt1_n_p2 PARTITION OF prt1_n FOR VALUES FROM ('0250') TO ('0500');
+INSERT INTO prt1_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 499, 2) i;
+ANALYZE prt1_n;
+ANALYZE prt1_n_p1;
+ANALYZE prt1_n_p2;
+CREATE TABLE prt2_n (a int, b int, c text) PARTITION BY LIST(c);
+CREATE TABLE prt2_n_p1 PARTITION OF prt2_n FOR VALUES IN ('0000', '0003', '0004', '0010', '0006', '0007');
+CREATE TABLE prt2_n_p2 PARTITION OF prt2_n FOR VALUES IN ('0001', '0005', '0002', '0009', '0008', '0011');
+INSERT INTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt2_n;
+ANALYZE prt2_n_p1;
+ANALYZE prt2_n_p2;
+CREATE TABLE prt3_n (a int, b int, c text) PARTITION BY LIST(c);
+CREATE TABLE prt3_n_p1 PARTITION OF prt3_n FOR VALUES IN ('0000', '0004', '0006', '0007');
+CREATE TABLE prt3_n_p2 PARTITION OF prt3_n FOR VALUES IN ('0001', '0002', '0008', '0010');
+CREATE TABLE prt3_n_p3 PARTITION OF prt3_n FOR VALUES IN ('0003', '0005', '0009', '0011');
+INSERT INTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt3_n;
+ANALYZE prt3_n_p1;
+ANALYZE prt3_n_p2;
+ANALYZE prt3_n_p3;
+CREATE TABLE prt4_n (a int, b int, c text) PARTITION BY RANGE(a);
+CREATE TABLE prt4_n_p1 PARTITION OF prt4_n FOR VALUES FROM (0) TO (300);
+CREATE TABLE prt4_n_p2 PARTITION OF prt4_n FOR VALUES FROM (300) TO (500);
+CREATE TABLE prt4_n_p3 PARTITION OF prt4_n FOR VALUES FROM (500) TO (600);
+INSERT INTO prt4_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt4_n;
+ANALYZE prt4_n_p1;
+ANALYZE prt4_n_p2;
+ANALYZE prt4_n_p3;
+-- partition-wise join can not be applied if the partition ranges differ
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2 WHERE t1.a = t2.a;
+ QUERY PLAN
+----------------------------------------------
+ Hash Join
+ Hash Cond: (t1.a = t2.a)
+ -> Append
+ -> Seq Scan on prt1 t1
+ -> Seq Scan on prt1_p1 t1_1
+ -> Seq Scan on prt1_p3 t1_2
+ -> Seq Scan on prt1_p2 t1_3
+ -> Hash
+ -> Append
+ -> Seq Scan on prt4_n t2
+ -> Seq Scan on prt4_n_p1 t2_1
+ -> Seq Scan on prt4_n_p2 t2_2
+ -> Seq Scan on prt4_n_p3 t2_3
+(13 rows)
+
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 FULL JOIN prt4_n t2 ON t1.a = t2.a;
+ QUERY PLAN
+----------------------------------------------
+ Hash Full Join
+ Hash Cond: (t1.a = t2.a)
+ -> Append
+ -> Seq Scan on prt1 t1
+ -> Seq Scan on prt1_p1 t1_1
+ -> Seq Scan on prt1_p3 t1_2
+ -> Seq Scan on prt1_p2 t1_3
+ -> Hash
+ -> Append
+ -> Seq Scan on prt4_n t2
+ -> Seq Scan on prt4_n_p1 t2_1
+ -> Seq Scan on prt4_n_p2 t2_2
+ -> Seq Scan on prt4_n_p3 t2_3
+(13 rows)
+
+-- partition-wise join can not be applied if there are no equi-join conditions
+-- between partition keys
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON (t1.a < t2.b);
+ QUERY PLAN
+---------------------------------------------------------
+ Nested Loop Left Join
+ -> Append
+ -> Seq Scan on prt1 t1
+ -> Seq Scan on prt1_p1 t1_1
+ -> Seq Scan on prt1_p3 t1_2
+ -> Seq Scan on prt1_p2 t1_3
+ -> Append
+ -> Seq Scan on prt2 t2
+ Filter: (t1.a < b)
+ -> Index Scan using iprt2_p1_b on prt2_p1 t2_1
+ Index Cond: (t1.a < b)
+ -> Index Scan using iprt2_p2_b on prt2_p2 t2_2
+ Index Cond: (t1.a < b)
+ -> Index Scan using iprt2_p3_b on prt2_p3 t2_3
+ Index Cond: (t1.a < b)
+(15 rows)
+
+-- equi-join with join condition on partial keys does not qualify for
+-- partition-wise join
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1, prt2_m t2 WHERE t1.a = (t2.b + t2.a)/2 AND t1.a % 25 = 0;
+ QUERY PLAN
+----------------------------------------------
+ Hash Join
+ Hash Cond: (((t2.b + t2.a) / 2) = t1.a)
+ -> Append
+ -> Seq Scan on prt2_m t2
+ -> Seq Scan on prt2_m_p1 t2_1
+ -> Seq Scan on prt2_m_p2 t2_2
+ -> Seq Scan on prt2_m_p3 t2_3
+ -> Hash
+ -> Append
+ -> Seq Scan on prt1_m t1
+ Filter: ((a % 25) = 0)
+ -> Seq Scan on prt1_m_p1 t1_1
+ Filter: ((a % 25) = 0)
+ -> Seq Scan on prt1_m_p2 t1_2
+ Filter: ((a % 25) = 0)
+ -> Seq Scan on prt1_m_p3 t1_3
+ Filter: ((a % 25) = 0)
+(17 rows)
+
+-- equi-join between out-of-order partition key columns does not qualify for
+-- partition-wise join
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.a = t2.b WHERE t1.a % 25 = 0;
+ QUERY PLAN
+----------------------------------------------
+ Hash Right Join
+ Hash Cond: (t2.b = t1.a)
+ -> Append
+ -> Seq Scan on prt2_m t2
+ -> Seq Scan on prt2_m_p1 t2_1
+ -> Seq Scan on prt2_m_p2 t2_2
+ -> Seq Scan on prt2_m_p3 t2_3
+ -> Hash
+ -> Append
+ -> Seq Scan on prt1_m t1
+ Filter: ((a % 25) = 0)
+ -> Seq Scan on prt1_m_p1 t1_1
+ Filter: ((a % 25) = 0)
+ -> Seq Scan on prt1_m_p2 t1_2
+ Filter: ((a % 25) = 0)
+ -> Seq Scan on prt1_m_p3 t1_3
+ Filter: ((a % 25) = 0)
+(17 rows)
+
+-- equi-join between non-key columns does not qualify for partition-wise join
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.c = t2.c WHERE t1.a % 25 = 0;
+ QUERY PLAN
+----------------------------------------------
+ Hash Right Join
+ Hash Cond: ((t2.c)::text = (t1.c)::text)
+ -> Append
+ -> Seq Scan on prt2_m t2
+ -> Seq Scan on prt2_m_p1 t2_1
+ -> Seq Scan on prt2_m_p2 t2_2
+ -> Seq Scan on prt2_m_p3 t2_3
+ -> Hash
+ -> Append
+ -> Seq Scan on prt1_m t1
+ Filter: ((a % 25) = 0)
+ -> Seq Scan on prt1_m_p1 t1_1
+ Filter: ((a % 25) = 0)
+ -> Seq Scan on prt1_m_p2 t1_2
+ Filter: ((a % 25) = 0)
+ -> Seq Scan on prt1_m_p3 t1_3
+ Filter: ((a % 25) = 0)
+(17 rows)
+
+-- partition-wise join can not be applied for a join between list and range
+-- partitioned table
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1, prt2_n t2 WHERE t1.c = t2.c;
+ QUERY PLAN
+----------------------------------------------
+ Hash Join
+ Hash Cond: (t2.c = (t1.c)::text)
+ -> Append
+ -> Seq Scan on prt2_n t2
+ -> Seq Scan on prt2_n_p1 t2_1
+ -> Seq Scan on prt2_n_p2 t2_2
+ -> Hash
+ -> Append
+ -> Seq Scan on prt1_n t1
+ -> Seq Scan on prt1_n_p1 t1_1
+ -> Seq Scan on prt1_n_p2 t1_2
+(11 rows)
+
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 LEFT JOIN prt2_n t2 ON (t1.c = t2.c);
+ QUERY PLAN
+----------------------------------------------
+ Hash Right Join
+ Hash Cond: (t2.c = (t1.c)::text)
+ -> Append
+ -> Seq Scan on prt2_n t2
+ -> Seq Scan on prt2_n_p1 t2_1
+ -> Seq Scan on prt2_n_p2 t2_2
+ -> Hash
+ -> Append
+ -> Seq Scan on prt1_n t1
+ -> Seq Scan on prt1_n_p1 t1_1
+ -> Seq Scan on prt1_n_p2 t1_2
+(11 rows)
+
+-- partition-wise join can not be applied between tables with different
+-- partition lists
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 RIGHT JOIN prt1 t2 ON (t1.c = t2.c);
+ QUERY PLAN
+----------------------------------------------
+ Hash Left Join
+ Hash Cond: ((t2.c)::text = (t1.c)::text)
+ -> Append
+ -> Seq Scan on prt1 t2
+ -> Seq Scan on prt1_p1 t2_1
+ -> Seq Scan on prt1_p3 t2_2
+ -> Seq Scan on prt1_p2 t2_3
+ -> Hash
+ -> Append
+ -> Seq Scan on prt1_n t1
+ -> Seq Scan on prt1_n_p1 t1_1
+ -> Seq Scan on prt1_n_p2 t1_2
+(12 rows)
+
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c);
+ QUERY PLAN
+----------------------------------------------
+ Hash Full Join
+ Hash Cond: ((t2.c)::text = (t1.c)::text)
+ -> Append
+ -> Seq Scan on prt1 t2
+ -> Seq Scan on prt1_p1 t2_1
+ -> Seq Scan on prt1_p3 t2_2
+ -> Seq Scan on prt1_p2 t2_3
+ -> Hash
+ -> Append
+ -> Seq Scan on prt1_n t1
+ -> Seq Scan on prt1_n_p1 t1_1
+ -> Seq Scan on prt1_n_p2 t1_2
+(12 rows)
+
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index edeb2d6..ac38f50 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -103,7 +103,7 @@ test: publication subscription
# ----------
# Another group of parallel tests
# ----------
-test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock json jsonb json_encoding indirect_toast equivclass
+test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock json jsonb json_encoding indirect_toast equivclass partition_join
# ----------
# Another group of parallel tests
# NB: temp.sql does a reconnect which transiently uses 2 connections,
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 27a46d7..1bf98a4 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -172,3 +172,4 @@ test: with
test: xml
test: event_trigger
test: stats
+test: partition_join
diff --git a/src/test/regress/sql/partition_join.sql b/src/test/regress/sql/partition_join.sql
new file mode 100644
index 0000000..0322f1e
--- /dev/null
+++ b/src/test/regress/sql/partition_join.sql
@@ -0,0 +1,515 @@
+--
+-- PARTITION_JOIN
+-- Test partition-wise join between partitioned tables
+--
+
+--
+-- partitioned by a single column
+--
+CREATE TABLE prt1 (a int, b int, c varchar) PARTITION BY RANGE(a);
+CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (250);
+CREATE TABLE prt1_p3 PARTITION OF prt1 FOR VALUES FROM (500) TO (600);
+CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (250) TO (500);
+INSERT INTO prt1 SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt1;
+ANALYZE prt1_p1;
+ANALYZE prt1_p2;
+ANALYZE prt1_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uprt1 AS SELECT * FROM prt1;
+
+CREATE TABLE prt2 (a int, b int, c varchar) PARTITION BY RANGE(b);
+CREATE TABLE prt2_p1 PARTITION OF prt2 FOR VALUES FROM (0) TO (250);
+CREATE TABLE prt2_p2 PARTITION OF prt2 FOR VALUES FROM (250) TO (500);
+CREATE TABLE prt2_p3 PARTITION OF prt2 FOR VALUES FROM (500) TO (600);
+INSERT INTO prt2 SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+ANALYZE prt2;
+ANALYZE prt2_p1;
+ANALYZE prt2_p2;
+ANALYZE prt2_p3;
+CREATE TABLE uprt2 AS SELECT * FROM prt2;
+
+-- inner join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1, uprt2 t2 WHERE t1.a = t2.b AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+-- left outer join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+-- right outer join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+
+-- full outer join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+
+-- Cases with non-nullable expressions in subquery results;
+-- make sure these go to null as expected
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t1.phv, t2.b, t2.c, t2.phv FROM (SELECT 25 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 50 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
+
+-- Join with pruned partitions from joining relations
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.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 t1, prt2 t2 WHERE t1.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 t1, uprt2 t2 WHERE t1.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 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.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 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.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 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM uprt2 WHERE b > 250) t2 ON t1.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 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2 WHERE b > 250) 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 prt1 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2 WHERE b > 250) 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 uprt1 WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM uprt2 WHERE b > 250) 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 prt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1 WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b ORDER BY t1.a, t2.b;
+
+-- Semi-join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+
+-- lateral reference
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM uprt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM uprt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+
+--
+-- partitioned by expression
+--
+CREATE TABLE prt1_e (a int, b int, c varchar) PARTITION BY RANGE(((a + b)/2));
+CREATE TABLE prt1_e_p1 PARTITION OF prt1_e FOR VALUES FROM (0) TO (250);
+CREATE TABLE prt1_e_p2 PARTITION OF prt1_e FOR VALUES FROM (250) TO (500);
+CREATE TABLE prt1_e_p3 PARTITION OF prt1_e FOR VALUES FROM (500) TO (600);
+INSERT INTO prt1_e SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt1_e;
+ANALYZE prt1_e_p1;
+ANALYZE prt1_e_p2;
+ANALYZE prt1_e_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uprt1_e AS SELECT * FROM prt1_e;
+
+CREATE TABLE prt2_e (a int, b int, c varchar) PARTITION BY RANGE(((b + a)/2));
+CREATE TABLE prt2_e_p1 PARTITION OF prt2_e FOR VALUES FROM (0) TO (250);
+CREATE TABLE prt2_e_p2 PARTITION OF prt2_e FOR VALUES FROM (250) TO (500);
+CREATE TABLE prt2_e_p3 PARTITION OF prt2_e FOR VALUES FROM (500) TO (600);
+INSERT INTO prt2_e SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i;
+ANALYZE prt2_e;
+ANALYZE prt2_e_p1;
+ANALYZE prt2_e_p2;
+ANALYZE prt2_e_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uprt2_e AS SELECT * FROM prt2_e;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1, prt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1, prt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_e t1, uprt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 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 prt1_e t1 LEFT JOIN prt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1 LEFT JOIN prt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_e t1 LEFT JOIN uprt2_e t2 ON (t1.a + t1.b)/2 = (t2.b + t2.a)/2 WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+--
+-- N-way join
+--
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM uprt1 t1, uprt2 t2, uprt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) LEFT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) LEFT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT * FROM uprt1_e WHERE uprt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+-- 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, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM uprt1 WHERE uprt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uprt2 WHERE uprt2.b % 25 = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM uprt1_e WHERE uprt1_e.a % 25 = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+-- Semi-join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1, uprt1_e t2 WHERE t1.b % 25 = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.a % 25 = 0 ORDER BY t1.a;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+
+-- test merge joins with and without using indexes
+SET enable_hashjoin TO off;
+SET enable_nestloop TO off;
+
+CREATE INDEX iprt1_p1_a on prt1_p1(a);
+CREATE INDEX iprt1_p2_a on prt1_p2(a);
+CREATE INDEX iprt1_p3_a on prt1_p3(a);
+CREATE INDEX iprt2_p1_b on prt2_p1(b);
+CREATE INDEX iprt2_p2_b on prt2_p2(b);
+CREATE INDEX iprt2_p3_b on prt2_p3(b);
+CREATE INDEX iprt1_e_p1_ab2 on prt1_e_p1(((a+b)/2));
+CREATE INDEX iprt1_e_p2_ab2 on prt1_e_p2(((a+b)/2));
+CREATE INDEX iprt1_e_p3_ab2 on prt1_e_p3(((a+b)/2));
+
+ANALYZE prt1;
+ANALYZE prt1_p1;
+ANALYZE prt1_p2;
+ANALYZE prt1_p3;
+ANALYZE prt2;
+ANALYZE prt2_p1;
+ANALYZE prt2_p2;
+ANALYZE prt2_p3;
+ANALYZE prt1_e;
+ANALYZE prt1_e_p1;
+ANALYZE prt1_e_p2;
+ANALYZE prt1_e_p3;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+SET enable_seqscan TO off;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 RIGHT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t2.b = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM uprt1 t1 WHERE t1.a IN (SELECT t1.b FROM uprt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM uprt1_e t1 WHERE t1.a %25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uprt1 t1 LEFT JOIN uprt2 t2 ON t1.a = t2.b) RIGHT JOIN uprt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+-- lateral references and parameterized paths
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM uprt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.a = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM prt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM uprt1 t1 LEFT JOIN LATERAL
+ (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1 t2 JOIN uprt2 t3 ON (t2.a = t3.b)) ss
+ ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY t1.a;
+
+RESET enable_hashjoin;
+RESET enable_nestloop;
+RESET enable_seqscan;
+
+--
+-- partitioned by multiple columns
+--
+CREATE TABLE prt1_m (a int, b int, c varchar) PARTITION BY RANGE(a, ((a + b)/2));
+CREATE TABLE prt1_m_p1 PARTITION OF prt1_m FOR VALUES FROM (0, 0) TO (250, 250);
+CREATE TABLE prt1_m_p2 PARTITION OF prt1_m FOR VALUES FROM (250, 250) TO (500, 500);
+CREATE TABLE prt1_m_p3 PARTITION OF prt1_m FOR VALUES FROM (500, 500) TO (600, 600);
+INSERT INTO prt1_m SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt1_m;
+ANALYZE prt1_m_p1;
+ANALYZE prt1_m_p2;
+ANALYZE prt1_m_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uprt1_m AS SELECT * FROM prt1_m;
+
+CREATE TABLE prt2_m (a int, b int, c varchar) PARTITION BY RANGE(((b + a)/2), b);
+CREATE TABLE prt2_m_p1 PARTITION OF prt2_m FOR VALUES FROM (0, 0) TO (250, 250);
+CREATE TABLE prt2_m_p2 PARTITION OF prt2_m FOR VALUES FROM (250, 250) TO (500, 500);
+CREATE TABLE prt2_m_p3 PARTITION OF prt2_m FOR VALUES FROM (500, 500) TO (600, 600);
+INSERT INTO prt2_m SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 3) i;
+ANALYZE prt2_m;
+ANALYZE prt2_m_p1;
+ANALYZE prt2_m_p2;
+ANALYZE prt2_m_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uprt2_m AS SELECT * FROM prt2_m;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 RIGHT JOIN prt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 RIGHT JOIN prt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_m t1 RIGHT JOIN uprt2_m t2 ON t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2 WHERE t2.b % 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_m WHERE prt1_m.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_m t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2_m t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b;
+
+--
+-- tests for list partitioned tables.
+--
+CREATE TABLE plt1 (a int, b int, c text) PARTITION BY LIST(c);
+CREATE TABLE plt1_p1 PARTITION OF plt1 FOR VALUES IN ('0000', '0003', '0004', '0010');
+CREATE TABLE plt1_p2 PARTITION OF plt1 FOR VALUES IN ('0001', '0005', '0002', '0009');
+CREATE TABLE plt1_p3 PARTITION OF plt1 FOR VALUES IN ('0006', '0007', '0008', '0011');
+INSERT INTO plt1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE plt1;
+ANALYZE plt1_p1;
+ANALYZE plt1_p2;
+ANALYZE plt1_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uplt1 AS SELECT * FROM plt1;
+
+CREATE TABLE plt2 (a int, b int, c text) PARTITION BY LIST(c);
+CREATE TABLE plt2_p1 PARTITION OF plt2 FOR VALUES IN ('0000', '0003', '0004', '0010');
+CREATE TABLE plt2_p2 PARTITION OF plt2 FOR VALUES IN ('0001', '0005', '0002', '0009');
+CREATE TABLE plt2_p3 PARTITION OF plt2 FOR VALUES IN ('0006', '0007', '0008', '0011');
+INSERT INTO plt2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 3) i;
+ANALYZE plt2;
+ANALYZE plt2_p1;
+ANALYZE plt2_p2;
+ANALYZE plt2_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uplt2 AS SELECT * FROM plt2;
+
+--
+-- list partitioned by expression
+--
+CREATE TABLE plt1_e (a int, b int, c text) PARTITION BY LIST(ltrim(c, 'A'));
+CREATE TABLE plt1_e_p1 PARTITION OF plt1_e FOR VALUES IN ('0000', '0003', '0004', '0010');
+CREATE TABLE plt1_e_p2 PARTITION OF plt1_e FOR VALUES IN ('0001', '0005', '0002', '0009');
+CREATE TABLE plt1_e_p3 PARTITION OF plt1_e FOR VALUES IN ('0006', '0007', '0008', '0011');
+INSERT INTO plt1_e SELECT i, i, 'A' || to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE plt1_e;
+ANALYZE plt1_e_p1;
+ANALYZE plt1_e_p2;
+ANALYZE plt1_e_p3;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uplt1_e AS SELECT * FROM plt1_e;
+
+--
+-- N-way join
+--
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c;
+SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c;
+SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM uplt1 t1, uplt2 t2, uplt1_e t3 WHERE t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN uplt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) LEFT JOIN uplt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 LEFT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 LEFT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN uplt1_e t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (plt1 t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN plt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (uplt1 t1 RIGHT JOIN uplt2 t2 ON t1.a = t2.b AND t1.c = t2.c) RIGHT JOIN uplt1_e t3 ON (t2.b = t3.a AND t2.c = ltrim(t3.c, 'A')) WHERE t3.a % 25 = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b;
+SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM ((SELECT * FROM uplt1 WHERE uplt1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uplt2 WHERE uplt2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c)) FULL JOIN (SELECT * FROM uplt1_e WHERE uplt1_e.a % 25 = 0) t3 ON (t1.a = t3.a AND ltrim(t3.c, 'A') = t1.c) ORDER BY t1.a, t2.b, t3.a + t3.b;
+
+-- Semi-join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1, plt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1, plt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1, uplt1_e t2 WHERE t1.c = ltrim(t2.c, 'A')) AND t1.a % 25 = 0 ORDER BY t1.a;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+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 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;
+
+--
+-- negative testcases
+--
+
+-- joins where one of the relations is proven empty
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 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 prt1 WHERE a = 1 AND a = 2) t1 LEFT JOIN prt2 t2 ON t1.a = t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2 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 prt1 WHERE a = 1 AND a = 2) t1 FULL JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+CREATE TABLE prt1_n (a int, b int, c varchar) PARTITION BY RANGE(c);
+CREATE TABLE prt1_n_p1 PARTITION OF prt1_n FOR VALUES FROM ('0000') TO ('0250');
+CREATE TABLE prt1_n_p2 PARTITION OF prt1_n FOR VALUES FROM ('0250') TO ('0500');
+INSERT INTO prt1_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 499, 2) i;
+ANALYZE prt1_n;
+ANALYZE prt1_n_p1;
+ANALYZE prt1_n_p2;
+
+CREATE TABLE prt2_n (a int, b int, c text) PARTITION BY LIST(c);
+CREATE TABLE prt2_n_p1 PARTITION OF prt2_n FOR VALUES IN ('0000', '0003', '0004', '0010', '0006', '0007');
+CREATE TABLE prt2_n_p2 PARTITION OF prt2_n FOR VALUES IN ('0001', '0005', '0002', '0009', '0008', '0011');
+INSERT INTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt2_n;
+ANALYZE prt2_n_p1;
+ANALYZE prt2_n_p2;
+
+CREATE TABLE prt3_n (a int, b int, c text) PARTITION BY LIST(c);
+CREATE TABLE prt3_n_p1 PARTITION OF prt3_n FOR VALUES IN ('0000', '0004', '0006', '0007');
+CREATE TABLE prt3_n_p2 PARTITION OF prt3_n FOR VALUES IN ('0001', '0002', '0008', '0010');
+CREATE TABLE prt3_n_p3 PARTITION OF prt3_n FOR VALUES IN ('0003', '0005', '0009', '0011');
+INSERT INTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt3_n;
+ANALYZE prt3_n_p1;
+ANALYZE prt3_n_p2;
+ANALYZE prt3_n_p3;
+
+CREATE TABLE prt4_n (a int, b int, c text) PARTITION BY RANGE(a);
+CREATE TABLE prt4_n_p1 PARTITION OF prt4_n FOR VALUES FROM (0) TO (300);
+CREATE TABLE prt4_n_p2 PARTITION OF prt4_n FOR VALUES FROM (300) TO (500);
+CREATE TABLE prt4_n_p3 PARTITION OF prt4_n FOR VALUES FROM (500) TO (600);
+INSERT INTO prt4_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE prt4_n;
+ANALYZE prt4_n_p1;
+ANALYZE prt4_n_p2;
+ANALYZE prt4_n_p3;
+
+-- partition-wise join can not be applied if the partition ranges differ
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2 WHERE t1.a = t2.a;
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 FULL JOIN prt4_n t2 ON t1.a = t2.a;
+
+-- partition-wise join can not be applied if there are no equi-join conditions
+-- between partition keys
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON (t1.a < t2.b);
+
+-- equi-join with join condition on partial keys does not qualify for
+-- partition-wise join
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1, prt2_m t2 WHERE t1.a = (t2.b + t2.a)/2 AND t1.a % 25 = 0;
+
+-- equi-join between out-of-order partition key columns does not qualify for
+-- partition-wise join
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.a = t2.b WHERE t1.a % 25 = 0;
+
+-- equi-join between non-key columns does not qualify for partition-wise join
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.c = t2.c WHERE t1.a % 25 = 0;
+
+-- partition-wise join can not be applied for a join between list and range
+-- partitioned table
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1, prt2_n t2 WHERE t1.c = t2.c;
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 LEFT JOIN prt2_n t2 ON (t1.c = t2.c);
+
+-- partition-wise join can not be applied between tables with different
+-- partition lists
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 RIGHT JOIN prt1 t2 ON (t1.c = t2.c);
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c);
--
1.7.9.5