3 -- Test partitionwise join between partitioned tables
5 -- Enable partitionwise join, which by default is disabled.
6 SET enable_partitionwise_join to true;
8 -- partitioned by a single column
10 CREATE TABLE prt1 (a int, b int, c varchar) PARTITION BY RANGE(a);
11 CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (250);
12 CREATE TABLE prt1_p3 PARTITION OF prt1 FOR VALUES FROM (500) TO (600);
13 CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (250) TO (500);
14 INSERT INTO prt1 SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(0, 599) i WHERE i % 2 = 0;
15 CREATE INDEX iprt1_p1_a on prt1_p1(a);
16 CREATE INDEX iprt1_p2_a on prt1_p2(a);
17 CREATE INDEX iprt1_p3_a on prt1_p3(a);
19 CREATE TABLE prt2 (a int, b int, c varchar) PARTITION BY RANGE(b);
20 CREATE TABLE prt2_p1 PARTITION OF prt2 FOR VALUES FROM (0) TO (250);
21 CREATE TABLE prt2_p2 PARTITION OF prt2 FOR VALUES FROM (250) TO (500);
22 CREATE TABLE prt2_p3 PARTITION OF prt2 FOR VALUES FROM (500) TO (600);
23 INSERT INTO prt2 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(0, 599) i WHERE i % 3 = 0;
24 CREATE INDEX iprt2_p1_b on prt2_p1(b);
25 CREATE INDEX iprt2_p2_b on prt2_p2(b);
26 CREATE INDEX iprt2_p3_b on prt2_p3(b);
30 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b;
32 --------------------------------------------------
37 Hash Cond: (t2_1.b = t1_1.a)
38 -> Seq Scan on prt2_p1 t2_1
40 -> Seq Scan on prt1_p1 t1_1
43 Hash Cond: (t2_2.b = t1_2.a)
44 -> Seq Scan on prt2_p2 t2_2
46 -> Seq Scan on prt1_p2 t1_2
49 Hash Cond: (t2_3.b = t1_3.a)
50 -> Seq Scan on prt2_p3 t2_3
52 -> Seq Scan on prt1_p3 t1_3
56 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b;
58 -----+------+-----+------
60 150 | 0150 | 150 | 0150
61 300 | 0300 | 300 | 0300
62 450 | 0450 | 450 | 0450
65 -- left outer join, 3-way
67 SELECT COUNT(*) FROM prt1 t1
68 LEFT JOIN prt1 t2 ON t1.a = t2.a
69 LEFT JOIN prt1 t3 ON t2.a = t3.a;
71 --------------------------------------------------------
75 Hash Cond: (t2_1.a = t3_1.a)
77 Hash Cond: (t1_1.a = t2_1.a)
78 -> Seq Scan on prt1_p1 t1_1
80 -> Seq Scan on prt1_p1 t2_1
82 -> Seq Scan on prt1_p1 t3_1
84 Hash Cond: (t2_2.a = t3_2.a)
86 Hash Cond: (t1_2.a = t2_2.a)
87 -> Seq Scan on prt1_p2 t1_2
89 -> Seq Scan on prt1_p2 t2_2
91 -> Seq Scan on prt1_p2 t3_2
93 Hash Cond: (t2_3.a = t3_3.a)
95 Hash Cond: (t1_3.a = t2_3.a)
96 -> Seq Scan on prt1_p3 t1_3
98 -> Seq Scan on prt1_p3 t2_3
100 -> Seq Scan on prt1_p3 t3_3
103 SELECT COUNT(*) FROM prt1 t1
104 LEFT JOIN prt1 t2 ON t1.a = t2.a
105 LEFT JOIN prt1 t3 ON t2.a = t3.a;
111 -- left outer join, with whole-row reference; partitionwise join does not apply
113 SELECT t1, t2 FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER BY t1.a, t2.b;
115 --------------------------------------------------
119 Hash Cond: (t2.b = t1.a)
121 -> Seq Scan on prt2_p1 t2_1
122 -> Seq Scan on prt2_p2 t2_2
123 -> Seq Scan on prt2_p3 t2_3
126 -> Seq Scan on prt1_p1 t1_1
128 -> Seq Scan on prt1_p2 t1_2
130 -> Seq Scan on prt1_p3 t1_3
134 SELECT t1, t2 FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER BY t1.a, t2.b;
136 --------------+--------------
137 (0,0,0000) | (0,0,0000)
140 (150,0,0150) | (0,150,0150)
143 (300,0,0300) | (0,300,0300)
146 (450,0,0450) | (0,450,0450)
153 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a = 0 ORDER BY t1.a, t2.b;
155 ---------------------------------------------------------------
160 Hash Cond: (t1_1.a = t2_1.b)
161 -> Seq Scan on prt1_p1 t1_1
163 -> Seq Scan on prt2_p1 t2_1
166 Hash Cond: (t1_2.a = t2_2.b)
167 -> Seq Scan on prt1_p2 t1_2
169 -> Seq Scan on prt2_p2 t2_2
171 -> Nested Loop Left Join
172 -> Seq Scan on prt2_p3 t2_3
174 -> Index Scan using iprt1_p3_a on prt1_p3 t1_3
175 Index Cond: (a = t2_3.b)
178 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a = 0 ORDER BY t1.a, t2.b;
180 -----+------+-----+------
182 150 | 0150 | 150 | 0150
183 300 | 0300 | 300 | 0300
184 450 | 0450 | 450 | 0450
191 -- full outer join, with placeholder vars
193 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.b = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b;
195 ----------------------------------------------------------------
197 Sort Key: prt1.a, prt2.b
200 Hash Cond: (prt1_1.a = prt2_1.b)
201 Filter: (((50) = prt1_1.a) OR ((75) = prt2_1.b))
202 -> Seq Scan on prt1_p1 prt1_1
205 -> Seq Scan on prt2_p1 prt2_1
208 Hash Cond: (prt1_2.a = prt2_2.b)
209 Filter: (((50) = prt1_2.a) OR ((75) = prt2_2.b))
210 -> Seq Scan on prt1_p2 prt1_2
213 -> Seq Scan on prt2_p2 prt2_2
216 Hash Cond: (prt1_3.a = prt2_3.b)
217 Filter: (((50) = prt1_3.a) OR ((75) = prt2_3.b))
218 -> Seq Scan on prt1_p3 prt1_3
221 -> Seq Scan on prt2_p3 prt2_3
225 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.b = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b;
227 ----+------+----+------
232 -- Join with pruned partitions from joining relations
234 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.b = 0 ORDER BY t1.a, t2.b;
236 -----------------------------------------------------
240 Hash Cond: (t2.b = t1.a)
241 -> Seq Scan on prt2_p2 t2
244 -> Seq Scan on prt1_p2 t1
245 Filter: ((a < 450) AND (b = 0))
248 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.b = 0 ORDER BY t1.a, t2.b;
250 -----+------+-----+------
251 300 | 0300 | 300 | 0300
254 -- Currently we can't do partitioned join if nullable-side partitions are pruned
256 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.b = 0 ORDER BY t1.a, t2.b;
258 -----------------------------------------------------------
260 Sort Key: prt1.a, prt2.b
262 Hash Cond: (prt2.b = prt1.a)
264 -> Seq Scan on prt2_p2 prt2_1
266 -> Seq Scan on prt2_p3 prt2_2
270 -> Seq Scan on prt1_p1 prt1_1
271 Filter: ((a < 450) AND (b = 0))
272 -> Seq Scan on prt1_p2 prt1_2
273 Filter: ((a < 450) AND (b = 0))
276 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.b = 0 ORDER BY t1.a, t2.b;
278 -----+------+-----+------
285 300 | 0300 | 300 | 0300
290 -- Currently we can't do partitioned join if nullable-side partitions are pruned
292 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0 OR t2.a = 0 ORDER BY t1.a, t2.b;
294 ----------------------------------------------------
296 Sort Key: prt1.a, prt2.b
298 Hash Cond: (prt1.a = prt2.b)
299 Filter: ((prt1.b = 0) OR (prt2.a = 0))
301 -> Seq Scan on prt1_p1 prt1_1
303 -> Seq Scan on prt1_p2 prt1_2
307 -> Seq Scan on prt2_p2 prt2_1
309 -> Seq Scan on prt2_p3 prt2_2
313 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0 OR t2.a = 0 ORDER BY t1.a, t2.b;
315 -----+------+-----+------
322 300 | 0300 | 300 | 0300
332 SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t2.b FROM prt2 t2 WHERE t2.a = 0) AND t1.b = 0 ORDER BY t1.a;
334 --------------------------------------------------
339 Hash Cond: (t1_1.a = t2_1.b)
340 -> Seq Scan on prt1_p1 t1_1
343 -> Seq Scan on prt2_p1 t2_1
346 Hash Cond: (t1_2.a = t2_2.b)
347 -> Seq Scan on prt1_p2 t1_2
350 -> Seq Scan on prt2_p2 t2_2
352 -> Nested Loop Semi Join
353 Join Filter: (t1_3.a = t2_3.b)
354 -> Seq Scan on prt1_p3 t1_3
357 -> Seq Scan on prt2_p3 t2_3
361 SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t2.b FROM prt2 t2 WHERE t2.a = 0) AND t1.b = 0 ORDER BY t1.a;
370 -- Anti-join with aggregates
372 SELECT sum(t1.a), avg(t1.a), sum(t1.b), avg(t1.b) FROM prt1 t1 WHERE NOT EXISTS (SELECT 1 FROM prt2 t2 WHERE t1.a = t2.b);
374 --------------------------------------------------
378 Hash Cond: (t1_1.a = t2_1.b)
379 -> Seq Scan on prt1_p1 t1_1
381 -> Seq Scan on prt2_p1 t2_1
383 Hash Cond: (t1_2.a = t2_2.b)
384 -> Seq Scan on prt1_p2 t1_2
386 -> Seq Scan on prt2_p2 t2_2
388 Hash Cond: (t1_3.a = t2_3.b)
389 -> Seq Scan on prt1_p3 t1_3
391 -> Seq Scan on prt2_p3 t2_3
394 SELECT sum(t1.a), avg(t1.a), sum(t1.b), avg(t1.b) FROM prt1 t1 WHERE NOT EXISTS (SELECT 1 FROM prt2 t2 WHERE t1.a = t2.b);
395 sum | avg | sum | avg
396 -------+----------------------+------+---------------------
397 60000 | 300.0000000000000000 | 2400 | 12.0000000000000000
402 SELECT * FROM prt1 t1 LEFT JOIN LATERAL
403 (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.b) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
404 ON t1.a = ss.t2a WHERE t1.b = 0 ORDER BY t1.a;
406 --------------------------------------------------------------------------
410 -> Nested Loop Left Join
411 -> Seq Scan on prt1_p1 t1_1
414 -> Index Only Scan using iprt1_p1_a on prt1_p1 t2_1
415 Index Cond: (a = t1_1.a)
416 -> Index Scan using iprt2_p1_b on prt2_p1 t3_1
417 Index Cond: (b = t2_1.a)
418 -> Nested Loop Left Join
419 -> Seq Scan on prt1_p2 t1_2
422 -> Index Only Scan using iprt1_p2_a on prt1_p2 t2_2
423 Index Cond: (a = t1_2.a)
424 -> Index Scan using iprt2_p2_b on prt2_p2 t3_2
425 Index Cond: (b = t2_2.a)
426 -> Nested Loop Left Join
427 -> Seq Scan on prt1_p3 t1_3
430 -> Index Only Scan using iprt1_p3_a on prt1_p3 t2_3
431 Index Cond: (a = t1_3.a)
432 -> Index Scan using iprt2_p3_b on prt2_p3 t3_3
433 Index Cond: (b = t2_3.a)
436 SELECT * FROM prt1 t1 LEFT JOIN LATERAL
437 (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.b) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
438 ON t1.a = ss.t2a WHERE t1.b = 0 ORDER BY t1.a;
439 a | b | c | t2a | t3a | least
440 -----+---+------+-----+-----+-------
441 0 | 0 | 0000 | 0 | 0 | 0
444 150 | 0 | 0150 | 150 | 0 | 150
447 300 | 0 | 0300 | 300 | 0 | 300
450 450 | 0 | 0450 | 450 | 0 | 450
456 SELECT t1.a, ss.t2a, ss.t2c FROM prt1 t1 LEFT JOIN LATERAL
457 (SELECT t2.a AS t2a, t3.a AS t3a, t2.b t2b, t2.c t2c, least(t1.a,t2.a,t3.b) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
458 ON t1.c = ss.t2c WHERE (t1.b + coalesce(ss.t2b, 0)) = 0 ORDER BY t1.a;
460 --------------------------------------------------------------
464 Hash Cond: ((t1.c)::text = (t2.c)::text)
465 Filter: ((t1.b + COALESCE(t2.b, 0)) = 0)
467 -> Seq Scan on prt1_p1 t1_1
468 -> Seq Scan on prt1_p2 t1_2
469 -> Seq Scan on prt1_p3 t1_3
473 Hash Cond: (t2_1.a = t3_1.b)
474 -> Seq Scan on prt1_p1 t2_1
476 -> Seq Scan on prt2_p1 t3_1
478 Hash Cond: (t2_2.a = t3_2.b)
479 -> Seq Scan on prt1_p2 t2_2
481 -> Seq Scan on prt2_p2 t3_2
483 Hash Cond: (t2_3.a = t3_3.b)
484 -> Seq Scan on prt1_p3 t2_3
486 -> Seq Scan on prt2_p3 t3_3
489 SELECT t1.a, ss.t2a, ss.t2c FROM prt1 t1 LEFT JOIN LATERAL
490 (SELECT t2.a AS t2a, t3.a AS t3a, t2.b t2b, t2.c t2c, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
491 ON t1.c = ss.t2c WHERE (t1.b + coalesce(ss.t2b, 0)) = 0 ORDER BY t1.a;
508 SET max_parallel_workers_per_gather = 0;
509 -- If there are lateral references to the other relation in sample scan,
510 -- we cannot generate a partitionwise join.
512 SELECT * FROM prt1 t1 JOIN LATERAL
513 (SELECT * FROM prt1 t2 TABLESAMPLE SYSTEM (t1.a) REPEATABLE(t1.b)) s
516 ---------------------------------------------------------
519 -> Seq Scan on prt1_p1 t1_1
520 -> Seq Scan on prt1_p2 t1_2
521 -> Seq Scan on prt1_p3 t1_3
523 -> Sample Scan on prt1_p1 t2_1
524 Sampling: system (t1.a) REPEATABLE (t1.b)
526 -> Sample Scan on prt1_p2 t2_2
527 Sampling: system (t1.a) REPEATABLE (t1.b)
529 -> Sample Scan on prt1_p3 t2_3
530 Sampling: system (t1.a) REPEATABLE (t1.b)
534 -- If there are lateral references to the other relation in scan's restriction
535 -- clauses, we cannot generate a partitionwise join.
537 SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL
538 (SELECT t1.b AS t1b, t2.* FROM prt2 t2) s
539 ON t1.a = s.b WHERE s.t1b = s.a;
541 ---------------------------------------------------------------
545 -> Seq Scan on prt1_p1 t1_1
546 -> Seq Scan on prt1_p2 t1_2
547 -> Seq Scan on prt1_p3 t1_3
549 -> Index Scan using iprt2_p1_b on prt2_p1 t2_1
550 Index Cond: (b = t1.a)
552 -> Index Scan using iprt2_p2_b on prt2_p2 t2_2
553 Index Cond: (b = t1.a)
555 -> Index Scan using iprt2_p3_b on prt2_p3 t2_3
556 Index Cond: (b = t1.a)
560 SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL
561 (SELECT t1.b AS t1b, t2.* FROM prt2 t2) s
562 ON t1.a = s.b WHERE s.t1b = s.a;
569 SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL
570 (SELECT t1.b AS t1b, t2.* FROM prt2 t2) s
571 ON t1.a = s.b WHERE s.t1b = s.b;
573 --------------------------------------------------------------------
577 -> Seq Scan on prt1_p1 t1_1
578 -> Seq Scan on prt1_p2 t1_2
579 -> Seq Scan on prt1_p3 t1_3
581 -> Index Only Scan using iprt2_p1_b on prt2_p1 t2_1
582 Index Cond: (b = t1.a)
584 -> Index Only Scan using iprt2_p2_b on prt2_p2 t2_2
585 Index Cond: (b = t1.a)
587 -> Index Only Scan using iprt2_p3_b on prt2_p3 t2_3
588 Index Cond: (b = t1.a)
592 SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL
593 (SELECT t1.b AS t1b, t2.* FROM prt2 t2) s
594 ON t1.a = s.b WHERE s.t1b = s.b;
600 RESET max_parallel_workers_per_gather;
601 -- bug with inadequate sort key representation
602 SET enable_partitionwise_aggregate TO true;
603 SET enable_hashjoin TO false;
605 SELECT a, b FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b)
606 WHERE a BETWEEN 490 AND 510
607 GROUP BY 1, 2 ORDER BY 1, 2;
609 -----------------------------------------------------------------------------------------------------------------
611 Group Key: (COALESCE(prt1.a, p2.a)), (COALESCE(prt1.b, p2.b))
613 Sort Key: (COALESCE(prt1.a, p2.a)), (COALESCE(prt1.b, p2.b))
615 Group Key: (COALESCE(prt1.a, p2.a)), (COALESCE(prt1.b, p2.b))
617 Sort Key: (COALESCE(prt1.a, p2.a)), (COALESCE(prt1.b, p2.b))
619 Merge Cond: ((prt1.a = p2.a) AND (prt1.b = p2.b))
620 Filter: ((COALESCE(prt1.a, p2.a) >= 490) AND (COALESCE(prt1.a, p2.a) <= 510))
622 Sort Key: prt1.a, prt1.b
623 -> Seq Scan on prt1_p1 prt1
626 -> Seq Scan on prt2_p1 p2
628 Group Key: (COALESCE(prt1_1.a, p2_1.a)), (COALESCE(prt1_1.b, p2_1.b))
630 Sort Key: (COALESCE(prt1_1.a, p2_1.a)), (COALESCE(prt1_1.b, p2_1.b))
632 Merge Cond: ((prt1_1.a = p2_1.a) AND (prt1_1.b = p2_1.b))
633 Filter: ((COALESCE(prt1_1.a, p2_1.a) >= 490) AND (COALESCE(prt1_1.a, p2_1.a) <= 510))
635 Sort Key: prt1_1.a, prt1_1.b
636 -> Seq Scan on prt1_p2 prt1_1
638 Sort Key: p2_1.a, p2_1.b
639 -> Seq Scan on prt2_p2 p2_1
641 Group Key: (COALESCE(prt1_2.a, p2_2.a)), (COALESCE(prt1_2.b, p2_2.b))
643 Sort Key: (COALESCE(prt1_2.a, p2_2.a)), (COALESCE(prt1_2.b, p2_2.b))
645 Merge Cond: ((prt1_2.a = p2_2.a) AND (prt1_2.b = p2_2.b))
646 Filter: ((COALESCE(prt1_2.a, p2_2.a) >= 490) AND (COALESCE(prt1_2.a, p2_2.a) <= 510))
648 Sort Key: prt1_2.a, prt1_2.b
649 -> Seq Scan on prt1_p3 prt1_2
651 Sort Key: p2_2.a, p2_2.b
652 -> Seq Scan on prt2_p3 p2_2
655 SELECT a, b FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b)
656 WHERE a BETWEEN 490 AND 510
657 GROUP BY 1, 2 ORDER BY 1, 2;
676 RESET enable_partitionwise_aggregate;
677 RESET enable_hashjoin;
679 -- partitioned by expression
681 CREATE TABLE prt1_e (a int, b int, c int) PARTITION BY RANGE(((a + b)/2));
682 CREATE TABLE prt1_e_p1 PARTITION OF prt1_e FOR VALUES FROM (0) TO (250);
683 CREATE TABLE prt1_e_p2 PARTITION OF prt1_e FOR VALUES FROM (250) TO (500);
684 CREATE TABLE prt1_e_p3 PARTITION OF prt1_e FOR VALUES FROM (500) TO (600);
685 INSERT INTO prt1_e SELECT i, i, i % 25 FROM generate_series(0, 599, 2) i;
686 CREATE INDEX iprt1_e_p1_ab2 on prt1_e_p1(((a+b)/2));
687 CREATE INDEX iprt1_e_p2_ab2 on prt1_e_p2(((a+b)/2));
688 CREATE INDEX iprt1_e_p3_ab2 on prt1_e_p3(((a+b)/2));
690 CREATE TABLE prt2_e (a int, b int, c int) PARTITION BY RANGE(((b + a)/2));
691 CREATE TABLE prt2_e_p1 PARTITION OF prt2_e FOR VALUES FROM (0) TO (250);
692 CREATE TABLE prt2_e_p2 PARTITION OF prt2_e FOR VALUES FROM (250) TO (500);
693 CREATE TABLE prt2_e_p3 PARTITION OF prt2_e FOR VALUES FROM (500) TO (600);
694 INSERT INTO prt2_e SELECT i, i, i % 25 FROM generate_series(0, 599, 3) i;
697 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.c = 0 ORDER BY t1.a, t2.b;
699 ------------------------------------------------------------------------------
704 Hash Cond: (((t2_1.b + t2_1.a) / 2) = ((t1_1.a + t1_1.b) / 2))
705 -> Seq Scan on prt2_e_p1 t2_1
707 -> Seq Scan on prt1_e_p1 t1_1
710 Hash Cond: (((t2_2.b + t2_2.a) / 2) = ((t1_2.a + t1_2.b) / 2))
711 -> Seq Scan on prt2_e_p2 t2_2
713 -> Seq Scan on prt1_e_p2 t1_2
716 Hash Cond: (((t2_3.b + t2_3.a) / 2) = ((t1_3.a + t1_3.b) / 2))
717 -> Seq Scan on prt2_e_p3 t2_3
719 -> Seq Scan on prt1_e_p3 t1_3
723 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.c = 0 ORDER BY t1.a, t2.b;
736 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.b = 0 ORDER BY t1.a, t2.b;
738 ---------------------------------------------------------------------
743 Join Filter: (t1_1.a = ((t3_1.a + t3_1.b) / 2))
745 Hash Cond: (t2_1.b = t1_1.a)
746 -> Seq Scan on prt2_p1 t2_1
748 -> Seq Scan on prt1_p1 t1_1
750 -> Index Scan using iprt1_e_p1_ab2 on prt1_e_p1 t3_1
751 Index Cond: (((a + b) / 2) = t2_1.b)
753 Join Filter: (t1_2.a = ((t3_2.a + t3_2.b) / 2))
755 Hash Cond: (t2_2.b = t1_2.a)
756 -> Seq Scan on prt2_p2 t2_2
758 -> Seq Scan on prt1_p2 t1_2
760 -> Index Scan using iprt1_e_p2_ab2 on prt1_e_p2 t3_2
761 Index Cond: (((a + b) / 2) = t2_2.b)
763 Join Filter: (t1_3.a = ((t3_3.a + t3_3.b) / 2))
765 Hash Cond: (t2_3.b = t1_3.a)
766 -> Seq Scan on prt2_p3 t2_3
768 -> Seq Scan on prt1_p3 t1_3
770 -> Index Scan using iprt1_e_p3_ab2 on prt1_e_p3 t3_3
771 Index Cond: (((a + b) / 2) = t2_3.b)
774 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.b = 0 ORDER BY t1.a, t2.b;
775 a | c | b | c | ?column? | c
776 -----+------+-----+------+----------+---
777 0 | 0000 | 0 | 0000 | 0 | 0
778 150 | 0150 | 150 | 0150 | 300 | 0
779 300 | 0300 | 300 | 0300 | 600 | 0
780 450 | 0450 | 450 | 0450 | 900 | 0
784 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.b = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
786 --------------------------------------------------------------
788 Sort Key: t1.a, t2.b, ((t3.a + t3.b))
791 Hash Cond: (((t3_1.a + t3_1.b) / 2) = t1_1.a)
792 -> Seq Scan on prt1_e_p1 t3_1
795 Hash Cond: (t2_1.b = t1_1.a)
796 -> Seq Scan on prt2_p1 t2_1
798 -> Seq Scan on prt1_p1 t1_1
801 Hash Cond: (((t3_2.a + t3_2.b) / 2) = t1_2.a)
802 -> Seq Scan on prt1_e_p2 t3_2
805 Hash Cond: (t2_2.b = t1_2.a)
806 -> Seq Scan on prt2_p2 t2_2
808 -> Seq Scan on prt1_p2 t1_2
811 Hash Cond: (((t3_3.a + t3_3.b) / 2) = t1_3.a)
812 -> Seq Scan on prt1_e_p3 t3_3
815 Hash Cond: (t2_3.b = t1_3.a)
816 -> Seq Scan on prt2_p3 t2_3
818 -> Seq Scan on prt1_p3 t1_3
822 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.b = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
823 a | c | b | c | ?column? | c
824 -----+------+-----+------+----------+---
825 0 | 0000 | 0 | 0000 | 0 | 0
826 50 | 0050 | | | 100 | 0
827 100 | 0100 | | | 200 | 0
828 150 | 0150 | 150 | 0150 | 300 | 0
829 200 | 0200 | | | 400 | 0
830 250 | 0250 | | | 500 | 0
831 300 | 0300 | 300 | 0300 | 600 | 0
832 350 | 0350 | | | 700 | 0
833 400 | 0400 | | | 800 | 0
834 450 | 0450 | 450 | 0450 | 900 | 0
835 500 | 0500 | | | 1000 | 0
836 550 | 0550 | | | 1100 | 0
840 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.c = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
842 -------------------------------------------------------------------
844 Sort Key: t1.a, t2.b, ((t3.a + t3.b))
846 -> Nested Loop Left Join
848 Hash Cond: (t1_1.a = ((t3_1.a + t3_1.b) / 2))
849 -> Seq Scan on prt1_p1 t1_1
851 -> Seq Scan on prt1_e_p1 t3_1
853 -> Index Scan using iprt2_p1_b on prt2_p1 t2_1
854 Index Cond: (b = t1_1.a)
855 -> Nested Loop Left Join
857 Hash Cond: (t1_2.a = ((t3_2.a + t3_2.b) / 2))
858 -> Seq Scan on prt1_p2 t1_2
860 -> Seq Scan on prt1_e_p2 t3_2
862 -> Index Scan using iprt2_p2_b on prt2_p2 t2_2
863 Index Cond: (b = t1_2.a)
864 -> Nested Loop Left Join
866 Hash Cond: (t1_3.a = ((t3_3.a + t3_3.b) / 2))
867 -> Seq Scan on prt1_p3 t1_3
869 -> Seq Scan on prt1_e_p3 t3_3
871 -> Index Scan using iprt2_p3_b on prt2_p3 t2_3
872 Index Cond: (b = t1_3.a)
875 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.c = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
876 a | c | b | c | ?column? | c
877 -----+------+-----+------+----------+---
878 0 | 0000 | 0 | 0000 | 0 | 0
879 50 | 0050 | | | 100 | 0
880 100 | 0100 | | | 200 | 0
881 150 | 0150 | 150 | 0150 | 300 | 0
882 200 | 0200 | | | 400 | 0
883 250 | 0250 | | | 500 | 0
884 300 | 0300 | 300 | 0300 | 600 | 0
885 350 | 0350 | | | 700 | 0
886 400 | 0400 | | | 800 | 0
887 450 | 0450 | 450 | 0450 | 900 | 0
888 500 | 0500 | | | 1000 | 0
889 550 | 0550 | | | 1100 | 0
896 SELECT COUNT(*) FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) FULL JOIN prt2 p3(b,a,c) USING (a, b)
897 WHERE a BETWEEN 490 AND 510;
899 -----------------------------------------------------------------------------------------------------------------------------------------
903 Hash Cond: ((COALESCE(prt1_1.a, p2_1.a) = p3_1.a) AND (COALESCE(prt1_1.b, p2_1.b) = p3_1.b))
904 Filter: ((COALESCE(COALESCE(prt1_1.a, p2_1.a), p3_1.a) >= 490) AND (COALESCE(COALESCE(prt1_1.a, p2_1.a), p3_1.a) <= 510))
906 Hash Cond: ((prt1_1.a = p2_1.a) AND (prt1_1.b = p2_1.b))
907 -> Seq Scan on prt1_p1 prt1_1
909 -> Seq Scan on prt2_p1 p2_1
911 -> Seq Scan on prt2_p1 p3_1
913 Hash Cond: ((COALESCE(prt1_2.a, p2_2.a) = p3_2.a) AND (COALESCE(prt1_2.b, p2_2.b) = p3_2.b))
914 Filter: ((COALESCE(COALESCE(prt1_2.a, p2_2.a), p3_2.a) >= 490) AND (COALESCE(COALESCE(prt1_2.a, p2_2.a), p3_2.a) <= 510))
916 Hash Cond: ((prt1_2.a = p2_2.a) AND (prt1_2.b = p2_2.b))
917 -> Seq Scan on prt1_p2 prt1_2
919 -> Seq Scan on prt2_p2 p2_2
921 -> Seq Scan on prt2_p2 p3_2
923 Hash Cond: ((COALESCE(prt1_3.a, p2_3.a) = p3_3.a) AND (COALESCE(prt1_3.b, p2_3.b) = p3_3.b))
924 Filter: ((COALESCE(COALESCE(prt1_3.a, p2_3.a), p3_3.a) >= 490) AND (COALESCE(COALESCE(prt1_3.a, p2_3.a), p3_3.a) <= 510))
926 Hash Cond: ((prt1_3.a = p2_3.a) AND (prt1_3.b = p2_3.b))
927 -> Seq Scan on prt1_p3 prt1_3
929 -> Seq Scan on prt2_p3 p2_3
931 -> Seq Scan on prt2_p3 p3_3
934 SELECT COUNT(*) FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) FULL JOIN prt2 p3(b,a,c) USING (a, b)
935 WHERE a BETWEEN 490 AND 510;
945 SELECT COUNT(*) FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) FULL JOIN prt2 p3(b,a,c) USING (a, b) FULL JOIN prt1 p4 (a,b,c) USING (a, b)
946 WHERE a BETWEEN 490 AND 510;
948 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
952 Hash Cond: ((COALESCE(COALESCE(prt1_1.a, p2_1.a), p3_1.a) = p4_1.a) AND (COALESCE(COALESCE(prt1_1.b, p2_1.b), p3_1.b) = p4_1.b))
953 Filter: ((COALESCE(COALESCE(COALESCE(prt1_1.a, p2_1.a), p3_1.a), p4_1.a) >= 490) AND (COALESCE(COALESCE(COALESCE(prt1_1.a, p2_1.a), p3_1.a), p4_1.a) <= 510))
955 Hash Cond: ((COALESCE(prt1_1.a, p2_1.a) = p3_1.a) AND (COALESCE(prt1_1.b, p2_1.b) = p3_1.b))
957 Hash Cond: ((prt1_1.a = p2_1.a) AND (prt1_1.b = p2_1.b))
958 -> Seq Scan on prt1_p1 prt1_1
960 -> Seq Scan on prt2_p1 p2_1
962 -> Seq Scan on prt2_p1 p3_1
964 -> Seq Scan on prt1_p1 p4_1
966 Hash Cond: ((COALESCE(COALESCE(prt1_2.a, p2_2.a), p3_2.a) = p4_2.a) AND (COALESCE(COALESCE(prt1_2.b, p2_2.b), p3_2.b) = p4_2.b))
967 Filter: ((COALESCE(COALESCE(COALESCE(prt1_2.a, p2_2.a), p3_2.a), p4_2.a) >= 490) AND (COALESCE(COALESCE(COALESCE(prt1_2.a, p2_2.a), p3_2.a), p4_2.a) <= 510))
969 Hash Cond: ((COALESCE(prt1_2.a, p2_2.a) = p3_2.a) AND (COALESCE(prt1_2.b, p2_2.b) = p3_2.b))
971 Hash Cond: ((prt1_2.a = p2_2.a) AND (prt1_2.b = p2_2.b))
972 -> Seq Scan on prt1_p2 prt1_2
974 -> Seq Scan on prt2_p2 p2_2
976 -> Seq Scan on prt2_p2 p3_2
978 -> Seq Scan on prt1_p2 p4_2
980 Hash Cond: ((COALESCE(COALESCE(prt1_3.a, p2_3.a), p3_3.a) = p4_3.a) AND (COALESCE(COALESCE(prt1_3.b, p2_3.b), p3_3.b) = p4_3.b))
981 Filter: ((COALESCE(COALESCE(COALESCE(prt1_3.a, p2_3.a), p3_3.a), p4_3.a) >= 490) AND (COALESCE(COALESCE(COALESCE(prt1_3.a, p2_3.a), p3_3.a), p4_3.a) <= 510))
983 Hash Cond: ((COALESCE(prt1_3.a, p2_3.a) = p3_3.a) AND (COALESCE(prt1_3.b, p2_3.b) = p3_3.b))
985 Hash Cond: ((prt1_3.a = p2_3.a) AND (prt1_3.b = p2_3.b))
986 -> Seq Scan on prt1_p3 prt1_3
988 -> Seq Scan on prt2_p3 p2_3
990 -> Seq Scan on prt2_p3 p3_3
992 -> Seq Scan on prt1_p3 p4_3
995 SELECT COUNT(*) FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) FULL JOIN prt2 p3(b,a,c) USING (a, b) FULL JOIN prt1 p4 (a,b,c) USING (a, b)
996 WHERE a BETWEEN 490 AND 510;
1002 -- Cases with non-nullable expressions in subquery results;
1003 -- make sure these go to null as expected
1005 SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.b = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.a = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.c = 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;
1007 ------------------------------------------------------------------------------------------------------------
1009 Sort Key: prt1.a, prt2.b, ((prt1_e.a + prt1_e.b))
1012 Hash Cond: (prt1_1.a = ((prt1_e_1.a + prt1_e_1.b) / 2))
1013 Filter: ((prt1_1.a = (50)) OR (prt2_1.b = (75)) OR (((prt1_e_1.a + prt1_e_1.b) / 2) = (50)))
1015 Hash Cond: (prt1_1.a = prt2_1.b)
1016 -> Seq Scan on prt1_p1 prt1_1
1019 -> Seq Scan on prt2_p1 prt2_1
1022 -> Seq Scan on prt1_e_p1 prt1_e_1
1025 Hash Cond: (prt1_2.a = ((prt1_e_2.a + prt1_e_2.b) / 2))
1026 Filter: ((prt1_2.a = (50)) OR (prt2_2.b = (75)) OR (((prt1_e_2.a + prt1_e_2.b) / 2) = (50)))
1028 Hash Cond: (prt1_2.a = prt2_2.b)
1029 -> Seq Scan on prt1_p2 prt1_2
1032 -> Seq Scan on prt2_p2 prt2_2
1035 -> Seq Scan on prt1_e_p2 prt1_e_2
1038 Hash Cond: (prt1_3.a = ((prt1_e_3.a + prt1_e_3.b) / 2))
1039 Filter: ((prt1_3.a = (50)) OR (prt2_3.b = (75)) OR (((prt1_e_3.a + prt1_e_3.b) / 2) = (50)))
1041 Hash Cond: (prt1_3.a = prt2_3.b)
1042 -> Seq Scan on prt1_p3 prt1_3
1045 -> Seq Scan on prt2_p3 prt2_3
1048 -> Seq Scan on prt1_e_p3 prt1_e_3
1052 SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.b = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.a = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.c = 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;
1053 a | phv | b | phv | ?column? | phv
1054 ----+-----+----+-----+----------+-----
1055 50 | 50 | | | 100 | 50
1061 SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.a = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.b = 0 ORDER BY t1.a;
1063 ---------------------------------------------------------------------------------
1068 Join Filter: (t1_2.a = t1_5.b)
1072 Hash Cond: (((t2_1.a + t2_1.b) / 2) = t1_5.b)
1073 -> Seq Scan on prt1_e_p1 t2_1
1075 -> Seq Scan on prt2_p1 t1_5
1077 -> Index Scan using iprt1_p1_a on prt1_p1 t1_2
1078 Index Cond: (a = ((t2_1.a + t2_1.b) / 2))
1081 Join Filter: (t1_3.a = t1_6.b)
1085 Hash Cond: (((t2_2.a + t2_2.b) / 2) = t1_6.b)
1086 -> Seq Scan on prt1_e_p2 t2_2
1088 -> Seq Scan on prt2_p2 t1_6
1090 -> Index Scan using iprt1_p2_a on prt1_p2 t1_3
1091 Index Cond: (a = ((t2_2.a + t2_2.b) / 2))
1094 Join Filter: (t1_4.a = t1_7.b)
1098 -> Seq Scan on prt2_p3 t1_7
1100 -> Index Scan using iprt1_e_p3_ab2 on prt1_e_p3 t2_3
1101 Index Cond: (((a + b) / 2) = t1_7.b)
1102 -> Index Scan using iprt1_p3_a on prt1_p3 t1_4
1103 Index Cond: (a = ((t2_3.a + t2_3.b) / 2))
1107 SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.a = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.b = 0 ORDER BY t1.a;
1117 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.c = 0)) AND t1.b = 0 ORDER BY t1.a;
1119 ---------------------------------------------------------------------------
1127 Hash Cond: (t1_6.b = ((t1_9.a + t1_9.b) / 2))
1128 -> Seq Scan on prt2_p1 t1_6
1130 -> Seq Scan on prt1_e_p1 t1_9
1132 -> Index Scan using iprt1_p1_a on prt1_p1 t1_3
1133 Index Cond: (a = t1_6.b)
1139 Hash Cond: (t1_7.b = ((t1_10.a + t1_10.b) / 2))
1140 -> Seq Scan on prt2_p2 t1_7
1142 -> Seq Scan on prt1_e_p2 t1_10
1144 -> Index Scan using iprt1_p2_a on prt1_p2 t1_4
1145 Index Cond: (a = t1_7.b)
1151 Hash Cond: (t1_8.b = ((t1_11.a + t1_11.b) / 2))
1152 -> Seq Scan on prt2_p3 t1_8
1154 -> Seq Scan on prt1_e_p3 t1_11
1156 -> Index Scan using iprt1_p3_a on prt1_p3 t1_5
1157 Index Cond: (a = t1_8.b)
1161 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.c = 0)) AND t1.b = 0 ORDER BY t1.a;
1171 SET enable_hashjoin TO off;
1172 SET enable_nestloop TO off;
1174 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.c = 0)) AND t1.b = 0 ORDER BY t1.a;
1176 ------------------------------------------------------------------
1180 Merge Cond: (t1_3.a = t1_6.b)
1183 -> Seq Scan on prt1_p1 t1_3
1186 Merge Cond: (t1_6.b = (((t1_9.a + t1_9.b) / 2)))
1189 -> Seq Scan on prt2_p1 t1_6
1191 Sort Key: (((t1_9.a + t1_9.b) / 2))
1192 -> Seq Scan on prt1_e_p1 t1_9
1195 Merge Cond: (t1_4.a = t1_7.b)
1198 -> Seq Scan on prt1_p2 t1_4
1201 Merge Cond: (t1_7.b = (((t1_10.a + t1_10.b) / 2)))
1204 -> Seq Scan on prt2_p2 t1_7
1206 Sort Key: (((t1_10.a + t1_10.b) / 2))
1207 -> Seq Scan on prt1_e_p2 t1_10
1210 Merge Cond: (t1_5.a = t1_8.b)
1213 -> Seq Scan on prt1_p3 t1_5
1216 Merge Cond: (t1_8.b = (((t1_11.a + t1_11.b) / 2)))
1219 -> Seq Scan on prt2_p3 t1_8
1221 Sort Key: (((t1_11.a + t1_11.b) / 2))
1222 -> Seq Scan on prt1_e_p3 t1_11
1226 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.c = 0)) AND t1.b = 0 ORDER BY t1.a;
1236 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.c = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
1238 ----------------------------------------------------------------------------
1240 Sort Key: t1.a, t2.b, ((t3.a + t3.b))
1243 Merge Cond: (t1_1.a = t2_1.b)
1247 Merge Cond: ((((t3_1.a + t3_1.b) / 2)) = t1_1.a)
1249 Sort Key: (((t3_1.a + t3_1.b) / 2))
1250 -> Seq Scan on prt1_e_p1 t3_1
1254 -> Seq Scan on prt1_p1 t1_1
1257 -> Seq Scan on prt2_p1 t2_1
1259 Merge Cond: (t1_2.a = t2_2.b)
1263 Merge Cond: ((((t3_2.a + t3_2.b) / 2)) = t1_2.a)
1265 Sort Key: (((t3_2.a + t3_2.b) / 2))
1266 -> Seq Scan on prt1_e_p2 t3_2
1270 -> Seq Scan on prt1_p2 t1_2
1273 -> Seq Scan on prt2_p2 t2_2
1275 Merge Cond: (t1_3.a = t2_3.b)
1279 Merge Cond: ((((t3_3.a + t3_3.b) / 2)) = t1_3.a)
1281 Sort Key: (((t3_3.a + t3_3.b) / 2))
1282 -> Seq Scan on prt1_e_p3 t3_3
1286 -> Seq Scan on prt1_p3 t1_3
1289 -> Seq Scan on prt2_p3 t2_3
1292 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.c = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
1293 a | c | b | c | ?column? | c
1294 -----+------+-----+------+----------+---
1295 0 | 0000 | 0 | 0000 | 0 | 0
1296 50 | 0050 | | | 100 | 0
1297 100 | 0100 | | | 200 | 0
1298 150 | 0150 | 150 | 0150 | 300 | 0
1299 200 | 0200 | | | 400 | 0
1300 250 | 0250 | | | 500 | 0
1301 300 | 0300 | 300 | 0300 | 600 | 0
1302 350 | 0350 | | | 700 | 0
1303 400 | 0400 | | | 800 | 0
1304 450 | 0450 | 450 | 0450 | 900 | 0
1305 500 | 0500 | | | 1000 | 0
1306 550 | 0550 | | | 1100 | 0
1309 -- MergeAppend on nullable column
1310 -- This should generate a partitionwise join, but currently fails to
1312 SELECT t1.a, t2.b FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER BY t1.a, t2.b;
1314 -----------------------------------------------------------
1316 Sort Key: prt1.a, prt2.b
1317 Presorted Key: prt1.a
1319 Merge Cond: (prt1.a = prt2.b)
1323 -> Seq Scan on prt1_p1 prt1_1
1324 Filter: ((a < 450) AND (b = 0))
1325 -> Seq Scan on prt1_p2 prt1_2
1326 Filter: ((a < 450) AND (b = 0))
1330 -> Seq Scan on prt2_p2 prt2_1
1332 -> Seq Scan on prt2_p3 prt2_2
1336 SELECT t1.a, t2.b FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER BY t1.a, t2.b;
1350 -- merge join when expression with whole-row reference needs to be sorted;
1351 -- partitionwise join does not apply
1353 SELECT t1.a, t2.b FROM prt1 t1, prt2 t2 WHERE t1::text = t2::text AND t1.a = t2.b ORDER BY t1.a;
1355 -----------------------------------------------------------------------------------------
1357 Merge Cond: ((t1.a = t2.b) AND (((((t1.*)::prt1))::text) = ((((t2.*)::prt2))::text)))
1359 Sort Key: t1.a, ((((t1.*)::prt1))::text)
1362 -> Seq Scan on prt1_p1 t1_1
1363 -> Seq Scan on prt1_p2 t1_2
1364 -> Seq Scan on prt1_p3 t1_3
1366 Sort Key: t2.b, ((((t2.*)::prt2))::text)
1369 -> Seq Scan on prt2_p1 t2_1
1370 -> Seq Scan on prt2_p2 t2_2
1371 -> Seq Scan on prt2_p3 t2_3
1374 SELECT t1.a, t2.b FROM prt1 t1, prt2 t2 WHERE t1::text = t2::text AND t1.a = t2.b ORDER BY t1.a;
1384 RESET enable_hashjoin;
1385 RESET enable_nestloop;
1387 -- partitioned by multiple columns
1389 CREATE TABLE prt1_m (a int, b int, c int) PARTITION BY RANGE(a, ((a + b)/2));
1390 CREATE TABLE prt1_m_p1 PARTITION OF prt1_m FOR VALUES FROM (0, 0) TO (250, 250);
1391 CREATE TABLE prt1_m_p2 PARTITION OF prt1_m FOR VALUES FROM (250, 250) TO (500, 500);
1392 CREATE TABLE prt1_m_p3 PARTITION OF prt1_m FOR VALUES FROM (500, 500) TO (600, 600);
1393 INSERT INTO prt1_m SELECT i, i, i % 25 FROM generate_series(0, 599, 2) i;
1395 CREATE TABLE prt2_m (a int, b int, c int) PARTITION BY RANGE(((b + a)/2), b);
1396 CREATE TABLE prt2_m_p1 PARTITION OF prt2_m FOR VALUES FROM (0, 0) TO (250, 250);
1397 CREATE TABLE prt2_m_p2 PARTITION OF prt2_m FOR VALUES FROM (250, 250) TO (500, 500);
1398 CREATE TABLE prt2_m_p3 PARTITION OF prt2_m FOR VALUES FROM (500, 500) TO (600, 600);
1399 INSERT INTO prt2_m SELECT i, i, i % 25 FROM generate_series(0, 599, 3) i;
1402 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.c = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.c = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b;
1404 ------------------------------------------------------------------------------------------------------------------------------
1406 Sort Key: prt1_m.a, prt2_m.b
1409 Hash Cond: ((prt1_m_1.a = ((prt2_m_1.b + prt2_m_1.a) / 2)) AND (((prt1_m_1.a + prt1_m_1.b) / 2) = prt2_m_1.b))
1410 -> Seq Scan on prt1_m_p1 prt1_m_1
1413 -> Seq Scan on prt2_m_p1 prt2_m_1
1416 Hash Cond: ((prt1_m_2.a = ((prt2_m_2.b + prt2_m_2.a) / 2)) AND (((prt1_m_2.a + prt1_m_2.b) / 2) = prt2_m_2.b))
1417 -> Seq Scan on prt1_m_p2 prt1_m_2
1420 -> Seq Scan on prt2_m_p2 prt2_m_2
1423 Hash Cond: ((prt1_m_3.a = ((prt2_m_3.b + prt2_m_3.a) / 2)) AND (((prt1_m_3.a + prt1_m_3.b) / 2) = prt2_m_3.b))
1424 -> Seq Scan on prt1_m_p3 prt1_m_3
1427 -> Seq Scan on prt2_m_p3 prt2_m_3
1431 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.c = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.c = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b;
1453 -- tests for list partitioned tables.
1455 CREATE TABLE plt1 (a int, b int, c text) PARTITION BY LIST(c);
1456 CREATE TABLE plt1_p1 PARTITION OF plt1 FOR VALUES IN ('0000', '0003', '0004', '0010');
1457 CREATE TABLE plt1_p2 PARTITION OF plt1 FOR VALUES IN ('0001', '0005', '0002', '0009');
1458 CREATE TABLE plt1_p3 PARTITION OF plt1 FOR VALUES IN ('0006', '0007', '0008', '0011');
1459 INSERT INTO plt1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
1461 CREATE TABLE plt2 (a int, b int, c text) PARTITION BY LIST(c);
1462 CREATE TABLE plt2_p1 PARTITION OF plt2 FOR VALUES IN ('0000', '0003', '0004', '0010');
1463 CREATE TABLE plt2_p2 PARTITION OF plt2 FOR VALUES IN ('0001', '0005', '0002', '0009');
1464 CREATE TABLE plt2_p3 PARTITION OF plt2 FOR VALUES IN ('0006', '0007', '0008', '0011');
1465 INSERT INTO plt2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 3) i;
1468 -- list partitioned by expression
1470 CREATE TABLE plt1_e (a int, b int, c text) PARTITION BY LIST(ltrim(c, 'A'));
1471 CREATE TABLE plt1_e_p1 PARTITION OF plt1_e FOR VALUES IN ('0000', '0003', '0004', '0010');
1472 CREATE TABLE plt1_e_p2 PARTITION OF plt1_e FOR VALUES IN ('0001', '0005', '0002', '0009');
1473 CREATE TABLE plt1_e_p3 PARTITION OF plt1_e FOR VALUES IN ('0006', '0007', '0008', '0011');
1474 INSERT INTO plt1_e SELECT i, i, 'A' || to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
1476 -- test partition matching with N-way join
1478 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.b = t2.b AND 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;
1480 --------------------------------------------------------------------------------
1482 Group Key: t1.c, t3.c
1484 Sort Key: t1.c, t3.c
1487 Hash Cond: (t1_1.c = ltrim(t3_1.c, 'A'::text))
1489 Hash Cond: ((t1_1.b = t2_1.b) AND (t1_1.c = t2_1.c))
1490 -> Seq Scan on plt1_p1 t1_1
1492 -> Seq Scan on plt2_p1 t2_1
1494 -> Seq Scan on plt1_e_p1 t3_1
1496 Hash Cond: (t1_2.c = ltrim(t3_2.c, 'A'::text))
1498 Hash Cond: ((t1_2.b = t2_2.b) AND (t1_2.c = t2_2.c))
1499 -> Seq Scan on plt1_p2 t1_2
1501 -> Seq Scan on plt2_p2 t2_2
1503 -> Seq Scan on plt1_e_p2 t3_2
1505 Hash Cond: (t1_3.c = ltrim(t3_3.c, 'A'::text))
1507 Hash Cond: ((t1_3.b = t2_3.b) AND (t1_3.c = t2_3.c))
1508 -> Seq Scan on plt1_p3 t1_3
1510 -> Seq Scan on plt2_p3 t2_3
1512 -> Seq Scan on plt1_e_p3 t3_3
1515 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.b = t2.b AND 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;
1516 avg | avg | avg | c | c | c
1517 ----------------------+----------------------+-----------------------+------+------+-------
1518 24.0000000000000000 | 24.0000000000000000 | 48.0000000000000000 | 0000 | 0000 | A0000
1519 75.0000000000000000 | 75.0000000000000000 | 148.0000000000000000 | 0001 | 0001 | A0001
1520 123.0000000000000000 | 123.0000000000000000 | 248.0000000000000000 | 0002 | 0002 | A0002
1521 174.0000000000000000 | 174.0000000000000000 | 348.0000000000000000 | 0003 | 0003 | A0003
1522 225.0000000000000000 | 225.0000000000000000 | 448.0000000000000000 | 0004 | 0004 | A0004
1523 273.0000000000000000 | 273.0000000000000000 | 548.0000000000000000 | 0005 | 0005 | A0005
1524 324.0000000000000000 | 324.0000000000000000 | 648.0000000000000000 | 0006 | 0006 | A0006
1525 375.0000000000000000 | 375.0000000000000000 | 748.0000000000000000 | 0007 | 0007 | A0007
1526 423.0000000000000000 | 423.0000000000000000 | 848.0000000000000000 | 0008 | 0008 | A0008
1527 474.0000000000000000 | 474.0000000000000000 | 948.0000000000000000 | 0009 | 0009 | A0009
1528 525.0000000000000000 | 525.0000000000000000 | 1048.0000000000000000 | 0010 | 0010 | A0010
1529 573.0000000000000000 | 573.0000000000000000 | 1148.0000000000000000 | 0011 | 0011 | A0011
1532 -- joins where one of the relations is proven empty
1534 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;
1536 --------------------------
1538 One-Time Filter: false
1542 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;
1544 --------------------------
1546 One-Time Filter: false
1550 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, prt1 t3 WHERE t2.b = t3.a;
1552 --------------------------------------------------
1554 Hash Cond: (t2.b = a)
1557 Hash Cond: (t3_1.a = t2_1.b)
1558 -> Seq Scan on prt1_p1 t3_1
1560 -> Seq Scan on prt2_p1 t2_1
1562 Hash Cond: (t3_2.a = t2_2.b)
1563 -> Seq Scan on prt1_p2 t3_2
1565 -> Seq Scan on prt2_p2 t2_2
1567 Hash Cond: (t3_3.a = t2_3.b)
1568 -> Seq Scan on prt1_p3 t3_3
1570 -> Seq Scan on prt2_p3 t2_3
1573 One-Time Filter: false
1577 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 = 0 ORDER BY t1.a, t2.b;
1579 --------------------------------------------
1583 Hash Cond: (t2.b = a)
1585 -> Seq Scan on prt2_p1 t2_1
1587 -> Seq Scan on prt2_p2 t2_2
1589 -> Seq Scan on prt2_p3 t2_3
1593 One-Time Filter: false
1597 -- tests for hash partitioned tables.
1599 CREATE TABLE pht1 (a int, b int, c text) PARTITION BY HASH(c);
1600 CREATE TABLE pht1_p1 PARTITION OF pht1 FOR VALUES WITH (MODULUS 3, REMAINDER 0);
1601 CREATE TABLE pht1_p2 PARTITION OF pht1 FOR VALUES WITH (MODULUS 3, REMAINDER 1);
1602 CREATE TABLE pht1_p3 PARTITION OF pht1 FOR VALUES WITH (MODULUS 3, REMAINDER 2);
1603 INSERT INTO pht1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
1605 CREATE TABLE pht2 (a int, b int, c text) PARTITION BY HASH(c);
1606 CREATE TABLE pht2_p1 PARTITION OF pht2 FOR VALUES WITH (MODULUS 3, REMAINDER 0);
1607 CREATE TABLE pht2_p2 PARTITION OF pht2 FOR VALUES WITH (MODULUS 3, REMAINDER 1);
1608 CREATE TABLE pht2_p3 PARTITION OF pht2 FOR VALUES WITH (MODULUS 3, REMAINDER 2);
1609 INSERT INTO pht2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 3) i;
1612 -- hash partitioned by expression
1614 CREATE TABLE pht1_e (a int, b int, c text) PARTITION BY HASH(ltrim(c, 'A'));
1615 CREATE TABLE pht1_e_p1 PARTITION OF pht1_e FOR VALUES WITH (MODULUS 3, REMAINDER 0);
1616 CREATE TABLE pht1_e_p2 PARTITION OF pht1_e FOR VALUES WITH (MODULUS 3, REMAINDER 1);
1617 CREATE TABLE pht1_e_p3 PARTITION OF pht1_e FOR VALUES WITH (MODULUS 3, REMAINDER 2);
1618 INSERT INTO pht1_e SELECT i, i, 'A' || to_char(i/50, 'FM0000') FROM generate_series(0, 299, 2) i;
1620 -- test partition matching with N-way join
1622 SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM pht1 t1, pht2 t2, pht1_e t3 WHERE t1.b = t2.b AND 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;
1624 --------------------------------------------------------------------------------
1626 Group Key: t1.c, t3.c
1628 Sort Key: t1.c, t3.c
1631 Hash Cond: (t1_1.c = ltrim(t3_1.c, 'A'::text))
1633 Hash Cond: ((t1_1.b = t2_1.b) AND (t1_1.c = t2_1.c))
1634 -> Seq Scan on pht1_p1 t1_1
1636 -> Seq Scan on pht2_p1 t2_1
1638 -> Seq Scan on pht1_e_p1 t3_1
1640 Hash Cond: (t1_2.c = ltrim(t3_2.c, 'A'::text))
1642 Hash Cond: ((t1_2.b = t2_2.b) AND (t1_2.c = t2_2.c))
1643 -> Seq Scan on pht1_p2 t1_2
1645 -> Seq Scan on pht2_p2 t2_2
1647 -> Seq Scan on pht1_e_p2 t3_2
1649 Hash Cond: (t1_3.c = ltrim(t3_3.c, 'A'::text))
1651 Hash Cond: ((t1_3.b = t2_3.b) AND (t1_3.c = t2_3.c))
1652 -> Seq Scan on pht1_p3 t1_3
1654 -> Seq Scan on pht2_p3 t2_3
1656 -> Seq Scan on pht1_e_p3 t3_3
1659 SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM pht1 t1, pht2 t2, pht1_e t3 WHERE t1.b = t2.b AND 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;
1660 avg | avg | avg | c | c | c
1661 ----------------------+----------------------+----------------------+------+------+-------
1662 24.0000000000000000 | 24.0000000000000000 | 48.0000000000000000 | 0000 | 0000 | A0000
1663 75.0000000000000000 | 75.0000000000000000 | 148.0000000000000000 | 0001 | 0001 | A0001
1664 123.0000000000000000 | 123.0000000000000000 | 248.0000000000000000 | 0002 | 0002 | A0002
1665 174.0000000000000000 | 174.0000000000000000 | 348.0000000000000000 | 0003 | 0003 | A0003
1666 225.0000000000000000 | 225.0000000000000000 | 448.0000000000000000 | 0004 | 0004 | A0004
1667 273.0000000000000000 | 273.0000000000000000 | 548.0000000000000000 | 0005 | 0005 | A0005
1670 -- test default partition behavior for range
1671 ALTER TABLE prt1 DETACH PARTITION prt1_p3;
1672 ALTER TABLE prt1 ATTACH PARTITION prt1_p3 DEFAULT;
1674 ALTER TABLE prt2 DETACH PARTITION prt2_p3;
1675 ALTER TABLE prt2 ATTACH PARTITION prt2_p3 DEFAULT;
1678 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b;
1680 --------------------------------------------------
1685 Hash Cond: (t2_1.b = t1_1.a)
1686 -> Seq Scan on prt2_p1 t2_1
1688 -> Seq Scan on prt1_p1 t1_1
1691 Hash Cond: (t2_2.b = t1_2.a)
1692 -> Seq Scan on prt2_p2 t2_2
1694 -> Seq Scan on prt1_p2 t1_2
1697 Hash Cond: (t2_3.b = t1_3.a)
1698 -> Seq Scan on prt2_p3 t2_3
1700 -> Seq Scan on prt1_p3 t1_3
1704 -- test default partition behavior for list
1705 ALTER TABLE plt1 DETACH PARTITION plt1_p3;
1706 ALTER TABLE plt1 ATTACH PARTITION plt1_p3 DEFAULT;
1708 ALTER TABLE plt2 DETACH PARTITION plt2_p3;
1709 ALTER TABLE plt2 ATTACH PARTITION plt2_p3 DEFAULT;
1712 SELECT avg(t1.a), avg(t2.b), t1.c, t2.c FROM plt1 t1 RIGHT JOIN plt2 t2 ON t1.c = t2.c WHERE t1.a % 25 = 0 GROUP BY t1.c, t2.c ORDER BY t1.c, t2.c;
1714 --------------------------------------------------------
1721 Hash Cond: (t2_1.c = t1_1.c)
1722 -> Seq Scan on plt2_p1 t2_1
1724 -> Seq Scan on plt1_p1 t1_1
1725 Filter: ((a % 25) = 0)
1727 Hash Cond: (t2_2.c = t1_2.c)
1728 -> Seq Scan on plt2_p2 t2_2
1730 -> Seq Scan on plt1_p2 t1_2
1731 Filter: ((a % 25) = 0)
1733 Hash Cond: (t2_3.c = t1_3.c)
1734 -> Seq Scan on plt2_p3 t2_3
1736 -> Seq Scan on plt1_p3 t1_3
1737 Filter: ((a % 25) = 0)
1741 -- multiple levels of partitioning
1743 CREATE TABLE prt1_l (a int, b int, c varchar) PARTITION BY RANGE(a);
1744 CREATE TABLE prt1_l_p1 PARTITION OF prt1_l FOR VALUES FROM (0) TO (250);
1745 CREATE TABLE prt1_l_p2 PARTITION OF prt1_l FOR VALUES FROM (250) TO (500) PARTITION BY LIST (c);
1746 CREATE TABLE prt1_l_p2_p1 PARTITION OF prt1_l_p2 FOR VALUES IN ('0000', '0001');
1747 CREATE TABLE prt1_l_p2_p2 PARTITION OF prt1_l_p2 FOR VALUES IN ('0002', '0003');
1748 CREATE TABLE prt1_l_p3 PARTITION OF prt1_l FOR VALUES FROM (500) TO (600) PARTITION BY RANGE (b);
1749 CREATE TABLE prt1_l_p3_p1 PARTITION OF prt1_l_p3 FOR VALUES FROM (0) TO (13);
1750 CREATE TABLE prt1_l_p3_p2 PARTITION OF prt1_l_p3 FOR VALUES FROM (13) TO (25);
1751 INSERT INTO prt1_l SELECT i, i % 25, to_char(i % 4, 'FM0000') FROM generate_series(0, 599, 2) i;
1753 CREATE TABLE prt2_l (a int, b int, c varchar) PARTITION BY RANGE(b);
1754 CREATE TABLE prt2_l_p1 PARTITION OF prt2_l FOR VALUES FROM (0) TO (250);
1755 CREATE TABLE prt2_l_p2 PARTITION OF prt2_l FOR VALUES FROM (250) TO (500) PARTITION BY LIST (c);
1756 CREATE TABLE prt2_l_p2_p1 PARTITION OF prt2_l_p2 FOR VALUES IN ('0000', '0001');
1757 CREATE TABLE prt2_l_p2_p2 PARTITION OF prt2_l_p2 FOR VALUES IN ('0002', '0003');
1758 CREATE TABLE prt2_l_p3 PARTITION OF prt2_l FOR VALUES FROM (500) TO (600) PARTITION BY RANGE (a);
1759 CREATE TABLE prt2_l_p3_p1 PARTITION OF prt2_l_p3 FOR VALUES FROM (0) TO (13);
1760 CREATE TABLE prt2_l_p3_p2 PARTITION OF prt2_l_p3 FOR VALUES FROM (13) TO (25);
1761 INSERT INTO prt2_l SELECT i % 25, i, to_char(i % 4, 'FM0000') FROM generate_series(0, 599, 3) i;
1763 -- inner join, qual covering only top-level partitions
1765 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b;
1767 -------------------------------------------------------------
1772 Hash Cond: (t2_1.b = t1_1.a)
1773 -> Seq Scan on prt2_l_p1 t2_1
1775 -> Seq Scan on prt1_l_p1 t1_1
1778 Hash Cond: (t2_3.b = t1_3.a)
1780 -> Seq Scan on prt2_l_p2_p1 t2_3
1781 -> Seq Scan on prt2_l_p2_p2 t2_4
1784 -> Seq Scan on prt1_l_p2_p1 t1_3
1786 -> Seq Scan on prt1_l_p2_p2 t1_4
1789 Hash Cond: (t2_6.b = t1_5.a)
1791 -> Seq Scan on prt2_l_p3_p1 t2_6
1792 -> Seq Scan on prt2_l_p3_p2 t2_7
1794 -> Seq Scan on prt1_l_p3_p1 t1_5
1798 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b;
1800 -----+------+-----+------
1802 150 | 0002 | 150 | 0002
1803 300 | 0000 | 300 | 0000
1804 450 | 0002 | 450 | 0002
1809 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 LEFT JOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t1.b = 0 ORDER BY t1.a, t2.b;
1811 ------------------------------------------------------------------------------------
1813 Sort Key: t1.a, t2.b
1816 Hash Cond: ((t2_1.b = t1_1.a) AND ((t2_1.c)::text = (t1_1.c)::text))
1817 -> Seq Scan on prt2_l_p1 t2_1
1819 -> Seq Scan on prt1_l_p1 t1_1
1822 Hash Cond: ((t2_2.b = t1_2.a) AND ((t2_2.c)::text = (t1_2.c)::text))
1823 -> Seq Scan on prt2_l_p2_p1 t2_2
1825 -> Seq Scan on prt1_l_p2_p1 t1_2
1828 Hash Cond: ((t2_3.b = t1_3.a) AND ((t2_3.c)::text = (t1_3.c)::text))
1829 -> Seq Scan on prt2_l_p2_p2 t2_3
1831 -> Seq Scan on prt1_l_p2_p2 t1_3
1834 Hash Cond: ((t2_5.b = t1_4.a) AND ((t2_5.c)::text = (t1_4.c)::text))
1836 -> Seq Scan on prt2_l_p3_p1 t2_5
1837 -> Seq Scan on prt2_l_p3_p2 t2_6
1839 -> Seq Scan on prt1_l_p3_p1 t1_4
1843 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 LEFT JOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t1.b = 0 ORDER BY t1.a, t2.b;
1845 -----+------+-----+------
1849 150 | 0002 | 150 | 0002
1852 300 | 0000 | 300 | 0000
1855 450 | 0002 | 450 | 0002
1862 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t2.a = 0 ORDER BY t1.a, t2.b;
1864 ------------------------------------------------------------------------------------
1866 Sort Key: t1.a, t2.b
1869 Hash Cond: ((t1_1.a = t2_1.b) AND ((t1_1.c)::text = (t2_1.c)::text))
1870 -> Seq Scan on prt1_l_p1 t1_1
1872 -> Seq Scan on prt2_l_p1 t2_1
1875 Hash Cond: ((t1_2.a = t2_2.b) AND ((t1_2.c)::text = (t2_2.c)::text))
1876 -> Seq Scan on prt1_l_p2_p1 t1_2
1878 -> Seq Scan on prt2_l_p2_p1 t2_2
1881 Hash Cond: ((t1_3.a = t2_3.b) AND ((t1_3.c)::text = (t2_3.c)::text))
1882 -> Seq Scan on prt1_l_p2_p2 t1_3
1884 -> Seq Scan on prt2_l_p2_p2 t2_3
1887 Hash Cond: ((t1_5.a = t2_4.b) AND ((t1_5.c)::text = (t2_4.c)::text))
1889 -> Seq Scan on prt1_l_p3_p1 t1_5
1890 -> Seq Scan on prt1_l_p3_p2 t1_6
1892 -> Seq Scan on prt2_l_p3_p1 t2_4
1896 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t2.a = 0 ORDER BY t1.a, t2.b;
1898 -----+------+-----+------
1900 150 | 0002 | 150 | 0002
1901 300 | 0000 | 300 | 0000
1902 450 | 0002 | 450 | 0002
1911 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE prt1_l.b = 0) t1 FULL JOIN (SELECT * FROM prt2_l WHERE prt2_l.a = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c) ORDER BY t1.a, t2.b;
1913 ----------------------------------------------------------------------------------------------------
1915 Sort Key: prt1_l.a, prt2_l.b
1918 Hash Cond: ((prt1_l_1.a = prt2_l_1.b) AND ((prt1_l_1.c)::text = (prt2_l_1.c)::text))
1919 -> Seq Scan on prt1_l_p1 prt1_l_1
1922 -> Seq Scan on prt2_l_p1 prt2_l_1
1925 Hash Cond: ((prt1_l_2.a = prt2_l_2.b) AND ((prt1_l_2.c)::text = (prt2_l_2.c)::text))
1926 -> Seq Scan on prt1_l_p2_p1 prt1_l_2
1929 -> Seq Scan on prt2_l_p2_p1 prt2_l_2
1932 Hash Cond: ((prt1_l_3.a = prt2_l_3.b) AND ((prt1_l_3.c)::text = (prt2_l_3.c)::text))
1933 -> Seq Scan on prt1_l_p2_p2 prt1_l_3
1936 -> Seq Scan on prt2_l_p2_p2 prt2_l_3
1939 Hash Cond: ((prt1_l_4.a = prt2_l_4.b) AND ((prt1_l_4.c)::text = (prt2_l_4.c)::text))
1940 -> Seq Scan on prt1_l_p3_p1 prt1_l_4
1943 -> Seq Scan on prt2_l_p3_p1 prt2_l_4
1947 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE prt1_l.b = 0) t1 FULL JOIN (SELECT * FROM prt2_l WHERE prt2_l.a = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c) ORDER BY t1.a, t2.b;
1949 -----+------+-----+------
1953 150 | 0002 | 150 | 0002
1956 300 | 0000 | 300 | 0000
1959 450 | 0002 | 450 | 0002
1968 -- lateral partitionwise join
1970 SELECT * FROM prt1_l t1 LEFT JOIN LATERAL
1971 (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.b AS t3b, least(t1.a,t2.a,t3.b) FROM prt1_l t2 JOIN prt2_l t3 ON (t2.a = t3.b AND t2.c = t3.c)) ss
1972 ON t1.a = ss.t2a AND t1.c = ss.t2c WHERE t1.b = 0 ORDER BY t1.a;
1974 -----------------------------------------------------------------------------------------------
1978 -> Nested Loop Left Join
1979 -> Seq Scan on prt1_l_p1 t1_1
1982 Hash Cond: ((t3_1.b = t2_1.a) AND ((t3_1.c)::text = (t2_1.c)::text))
1983 -> Seq Scan on prt2_l_p1 t3_1
1985 -> Seq Scan on prt1_l_p1 t2_1
1986 Filter: ((t1_1.a = a) AND ((t1_1.c)::text = (c)::text))
1987 -> Nested Loop Left Join
1988 -> Seq Scan on prt1_l_p2_p1 t1_2
1991 Hash Cond: ((t3_2.b = t2_2.a) AND ((t3_2.c)::text = (t2_2.c)::text))
1992 -> Seq Scan on prt2_l_p2_p1 t3_2
1994 -> Seq Scan on prt1_l_p2_p1 t2_2
1995 Filter: ((t1_2.a = a) AND ((t1_2.c)::text = (c)::text))
1996 -> Nested Loop Left Join
1997 -> Seq Scan on prt1_l_p2_p2 t1_3
2000 Hash Cond: ((t3_3.b = t2_3.a) AND ((t3_3.c)::text = (t2_3.c)::text))
2001 -> Seq Scan on prt2_l_p2_p2 t3_3
2003 -> Seq Scan on prt1_l_p2_p2 t2_3
2004 Filter: ((t1_3.a = a) AND ((t1_3.c)::text = (c)::text))
2005 -> Nested Loop Left Join
2006 -> Seq Scan on prt1_l_p3_p1 t1_4
2009 Hash Cond: ((t3_5.b = t2_5.a) AND ((t3_5.c)::text = (t2_5.c)::text))
2011 -> Seq Scan on prt2_l_p3_p1 t3_5
2012 -> Seq Scan on prt2_l_p3_p2 t3_6
2015 -> Seq Scan on prt1_l_p3_p1 t2_5
2016 Filter: ((t1_4.a = a) AND ((t1_4.c)::text = (c)::text))
2017 -> Seq Scan on prt1_l_p3_p2 t2_6
2018 Filter: ((t1_4.a = a) AND ((t1_4.c)::text = (c)::text))
2021 SELECT * FROM prt1_l t1 LEFT JOIN LATERAL
2022 (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.b AS t3b, least(t1.a,t2.a,t3.b) FROM prt1_l t2 JOIN prt2_l t3 ON (t2.a = t3.b AND t2.c = t3.c)) ss
2023 ON t1.a = ss.t2a AND t1.c = ss.t2c WHERE t1.b = 0 ORDER BY t1.a;
2024 a | b | c | t2a | t2c | t2b | t3b | least
2025 -----+---+------+-----+------+-----+-----+-------
2026 0 | 0 | 0000 | 0 | 0000 | 0 | 0 | 0
2027 50 | 0 | 0002 | | | | |
2028 100 | 0 | 0000 | | | | |
2029 150 | 0 | 0002 | 150 | 0002 | 0 | 150 | 150
2030 200 | 0 | 0000 | | | | |
2031 250 | 0 | 0002 | | | | |
2032 300 | 0 | 0000 | 300 | 0000 | 0 | 300 | 300
2033 350 | 0 | 0002 | | | | |
2034 400 | 0 | 0000 | | | | |
2035 450 | 0 | 0002 | 450 | 0002 | 0 | 450 | 450
2036 500 | 0 | 0000 | | | | |
2037 550 | 0 | 0002 | | | | |
2040 SET max_parallel_workers_per_gather = 0;
2041 -- If there are lateral references to the other relation in sample scan,
2042 -- we cannot generate a partitionwise join.
2044 SELECT * FROM prt1_l t1 JOIN LATERAL
2045 (SELECT * FROM prt1_l t2 TABLESAMPLE SYSTEM (t1.a) REPEATABLE(t1.b)) s
2046 ON t1.a = s.a AND t1.b = s.b AND t1.c = s.c;
2048 ----------------------------------------------------------------------------------
2051 -> Seq Scan on prt1_l_p1 t1_1
2052 -> Seq Scan on prt1_l_p2_p1 t1_2
2053 -> Seq Scan on prt1_l_p2_p2 t1_3
2054 -> Seq Scan on prt1_l_p3_p1 t1_4
2055 -> Seq Scan on prt1_l_p3_p2 t1_5
2057 -> Sample Scan on prt1_l_p1 t2_1
2058 Sampling: system (t1.a) REPEATABLE (t1.b)
2059 Filter: ((t1.a = a) AND (t1.b = b) AND ((t1.c)::text = (c)::text))
2060 -> Sample Scan on prt1_l_p2_p1 t2_2
2061 Sampling: system (t1.a) REPEATABLE (t1.b)
2062 Filter: ((t1.a = a) AND (t1.b = b) AND ((t1.c)::text = (c)::text))
2063 -> Sample Scan on prt1_l_p2_p2 t2_3
2064 Sampling: system (t1.a) REPEATABLE (t1.b)
2065 Filter: ((t1.a = a) AND (t1.b = b) AND ((t1.c)::text = (c)::text))
2066 -> Sample Scan on prt1_l_p3_p1 t2_4
2067 Sampling: system (t1.a) REPEATABLE (t1.b)
2068 Filter: ((t1.a = a) AND (t1.b = b) AND ((t1.c)::text = (c)::text))
2069 -> Sample Scan on prt1_l_p3_p2 t2_5
2070 Sampling: system (t1.a) REPEATABLE (t1.b)
2071 Filter: ((t1.a = a) AND (t1.b = b) AND ((t1.c)::text = (c)::text))
2074 -- If there are lateral references to the other relation in scan's restriction
2075 -- clauses, we cannot generate a partitionwise join.
2077 SELECT COUNT(*) FROM prt1_l t1 LEFT JOIN LATERAL
2078 (SELECT t1.b AS t1b, t2.* FROM prt2_l t2) s
2079 ON t1.a = s.b AND t1.b = s.a AND t1.c = s.c
2082 -------------------------------------------------------------------------------------------------------
2086 -> Seq Scan on prt1_l_p1 t1_1
2087 -> Seq Scan on prt1_l_p2_p1 t1_2
2088 -> Seq Scan on prt1_l_p2_p2 t1_3
2089 -> Seq Scan on prt1_l_p3_p1 t1_4
2090 -> Seq Scan on prt1_l_p3_p2 t1_5
2092 -> Seq Scan on prt2_l_p1 t2_1
2093 Filter: ((a = t1.b) AND (t1.a = b) AND (t1.b = a) AND ((t1.c)::text = (c)::text))
2094 -> Seq Scan on prt2_l_p2_p1 t2_2
2095 Filter: ((a = t1.b) AND (t1.a = b) AND (t1.b = a) AND ((t1.c)::text = (c)::text))
2096 -> Seq Scan on prt2_l_p2_p2 t2_3
2097 Filter: ((a = t1.b) AND (t1.a = b) AND (t1.b = a) AND ((t1.c)::text = (c)::text))
2098 -> Seq Scan on prt2_l_p3_p1 t2_4
2099 Filter: ((a = t1.b) AND (t1.a = b) AND (t1.b = a) AND ((t1.c)::text = (c)::text))
2100 -> Seq Scan on prt2_l_p3_p2 t2_5
2101 Filter: ((a = t1.b) AND (t1.a = b) AND (t1.b = a) AND ((t1.c)::text = (c)::text))
2104 SELECT COUNT(*) FROM prt1_l t1 LEFT JOIN LATERAL
2105 (SELECT t1.b AS t1b, t2.* FROM prt2_l t2) s
2106 ON t1.a = s.b AND t1.b = s.a AND t1.c = s.c
2113 RESET max_parallel_workers_per_gather;
2114 -- join with one side empty
2116 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c;
2118 -------------------------------------------------------------------------
2120 Hash Cond: ((t2.b = a) AND (t2.a = b) AND ((t2.c)::text = (c)::text))
2122 -> Seq Scan on prt2_l_p1 t2_1
2123 -> Seq Scan on prt2_l_p2_p1 t2_2
2124 -> Seq Scan on prt2_l_p2_p2 t2_3
2125 -> Seq Scan on prt2_l_p3_p1 t2_4
2126 -> Seq Scan on prt2_l_p3_p2 t2_5
2129 One-Time Filter: false
2132 -- Test case to verify proper handling of subqueries in a partitioned delete.
2133 -- The weird-looking lateral join is just there to force creation of a
2134 -- nestloop parameter within the subquery, which exposes the problem if the
2135 -- planner fails to make multiple copies of the subquery as appropriate.
2141 LATERAL (SELECT int4_tbl.f1 FROM int8_tbl LIMIT 2) ss
2142 WHERE prt1_l.c IS NULL);
2144 ----------------------------------------------------------
2146 Delete on prt1_l_p1 prt1_l_1
2147 Delete on prt1_l_p3_p1 prt1_l_2
2148 Delete on prt1_l_p3_p2 prt1_l_3
2149 -> Nested Loop Semi Join
2151 -> Seq Scan on prt1_l_p1 prt1_l_1
2153 -> Seq Scan on prt1_l_p3_p1 prt1_l_2
2155 -> Seq Scan on prt1_l_p3_p2 prt1_l_3
2159 -> Seq Scan on int4_tbl
2160 -> Subquery Scan on ss
2162 -> Seq Scan on int8_tbl
2166 -- negative testcases
2168 CREATE TABLE prt1_n (a int, b int, c varchar) PARTITION BY RANGE(c);
2169 CREATE TABLE prt1_n_p1 PARTITION OF prt1_n FOR VALUES FROM ('0000') TO ('0250');
2170 CREATE TABLE prt1_n_p2 PARTITION OF prt1_n FOR VALUES FROM ('0250') TO ('0500');
2171 INSERT INTO prt1_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 499, 2) i;
2173 CREATE TABLE prt2_n (a int, b int, c text) PARTITION BY LIST(c);
2174 CREATE TABLE prt2_n_p1 PARTITION OF prt2_n FOR VALUES IN ('0000', '0003', '0004', '0010', '0006', '0007');
2175 CREATE TABLE prt2_n_p2 PARTITION OF prt2_n FOR VALUES IN ('0001', '0005', '0002', '0009', '0008', '0011');
2176 INSERT INTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
2178 CREATE TABLE prt3_n (a int, b int, c text) PARTITION BY LIST(c);
2179 CREATE TABLE prt3_n_p1 PARTITION OF prt3_n FOR VALUES IN ('0000', '0004', '0006', '0007');
2180 CREATE TABLE prt3_n_p2 PARTITION OF prt3_n FOR VALUES IN ('0001', '0002', '0008', '0010');
2181 CREATE TABLE prt3_n_p3 PARTITION OF prt3_n FOR VALUES IN ('0003', '0005', '0009', '0011');
2182 INSERT INTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
2184 CREATE TABLE prt4_n (a int, b int, c text) PARTITION BY RANGE(a);
2185 CREATE TABLE prt4_n_p1 PARTITION OF prt4_n FOR VALUES FROM (0) TO (300);
2186 CREATE TABLE prt4_n_p2 PARTITION OF prt4_n FOR VALUES FROM (300) TO (500);
2187 CREATE TABLE prt4_n_p3 PARTITION OF prt4_n FOR VALUES FROM (500) TO (600);
2188 INSERT INTO prt4_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
2190 -- partitionwise join can not be applied if the partition ranges differ
2192 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2 WHERE t1.a = t2.a;
2194 ----------------------------------------------
2196 Hash Cond: (t1.a = t2.a)
2198 -> Seq Scan on prt1_p1 t1_1
2199 -> Seq Scan on prt1_p2 t1_2
2200 -> Seq Scan on prt1_p3 t1_3
2203 -> Seq Scan on prt4_n_p1 t2_1
2204 -> Seq Scan on prt4_n_p2 t2_2
2205 -> Seq Scan on prt4_n_p3 t2_3
2209 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2, prt2 t3 WHERE t1.a = t2.a and t1.a = t3.b;
2211 --------------------------------------------------------
2213 Hash Cond: (t2.a = t1.a)
2215 -> Seq Scan on prt4_n_p1 t2_1
2216 -> Seq Scan on prt4_n_p2 t2_2
2217 -> Seq Scan on prt4_n_p3 t2_3
2221 Hash Cond: (t1_1.a = t3_1.b)
2222 -> Seq Scan on prt1_p1 t1_1
2224 -> Seq Scan on prt2_p1 t3_1
2226 Hash Cond: (t1_2.a = t3_2.b)
2227 -> Seq Scan on prt1_p2 t1_2
2229 -> Seq Scan on prt2_p2 t3_2
2231 Hash Cond: (t1_3.a = t3_3.b)
2232 -> Seq Scan on prt1_p3 t1_3
2234 -> Seq Scan on prt2_p3 t3_3
2237 -- partitionwise join can not be applied if there are no equi-join conditions
2238 -- between partition keys
2240 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON (t1.a < t2.b);
2242 ---------------------------------------------------------
2243 Nested Loop Left Join
2245 -> Seq Scan on prt1_p1 t1_1
2246 -> Seq Scan on prt1_p2 t1_2
2247 -> Seq Scan on prt1_p3 t1_3
2249 -> Index Scan using iprt2_p1_b on prt2_p1 t2_1
2250 Index Cond: (b > t1.a)
2251 -> Index Scan using iprt2_p2_b on prt2_p2 t2_2
2252 Index Cond: (b > t1.a)
2253 -> Index Scan using iprt2_p3_b on prt2_p3 t2_3
2254 Index Cond: (b > t1.a)
2257 -- equi-join with join condition on partial keys does not qualify for
2258 -- partitionwise join
2260 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1, prt2_m t2 WHERE t1.a = (t2.b + t2.a)/2;
2262 ----------------------------------------------
2264 Hash Cond: (((t2.b + t2.a) / 2) = t1.a)
2266 -> Seq Scan on prt2_m_p1 t2_1
2267 -> Seq Scan on prt2_m_p2 t2_2
2268 -> Seq Scan on prt2_m_p3 t2_3
2271 -> Seq Scan on prt1_m_p1 t1_1
2272 -> Seq Scan on prt1_m_p2 t1_2
2273 -> Seq Scan on prt1_m_p3 t1_3
2276 -- equi-join between out-of-order partition key columns does not qualify for
2277 -- partitionwise join
2279 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.a = t2.b;
2281 ----------------------------------------------
2283 Hash Cond: (t1.a = t2.b)
2285 -> Seq Scan on prt1_m_p1 t1_1
2286 -> Seq Scan on prt1_m_p2 t1_2
2287 -> Seq Scan on prt1_m_p3 t1_3
2290 -> Seq Scan on prt2_m_p1 t2_1
2291 -> Seq Scan on prt2_m_p2 t2_2
2292 -> Seq Scan on prt2_m_p3 t2_3
2295 -- equi-join between non-key columns does not qualify for partitionwise join
2297 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.c = t2.c;
2299 ----------------------------------------------
2301 Hash Cond: (t1.c = t2.c)
2303 -> Seq Scan on prt1_m_p1 t1_1
2304 -> Seq Scan on prt1_m_p2 t1_2
2305 -> Seq Scan on prt1_m_p3 t1_3
2308 -> Seq Scan on prt2_m_p1 t2_1
2309 -> Seq Scan on prt2_m_p2 t2_2
2310 -> Seq Scan on prt2_m_p3 t2_3
2313 -- partitionwise join can not be applied for a join between list and range
2314 -- partitioned tables
2316 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 LEFT JOIN prt2_n t2 ON (t1.c = t2.c);
2318 ----------------------------------------------
2320 Hash Cond: (t2.c = (t1.c)::text)
2322 -> Seq Scan on prt2_n_p1 t2_1
2323 -> Seq Scan on prt2_n_p2 t2_2
2326 -> Seq Scan on prt1_n_p1 t1_1
2327 -> Seq Scan on prt1_n_p2 t1_2
2330 -- partitionwise join can not be applied between tables with different
2333 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 JOIN prt2_n t2 ON (t1.c = t2.c) JOIN plt1 t3 ON (t1.c = t3.c);
2335 ----------------------------------------------------------
2337 Hash Cond: (t2.c = (t1.c)::text)
2339 -> Seq Scan on prt2_n_p1 t2_1
2340 -> Seq Scan on prt2_n_p2 t2_2
2343 Hash Cond: (t3.c = (t1.c)::text)
2345 -> Seq Scan on plt1_p1 t3_1
2346 -> Seq Scan on plt1_p2 t3_2
2347 -> Seq Scan on plt1_p3 t3_3
2350 -> Seq Scan on prt1_n_p1 t1_1
2351 -> Seq Scan on prt1_n_p2 t1_2
2354 -- partitionwise join can not be applied for a join between key column and
2357 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c);
2359 ----------------------------------------------
2361 Hash Cond: ((t2.c)::text = (t1.c)::text)
2363 -> Seq Scan on prt1_p1 t2_1
2364 -> Seq Scan on prt1_p2 t2_2
2365 -> Seq Scan on prt1_p3 t2_3
2368 -> Seq Scan on prt1_n_p1 t1_1
2369 -> Seq Scan on prt1_n_p2 t1_2
2373 -- Test some other plan types in a partitionwise join (unfortunately,
2374 -- we need larger tables to get the planner to choose these plan types)
2376 create temp table prtx1 (a integer, b integer, c integer)
2377 partition by range (a);
2378 create temp table prtx1_1 partition of prtx1 for values from (1) to (11);
2379 create temp table prtx1_2 partition of prtx1 for values from (11) to (21);
2380 create temp table prtx1_3 partition of prtx1 for values from (21) to (31);
2381 create temp table prtx2 (a integer, b integer, c integer)
2382 partition by range (a);
2383 create temp table prtx2_1 partition of prtx2 for values from (1) to (11);
2384 create temp table prtx2_2 partition of prtx2 for values from (11) to (21);
2385 create temp table prtx2_3 partition of prtx2 for values from (21) to (31);
2386 insert into prtx1 select 1 + i%30, i, i
2387 from generate_series(1,1000) i;
2388 insert into prtx2 select 1 + i%30, i, i
2389 from generate_series(1,500) i, generate_series(1,10) j;
2390 create index on prtx2 (b);
2391 create index on prtx2 (c);
2396 where not exists (select 1 from prtx2
2397 where prtx2.a=prtx1.a and prtx2.b=prtx1.b and prtx2.c=123)
2400 -------------------------------------------------------------
2402 -> Nested Loop Anti Join
2403 -> Seq Scan on prtx1_1
2404 Filter: ((a < 20) AND (c = 120))
2405 -> Bitmap Heap Scan on prtx2_1
2406 Recheck Cond: ((b = prtx1_1.b) AND (c = 123))
2407 Filter: (a = prtx1_1.a)
2409 -> Bitmap Index Scan on prtx2_1_b_idx
2410 Index Cond: (b = prtx1_1.b)
2411 -> Bitmap Index Scan on prtx2_1_c_idx
2412 Index Cond: (c = 123)
2413 -> Nested Loop Anti Join
2414 -> Seq Scan on prtx1_2
2415 Filter: ((a < 20) AND (c = 120))
2416 -> Bitmap Heap Scan on prtx2_2
2417 Recheck Cond: ((b = prtx1_2.b) AND (c = 123))
2418 Filter: (a = prtx1_2.a)
2420 -> Bitmap Index Scan on prtx2_2_b_idx
2421 Index Cond: (b = prtx1_2.b)
2422 -> Bitmap Index Scan on prtx2_2_c_idx
2423 Index Cond: (c = 123)
2427 where not exists (select 1 from prtx2
2428 where prtx2.a=prtx1.a and prtx2.b=prtx1.b and prtx2.c=123)
2437 where not exists (select 1 from prtx2
2438 where prtx2.a=prtx1.a and (prtx2.b=prtx1.b+1 or prtx2.c=99))
2441 -----------------------------------------------------------------
2443 -> Nested Loop Anti Join
2444 -> Seq Scan on prtx1_1
2445 Filter: ((a < 20) AND (c = 91))
2446 -> Bitmap Heap Scan on prtx2_1
2447 Recheck Cond: ((b = (prtx1_1.b + 1)) OR (c = 99))
2448 Filter: (a = prtx1_1.a)
2450 -> Bitmap Index Scan on prtx2_1_b_idx
2451 Index Cond: (b = (prtx1_1.b + 1))
2452 -> Bitmap Index Scan on prtx2_1_c_idx
2453 Index Cond: (c = 99)
2454 -> Nested Loop Anti Join
2455 -> Seq Scan on prtx1_2
2456 Filter: ((a < 20) AND (c = 91))
2457 -> Bitmap Heap Scan on prtx2_2
2458 Recheck Cond: ((b = (prtx1_2.b + 1)) OR (c = 99))
2459 Filter: (a = prtx1_2.a)
2461 -> Bitmap Index Scan on prtx2_2_b_idx
2462 Index Cond: (b = (prtx1_2.b + 1))
2463 -> Bitmap Index Scan on prtx2_2_c_idx
2464 Index Cond: (c = 99)
2468 where not exists (select 1 from prtx2
2469 where prtx2.a=prtx1.a and (prtx2.b=prtx1.b+1 or prtx2.c=99))
2477 -- Test advanced partition-matching algorithm for partitioned join
2479 -- Tests for range-partitioned tables
2480 CREATE TABLE prt1_adv (a int, b int, c varchar) PARTITION BY RANGE (a);
2481 CREATE TABLE prt1_adv_p1 PARTITION OF prt1_adv FOR VALUES FROM (100) TO (200);
2482 CREATE TABLE prt1_adv_p2 PARTITION OF prt1_adv FOR VALUES FROM (200) TO (300);
2483 CREATE TABLE prt1_adv_p3 PARTITION OF prt1_adv FOR VALUES FROM (300) TO (400);
2484 CREATE INDEX prt1_adv_a_idx ON prt1_adv (a);
2485 INSERT INTO prt1_adv SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(100, 399) i;
2487 CREATE TABLE prt2_adv (a int, b int, c varchar) PARTITION BY RANGE (b);
2488 CREATE TABLE prt2_adv_p1 PARTITION OF prt2_adv FOR VALUES FROM (100) TO (150);
2489 CREATE TABLE prt2_adv_p2 PARTITION OF prt2_adv FOR VALUES FROM (200) TO (300);
2490 CREATE TABLE prt2_adv_p3 PARTITION OF prt2_adv FOR VALUES FROM (350) TO (500);
2491 CREATE INDEX prt2_adv_b_idx ON prt2_adv (b);
2492 INSERT INTO prt2_adv_p1 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(100, 149) i;
2493 INSERT INTO prt2_adv_p2 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(200, 299) i;
2494 INSERT INTO prt2_adv_p3 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(350, 499) i;
2498 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
2500 ------------------------------------------------------
2505 Hash Cond: (t2_1.b = t1_1.a)
2506 -> Seq Scan on prt2_adv_p1 t2_1
2508 -> Seq Scan on prt1_adv_p1 t1_1
2511 Hash Cond: (t2_2.b = t1_2.a)
2512 -> Seq Scan on prt2_adv_p2 t2_2
2514 -> Seq Scan on prt1_adv_p2 t1_2
2517 Hash Cond: (t2_3.b = t1_3.a)
2518 -> Seq Scan on prt2_adv_p3 t2_3
2520 -> Seq Scan on prt1_adv_p3 t1_3
2524 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
2526 -----+------+-----+------
2527 100 | 0100 | 100 | 0100
2528 125 | 0125 | 125 | 0125
2529 200 | 0200 | 200 | 0200
2530 225 | 0225 | 225 | 0225
2531 250 | 0250 | 250 | 0250
2532 275 | 0275 | 275 | 0275
2533 350 | 0350 | 350 | 0350
2534 375 | 0375 | 375 | 0375
2539 SELECT t1.* FROM prt1_adv t1 WHERE EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
2541 ------------------------------------------------------
2546 Hash Cond: (t1_1.a = t2_1.b)
2547 -> Seq Scan on prt1_adv_p1 t1_1
2550 -> Seq Scan on prt2_adv_p1 t2_1
2552 Hash Cond: (t1_2.a = t2_2.b)
2553 -> Seq Scan on prt1_adv_p2 t1_2
2556 -> Seq Scan on prt2_adv_p2 t2_2
2558 Hash Cond: (t1_3.a = t2_3.b)
2559 -> Seq Scan on prt1_adv_p3 t1_3
2562 -> Seq Scan on prt2_adv_p3 t2_3
2565 SELECT t1.* FROM prt1_adv t1 WHERE EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
2580 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
2582 ------------------------------------------------------
2584 Sort Key: t1.a, t2.b
2587 Hash Cond: (t2_1.b = t1_1.a)
2588 -> Seq Scan on prt2_adv_p1 t2_1
2590 -> Seq Scan on prt1_adv_p1 t1_1
2593 Hash Cond: (t2_2.b = t1_2.a)
2594 -> Seq Scan on prt2_adv_p2 t2_2
2596 -> Seq Scan on prt1_adv_p2 t1_2
2599 Hash Cond: (t2_3.b = t1_3.a)
2600 -> Seq Scan on prt2_adv_p3 t2_3
2602 -> Seq Scan on prt1_adv_p3 t1_3
2606 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
2608 -----+------+-----+------
2609 100 | 0100 | 100 | 0100
2610 125 | 0125 | 125 | 0125
2613 200 | 0200 | 200 | 0200
2614 225 | 0225 | 225 | 0225
2615 250 | 0250 | 250 | 0250
2616 275 | 0275 | 275 | 0275
2619 350 | 0350 | 350 | 0350
2620 375 | 0375 | 375 | 0375
2625 SELECT t1.* FROM prt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
2627 ------------------------------------------------------
2631 -> Hash Right Anti Join
2632 Hash Cond: (t2_1.b = t1_1.a)
2633 -> Seq Scan on prt2_adv_p1 t2_1
2635 -> Seq Scan on prt1_adv_p1 t1_1
2637 -> Hash Right Anti Join
2638 Hash Cond: (t2_2.b = t1_2.a)
2639 -> Seq Scan on prt2_adv_p2 t2_2
2641 -> Seq Scan on prt1_adv_p2 t1_2
2643 -> Hash Right Anti Join
2644 Hash Cond: (t2_3.b = t1_3.a)
2645 -> Seq Scan on prt2_adv_p3 t2_3
2647 -> Seq Scan on prt1_adv_p3 t1_3
2651 SELECT t1.* FROM prt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
2662 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT 425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b;
2664 --------------------------------------------------------------------------
2666 Sort Key: prt1_adv.a, prt2_adv.b
2669 Hash Cond: (prt1_adv_1.a = prt2_adv_1.b)
2670 Filter: (((175) = prt1_adv_1.a) OR ((425) = prt2_adv_1.b))
2671 -> Seq Scan on prt1_adv_p1 prt1_adv_1
2674 -> Seq Scan on prt2_adv_p1 prt2_adv_1
2677 Hash Cond: (prt1_adv_2.a = prt2_adv_2.b)
2678 Filter: (((175) = prt1_adv_2.a) OR ((425) = prt2_adv_2.b))
2679 -> Seq Scan on prt1_adv_p2 prt1_adv_2
2682 -> Seq Scan on prt2_adv_p2 prt2_adv_2
2685 Hash Cond: (prt2_adv_3.b = prt1_adv_3.a)
2686 Filter: (((175) = prt1_adv_3.a) OR ((425) = prt2_adv_3.b))
2687 -> Seq Scan on prt2_adv_p3 prt2_adv_3
2690 -> Seq Scan on prt1_adv_p3 prt1_adv_3
2694 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT 425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b;
2696 -----+------+-----+------
2701 -- Test cases where one side has an extra partition
2702 CREATE TABLE prt2_adv_extra PARTITION OF prt2_adv FOR VALUES FROM (500) TO (MAXVALUE);
2703 INSERT INTO prt2_adv SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(500, 599) i;
2707 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
2709 ------------------------------------------------------
2714 Hash Cond: (t2_1.b = t1_1.a)
2715 -> Seq Scan on prt2_adv_p1 t2_1
2717 -> Seq Scan on prt1_adv_p1 t1_1
2720 Hash Cond: (t2_2.b = t1_2.a)
2721 -> Seq Scan on prt2_adv_p2 t2_2
2723 -> Seq Scan on prt1_adv_p2 t1_2
2726 Hash Cond: (t2_3.b = t1_3.a)
2727 -> Seq Scan on prt2_adv_p3 t2_3
2729 -> Seq Scan on prt1_adv_p3 t1_3
2733 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
2735 -----+------+-----+------
2736 100 | 0100 | 100 | 0100
2737 125 | 0125 | 125 | 0125
2738 200 | 0200 | 200 | 0200
2739 225 | 0225 | 225 | 0225
2740 250 | 0250 | 250 | 0250
2741 275 | 0275 | 275 | 0275
2742 350 | 0350 | 350 | 0350
2743 375 | 0375 | 375 | 0375
2748 SELECT t1.* FROM prt1_adv t1 WHERE EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
2750 ------------------------------------------------------
2755 Hash Cond: (t1_1.a = t2_1.b)
2756 -> Seq Scan on prt1_adv_p1 t1_1
2759 -> Seq Scan on prt2_adv_p1 t2_1
2761 Hash Cond: (t1_2.a = t2_2.b)
2762 -> Seq Scan on prt1_adv_p2 t1_2
2765 -> Seq Scan on prt2_adv_p2 t2_2
2767 Hash Cond: (t1_3.a = t2_3.b)
2768 -> Seq Scan on prt1_adv_p3 t1_3
2771 -> Seq Scan on prt2_adv_p3 t2_3
2774 SELECT t1.* FROM prt1_adv t1 WHERE EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
2789 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
2791 ------------------------------------------------------
2793 Sort Key: t1.a, t2.b
2796 Hash Cond: (t2_1.b = t1_1.a)
2797 -> Seq Scan on prt2_adv_p1 t2_1
2799 -> Seq Scan on prt1_adv_p1 t1_1
2802 Hash Cond: (t2_2.b = t1_2.a)
2803 -> Seq Scan on prt2_adv_p2 t2_2
2805 -> Seq Scan on prt1_adv_p2 t1_2
2808 Hash Cond: (t2_3.b = t1_3.a)
2809 -> Seq Scan on prt2_adv_p3 t2_3
2811 -> Seq Scan on prt1_adv_p3 t1_3
2815 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
2817 -----+------+-----+------
2818 100 | 0100 | 100 | 0100
2819 125 | 0125 | 125 | 0125
2822 200 | 0200 | 200 | 0200
2823 225 | 0225 | 225 | 0225
2824 250 | 0250 | 250 | 0250
2825 275 | 0275 | 275 | 0275
2828 350 | 0350 | 350 | 0350
2829 375 | 0375 | 375 | 0375
2832 -- left join; currently we can't do partitioned join if there are no matched
2833 -- partitions on the nullable side
2835 SELECT t1.b, t1.c, t2.a, t2.c FROM prt2_adv t1 LEFT JOIN prt1_adv t2 ON (t1.b = t2.a) WHERE t1.a = 0 ORDER BY t1.b, t2.a;
2837 ---------------------------------------------------------
2839 Sort Key: t1.b, t2.a
2841 Hash Cond: (t2.a = t1.b)
2843 -> Seq Scan on prt1_adv_p1 t2_1
2844 -> Seq Scan on prt1_adv_p2 t2_2
2845 -> Seq Scan on prt1_adv_p3 t2_3
2848 -> Seq Scan on prt2_adv_p1 t1_1
2850 -> Seq Scan on prt2_adv_p2 t1_2
2852 -> Seq Scan on prt2_adv_p3 t1_3
2854 -> Seq Scan on prt2_adv_extra t1_4
2860 SELECT t1.* FROM prt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
2862 ------------------------------------------------------
2866 -> Hash Right Anti Join
2867 Hash Cond: (t2_1.b = t1_1.a)
2868 -> Seq Scan on prt2_adv_p1 t2_1
2870 -> Seq Scan on prt1_adv_p1 t1_1
2872 -> Hash Right Anti Join
2873 Hash Cond: (t2_2.b = t1_2.a)
2874 -> Seq Scan on prt2_adv_p2 t2_2
2876 -> Seq Scan on prt1_adv_p2 t1_2
2878 -> Hash Right Anti Join
2879 Hash Cond: (t2_3.b = t1_3.a)
2880 -> Seq Scan on prt2_adv_p3 t2_3
2882 -> Seq Scan on prt1_adv_p3 t1_3
2886 SELECT t1.* FROM prt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
2895 -- anti join; currently we can't do partitioned join if there are no matched
2896 -- partitions on the nullable side
2898 SELECT t1.* FROM prt2_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt1_adv t2 WHERE t1.b = t2.a) AND t1.a = 0 ORDER BY t1.b;
2900 ---------------------------------------------------------
2903 -> Hash Right Anti Join
2904 Hash Cond: (t2.a = t1.b)
2906 -> Seq Scan on prt1_adv_p1 t2_1
2907 -> Seq Scan on prt1_adv_p2 t2_2
2908 -> Seq Scan on prt1_adv_p3 t2_3
2911 -> Seq Scan on prt2_adv_p1 t1_1
2913 -> Seq Scan on prt2_adv_p2 t1_2
2915 -> Seq Scan on prt2_adv_p3 t1_3
2917 -> Seq Scan on prt2_adv_extra t1_4
2921 -- full join; currently we can't do partitioned join if there are no matched
2922 -- partitions on the nullable side
2924 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT 425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b;
2926 ----------------------------------------------------------------
2928 Sort Key: prt1_adv.a, prt2_adv.b
2930 Hash Cond: (prt2_adv.b = prt1_adv.a)
2931 Filter: (((175) = prt1_adv.a) OR ((425) = prt2_adv.b))
2933 -> Seq Scan on prt2_adv_p1 prt2_adv_1
2935 -> Seq Scan on prt2_adv_p2 prt2_adv_2
2937 -> Seq Scan on prt2_adv_p3 prt2_adv_3
2939 -> Seq Scan on prt2_adv_extra prt2_adv_4
2943 -> Seq Scan on prt1_adv_p1 prt1_adv_1
2945 -> Seq Scan on prt1_adv_p2 prt1_adv_2
2947 -> Seq Scan on prt1_adv_p3 prt1_adv_3
2951 -- 3-way join where not every pair of relations can do partitioned join
2953 SELECT t1.b, t1.c, t2.a, t2.c, t3.a, t3.c FROM prt2_adv t1 LEFT JOIN prt1_adv t2 ON (t1.b = t2.a) INNER JOIN prt1_adv t3 ON (t1.b = t3.a) WHERE t1.a = 0 ORDER BY t1.b, t2.a, t3.a;
2955 --------------------------------------------------------------------------------
2957 Sort Key: t1.b, t2.a
2959 -> Nested Loop Left Join
2961 -> Seq Scan on prt2_adv_p1 t1_1
2963 -> Index Scan using prt1_adv_p1_a_idx on prt1_adv_p1 t3_1
2964 Index Cond: (a = t1_1.b)
2965 -> Index Scan using prt1_adv_p1_a_idx on prt1_adv_p1 t2_1
2966 Index Cond: (a = t1_1.b)
2968 Hash Cond: (t2_2.a = t1_2.b)
2969 -> Seq Scan on prt1_adv_p2 t2_2
2972 Hash Cond: (t3_2.a = t1_2.b)
2973 -> Seq Scan on prt1_adv_p2 t3_2
2975 -> Seq Scan on prt2_adv_p2 t1_2
2978 Hash Cond: (t2_3.a = t1_3.b)
2979 -> Seq Scan on prt1_adv_p3 t2_3
2982 Hash Cond: (t3_3.a = t1_3.b)
2983 -> Seq Scan on prt1_adv_p3 t3_3
2985 -> Seq Scan on prt2_adv_p3 t1_3
2989 SELECT t1.b, t1.c, t2.a, t2.c, t3.a, t3.c FROM prt2_adv t1 LEFT JOIN prt1_adv t2 ON (t1.b = t2.a) INNER JOIN prt1_adv t3 ON (t1.b = t3.a) WHERE t1.a = 0 ORDER BY t1.b, t2.a, t3.a;
2990 b | c | a | c | a | c
2991 -----+------+-----+------+-----+------
2992 100 | 0100 | 100 | 0100 | 100 | 0100
2993 125 | 0125 | 125 | 0125 | 125 | 0125
2994 200 | 0200 | 200 | 0200 | 200 | 0200
2995 225 | 0225 | 225 | 0225 | 225 | 0225
2996 250 | 0250 | 250 | 0250 | 250 | 0250
2997 275 | 0275 | 275 | 0275 | 275 | 0275
2998 350 | 0350 | 350 | 0350 | 350 | 0350
2999 375 | 0375 | 375 | 0375 | 375 | 0375
3002 DROP TABLE prt2_adv_extra;
3003 -- Test cases where a partition on one side matches multiple partitions on
3004 -- the other side; we currently can't do partitioned join in such cases
3005 ALTER TABLE prt2_adv DETACH PARTITION prt2_adv_p3;
3006 -- Split prt2_adv_p3 into two partitions so that prt1_adv_p3 matches both
3007 CREATE TABLE prt2_adv_p3_1 PARTITION OF prt2_adv FOR VALUES FROM (350) TO (375);
3008 CREATE TABLE prt2_adv_p3_2 PARTITION OF prt2_adv FOR VALUES FROM (375) TO (500);
3009 INSERT INTO prt2_adv SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(350, 499) i;
3013 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
3015 ------------------------------------------------------
3019 Hash Cond: (t2.b = t1.a)
3021 -> Seq Scan on prt2_adv_p1 t2_1
3022 -> Seq Scan on prt2_adv_p2 t2_2
3023 -> Seq Scan on prt2_adv_p3_1 t2_3
3024 -> Seq Scan on prt2_adv_p3_2 t2_4
3027 -> Seq Scan on prt1_adv_p1 t1_1
3029 -> Seq Scan on prt1_adv_p2 t1_2
3031 -> Seq Scan on prt1_adv_p3 t1_3
3037 SELECT t1.* FROM prt1_adv t1 WHERE EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
3039 --------------------------------------------------------
3043 Hash Cond: (t1.a = t2.b)
3045 -> Seq Scan on prt1_adv_p1 t1_1
3047 -> Seq Scan on prt1_adv_p2 t1_2
3049 -> Seq Scan on prt1_adv_p3 t1_3
3053 -> Seq Scan on prt2_adv_p1 t2_1
3054 -> Seq Scan on prt2_adv_p2 t2_2
3055 -> Seq Scan on prt2_adv_p3_1 t2_3
3056 -> Seq Scan on prt2_adv_p3_2 t2_4
3061 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
3063 ------------------------------------------------------
3065 Sort Key: t1.a, t2.b
3067 Hash Cond: (t2.b = t1.a)
3069 -> Seq Scan on prt2_adv_p1 t2_1
3070 -> Seq Scan on prt2_adv_p2 t2_2
3071 -> Seq Scan on prt2_adv_p3_1 t2_3
3072 -> Seq Scan on prt2_adv_p3_2 t2_4
3075 -> Seq Scan on prt1_adv_p1 t1_1
3077 -> Seq Scan on prt1_adv_p2 t1_2
3079 -> Seq Scan on prt1_adv_p3 t1_3
3085 SELECT t1.* FROM prt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
3087 ------------------------------------------------------
3090 -> Hash Right Anti Join
3091 Hash Cond: (t2.b = t1.a)
3093 -> Seq Scan on prt2_adv_p1 t2_1
3094 -> Seq Scan on prt2_adv_p2 t2_2
3095 -> Seq Scan on prt2_adv_p3_1 t2_3
3096 -> Seq Scan on prt2_adv_p3_2 t2_4
3099 -> Seq Scan on prt1_adv_p1 t1_1
3101 -> Seq Scan on prt1_adv_p2 t1_2
3103 -> Seq Scan on prt1_adv_p3 t1_3
3109 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT 425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b;
3111 ----------------------------------------------------------------
3113 Sort Key: prt1_adv.a, prt2_adv.b
3115 Hash Cond: (prt2_adv.b = prt1_adv.a)
3116 Filter: (((175) = prt1_adv.a) OR ((425) = prt2_adv.b))
3118 -> Seq Scan on prt2_adv_p1 prt2_adv_1
3120 -> Seq Scan on prt2_adv_p2 prt2_adv_2
3122 -> Seq Scan on prt2_adv_p3_1 prt2_adv_3
3124 -> Seq Scan on prt2_adv_p3_2 prt2_adv_4
3128 -> Seq Scan on prt1_adv_p1 prt1_adv_1
3130 -> Seq Scan on prt1_adv_p2 prt1_adv_2
3132 -> Seq Scan on prt1_adv_p3 prt1_adv_3
3136 DROP TABLE prt2_adv_p3_1;
3137 DROP TABLE prt2_adv_p3_2;
3139 -- Test default partitions
3140 ALTER TABLE prt1_adv DETACH PARTITION prt1_adv_p1;
3141 -- Change prt1_adv_p1 to the default partition
3142 ALTER TABLE prt1_adv ATTACH PARTITION prt1_adv_p1 DEFAULT;
3143 ALTER TABLE prt1_adv DETACH PARTITION prt1_adv_p3;
3145 -- We can do partitioned join even if only one of relations has the default
3148 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
3150 ------------------------------------------------------
3155 Hash Cond: (t2_1.b = t1_2.a)
3156 -> Seq Scan on prt2_adv_p1 t2_1
3158 -> Seq Scan on prt1_adv_p1 t1_2
3161 Hash Cond: (t2_2.b = t1_1.a)
3162 -> Seq Scan on prt2_adv_p2 t2_2
3164 -> Seq Scan on prt1_adv_p2 t1_1
3168 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
3170 -----+------+-----+------
3171 100 | 0100 | 100 | 0100
3172 125 | 0125 | 125 | 0125
3173 200 | 0200 | 200 | 0200
3174 225 | 0225 | 225 | 0225
3175 250 | 0250 | 250 | 0250
3176 275 | 0275 | 275 | 0275
3179 -- Restore prt1_adv_p3
3180 ALTER TABLE prt1_adv ATTACH PARTITION prt1_adv_p3 FOR VALUES FROM (300) TO (400);
3182 -- Restore prt2_adv_p3
3183 ALTER TABLE prt2_adv ATTACH PARTITION prt2_adv_p3 FOR VALUES FROM (350) TO (500);
3185 -- Partitioned join can't be applied because the default partition of prt1_adv
3186 -- matches prt2_adv_p1 and prt2_adv_p3
3188 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
3190 ------------------------------------------------------
3194 Hash Cond: (t2.b = t1.a)
3196 -> Seq Scan on prt2_adv_p1 t2_1
3197 -> Seq Scan on prt2_adv_p2 t2_2
3198 -> Seq Scan on prt2_adv_p3 t2_3
3201 -> Seq Scan on prt1_adv_p2 t1_1
3203 -> Seq Scan on prt1_adv_p3 t1_2
3205 -> Seq Scan on prt1_adv_p1 t1_3
3209 ALTER TABLE prt2_adv DETACH PARTITION prt2_adv_p3;
3210 -- Change prt2_adv_p3 to the default partition
3211 ALTER TABLE prt2_adv ATTACH PARTITION prt2_adv_p3 DEFAULT;
3213 -- Partitioned join can't be applied because the default partition of prt1_adv
3214 -- matches prt2_adv_p1 and prt2_adv_p3
3216 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
3218 ------------------------------------------------------
3222 Hash Cond: (t2.b = t1.a)
3224 -> Seq Scan on prt2_adv_p1 t2_1
3225 -> Seq Scan on prt2_adv_p2 t2_2
3226 -> Seq Scan on prt2_adv_p3 t2_3
3229 -> Seq Scan on prt1_adv_p2 t1_1
3231 -> Seq Scan on prt1_adv_p3 t1_2
3233 -> Seq Scan on prt1_adv_p1 t1_3
3237 DROP TABLE prt1_adv_p3;
3239 DROP TABLE prt2_adv_p3;
3241 CREATE TABLE prt3_adv (a int, b int, c varchar) PARTITION BY RANGE (a);
3242 CREATE TABLE prt3_adv_p1 PARTITION OF prt3_adv FOR VALUES FROM (200) TO (300);
3243 CREATE TABLE prt3_adv_p2 PARTITION OF prt3_adv FOR VALUES FROM (300) TO (400);
3244 CREATE INDEX prt3_adv_a_idx ON prt3_adv (a);
3245 INSERT INTO prt3_adv SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(200, 399) i;
3247 -- 3-way join to test the default partition of a join relation
3249 SELECT t1.a, t1.c, t2.b, t2.c, t3.a, t3.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) LEFT JOIN prt3_adv t3 ON (t1.a = t3.a) WHERE t1.b = 0 ORDER BY t1.a, t2.b, t3.a;
3251 ------------------------------------------------------------------
3253 Sort Key: t1.a, t2.b, t3.a
3256 Hash Cond: (t3_1.a = t1_1.a)
3257 -> Seq Scan on prt3_adv_p1 t3_1
3260 Hash Cond: (t2_2.b = t1_1.a)
3261 -> Seq Scan on prt2_adv_p2 t2_2
3263 -> Seq Scan on prt1_adv_p2 t1_1
3266 Hash Cond: (t3_2.a = t1_2.a)
3267 -> Seq Scan on prt3_adv_p2 t3_2
3270 Hash Cond: (t2_1.b = t1_2.a)
3271 -> Seq Scan on prt2_adv_p1 t2_1
3273 -> Seq Scan on prt1_adv_p1 t1_2
3277 SELECT t1.a, t1.c, t2.b, t2.c, t3.a, t3.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) LEFT JOIN prt3_adv t3 ON (t1.a = t3.a) WHERE t1.b = 0 ORDER BY t1.a, t2.b, t3.a;
3278 a | c | b | c | a | c
3279 -----+------+-----+------+-----+------
3280 100 | 0100 | 100 | 0100 | |
3281 125 | 0125 | 125 | 0125 | |
3284 200 | 0200 | 200 | 0200 | 200 | 0200
3285 225 | 0225 | 225 | 0225 | 225 | 0225
3286 250 | 0250 | 250 | 0250 | 250 | 0250
3287 275 | 0275 | 275 | 0275 | 275 | 0275
3290 DROP TABLE prt1_adv;
3291 DROP TABLE prt2_adv;
3292 DROP TABLE prt3_adv;
3293 -- Test interaction of partitioned join with partition pruning
3294 CREATE TABLE prt1_adv (a int, b int, c varchar) PARTITION BY RANGE (a);
3295 CREATE TABLE prt1_adv_p1 PARTITION OF prt1_adv FOR VALUES FROM (100) TO (200);
3296 CREATE TABLE prt1_adv_p2 PARTITION OF prt1_adv FOR VALUES FROM (200) TO (300);
3297 CREATE TABLE prt1_adv_p3 PARTITION OF prt1_adv FOR VALUES FROM (300) TO (400);
3298 CREATE INDEX prt1_adv_a_idx ON prt1_adv (a);
3299 INSERT INTO prt1_adv SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(100, 399) i;
3301 CREATE TABLE prt2_adv (a int, b int, c varchar) PARTITION BY RANGE (b);
3302 CREATE TABLE prt2_adv_p1 PARTITION OF prt2_adv FOR VALUES FROM (100) TO (200);
3303 CREATE TABLE prt2_adv_p2 PARTITION OF prt2_adv FOR VALUES FROM (200) TO (400);
3304 CREATE INDEX prt2_adv_b_idx ON prt2_adv (b);
3305 INSERT INTO prt2_adv SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(100, 399) i;
3308 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a < 300 AND t1.b = 0 ORDER BY t1.a, t2.b;
3310 -----------------------------------------------------------
3315 Hash Cond: (t2_1.b = t1_1.a)
3316 -> Seq Scan on prt2_adv_p1 t2_1
3318 -> Seq Scan on prt1_adv_p1 t1_1
3319 Filter: ((a < 300) AND (b = 0))
3321 Hash Cond: (t2_2.b = t1_2.a)
3322 -> Seq Scan on prt2_adv_p2 t2_2
3324 -> Seq Scan on prt1_adv_p2 t1_2
3325 Filter: ((a < 300) AND (b = 0))
3328 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a < 300 AND t1.b = 0 ORDER BY t1.a, t2.b;
3330 -----+------+-----+------
3331 100 | 0100 | 100 | 0100
3332 125 | 0125 | 125 | 0125
3333 150 | 0150 | 150 | 0150
3334 175 | 0175 | 175 | 0175
3335 200 | 0200 | 200 | 0200
3336 225 | 0225 | 225 | 0225
3337 250 | 0250 | 250 | 0250
3338 275 | 0275 | 275 | 0275
3341 DROP TABLE prt1_adv_p3;
3342 CREATE TABLE prt1_adv_default PARTITION OF prt1_adv DEFAULT;
3344 CREATE TABLE prt2_adv_default PARTITION OF prt2_adv DEFAULT;
3347 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a >= 100 AND t1.a < 300 AND t1.b = 0 ORDER BY t1.a, t2.b;
3349 --------------------------------------------------------------------------
3354 Hash Cond: (t2_1.b = t1_1.a)
3355 -> Seq Scan on prt2_adv_p1 t2_1
3357 -> Seq Scan on prt1_adv_p1 t1_1
3358 Filter: ((a >= 100) AND (a < 300) AND (b = 0))
3360 Hash Cond: (t2_2.b = t1_2.a)
3361 -> Seq Scan on prt2_adv_p2 t2_2
3363 -> Seq Scan on prt1_adv_p2 t1_2
3364 Filter: ((a >= 100) AND (a < 300) AND (b = 0))
3367 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a >= 100 AND t1.a < 300 AND t1.b = 0 ORDER BY t1.a, t2.b;
3369 -----+------+-----+------
3370 100 | 0100 | 100 | 0100
3371 125 | 0125 | 125 | 0125
3372 150 | 0150 | 150 | 0150
3373 175 | 0175 | 175 | 0175
3374 200 | 0200 | 200 | 0200
3375 225 | 0225 | 225 | 0225
3376 250 | 0250 | 250 | 0250
3377 275 | 0275 | 275 | 0275
3380 DROP TABLE prt1_adv;
3381 DROP TABLE prt2_adv;
3382 -- Tests for list-partitioned tables
3383 CREATE TABLE plt1_adv (a int, b int, c text) PARTITION BY LIST (c);
3384 CREATE TABLE plt1_adv_p1 PARTITION OF plt1_adv FOR VALUES IN ('0001', '0003');
3385 CREATE TABLE plt1_adv_p2 PARTITION OF plt1_adv FOR VALUES IN ('0004', '0006');
3386 CREATE TABLE plt1_adv_p3 PARTITION OF plt1_adv FOR VALUES IN ('0008', '0009');
3387 INSERT INTO plt1_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (1, 3, 4, 6, 8, 9);
3389 CREATE TABLE plt2_adv (a int, b int, c text) PARTITION BY LIST (c);
3390 CREATE TABLE plt2_adv_p1 PARTITION OF plt2_adv FOR VALUES IN ('0002', '0003');
3391 CREATE TABLE plt2_adv_p2 PARTITION OF plt2_adv FOR VALUES IN ('0004', '0006');
3392 CREATE TABLE plt2_adv_p3 PARTITION OF plt2_adv FOR VALUES IN ('0007', '0009');
3393 INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
3397 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3399 --------------------------------------------------------------------
3404 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
3405 -> Seq Scan on plt2_adv_p1 t2_1
3407 -> Seq Scan on plt1_adv_p1 t1_1
3410 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
3411 -> Seq Scan on plt2_adv_p2 t2_2
3413 -> Seq Scan on plt1_adv_p2 t1_2
3416 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
3417 -> Seq Scan on plt2_adv_p3 t2_3
3419 -> Seq Scan on plt1_adv_p3 t1_3
3423 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3425 ---+------+---+------
3434 SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3436 ----------------------------------------------------------------------
3440 -> Nested Loop Semi Join
3441 Join Filter: ((t1_1.a = t2_1.a) AND (t1_1.c = t2_1.c))
3442 -> Seq Scan on plt1_adv_p1 t1_1
3444 -> Seq Scan on plt2_adv_p1 t2_1
3445 -> Nested Loop Semi Join
3446 Join Filter: ((t1_2.a = t2_2.a) AND (t1_2.c = t2_2.c))
3447 -> Seq Scan on plt1_adv_p2 t1_2
3449 -> Seq Scan on plt2_adv_p2 t2_2
3450 -> Nested Loop Semi Join
3451 Join Filter: ((t1_3.a = t2_3.a) AND (t1_3.c = t2_3.c))
3452 -> Seq Scan on plt1_adv_p3 t1_3
3454 -> Seq Scan on plt2_adv_p3 t2_3
3457 SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3468 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3470 --------------------------------------------------------------------
3475 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
3476 -> Seq Scan on plt2_adv_p1 t2_1
3478 -> Seq Scan on plt1_adv_p1 t1_1
3481 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
3482 -> Seq Scan on plt2_adv_p2 t2_2
3484 -> Seq Scan on plt1_adv_p2 t1_2
3487 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
3488 -> Seq Scan on plt2_adv_p3 t2_3
3490 -> Seq Scan on plt1_adv_p3 t1_3
3494 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3496 ---+------+---+------
3507 SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3509 --------------------------------------------------------------------
3513 -> Hash Right Anti Join
3514 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
3515 -> Seq Scan on plt2_adv_p1 t2_1
3517 -> Seq Scan on plt1_adv_p1 t1_1
3519 -> Hash Right Anti Join
3520 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
3521 -> Seq Scan on plt2_adv_p2 t2_2
3523 -> Seq Scan on plt1_adv_p2 t1_2
3525 -> Hash Right Anti Join
3526 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
3527 -> Seq Scan on plt2_adv_p3 t2_3
3529 -> Seq Scan on plt1_adv_p3 t1_3
3533 SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3542 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
3544 -----------------------------------------------------------------------------------
3546 Sort Key: t1.a, t2.a
3549 Hash Cond: ((t1_1.a = t2_1.a) AND (t1_1.c = t2_1.c))
3550 Filter: ((COALESCE(t1_1.b, 0) < 10) AND (COALESCE(t2_1.b, 0) < 10))
3551 -> Seq Scan on plt1_adv_p1 t1_1
3553 -> Seq Scan on plt2_adv_p1 t2_1
3555 Hash Cond: ((t1_2.a = t2_2.a) AND (t1_2.c = t2_2.c))
3556 Filter: ((COALESCE(t1_2.b, 0) < 10) AND (COALESCE(t2_2.b, 0) < 10))
3557 -> Seq Scan on plt1_adv_p2 t1_2
3559 -> Seq Scan on plt2_adv_p2 t2_2
3561 Hash Cond: ((t1_3.a = t2_3.a) AND (t1_3.c = t2_3.c))
3562 Filter: ((COALESCE(t1_3.b, 0) < 10) AND (COALESCE(t2_3.b, 0) < 10))
3563 -> Seq Scan on plt1_adv_p3 t1_3
3565 -> Seq Scan on plt2_adv_p3 t2_3
3568 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
3570 ---+------+---+------
3581 -- Test cases where one side has an extra partition
3582 CREATE TABLE plt2_adv_extra PARTITION OF plt2_adv FOR VALUES IN ('0000');
3583 INSERT INTO plt2_adv_extra VALUES (0, 0, '0000');
3587 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3589 --------------------------------------------------------------------
3594 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
3595 -> Seq Scan on plt2_adv_p1 t2_1
3597 -> Seq Scan on plt1_adv_p1 t1_1
3600 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
3601 -> Seq Scan on plt2_adv_p2 t2_2
3603 -> Seq Scan on plt1_adv_p2 t1_2
3606 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
3607 -> Seq Scan on plt2_adv_p3 t2_3
3609 -> Seq Scan on plt1_adv_p3 t1_3
3613 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3615 ---+------+---+------
3624 SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3626 ----------------------------------------------------------------------
3630 -> Nested Loop Semi Join
3631 Join Filter: ((t1_1.a = t2_1.a) AND (t1_1.c = t2_1.c))
3632 -> Seq Scan on plt1_adv_p1 t1_1
3634 -> Seq Scan on plt2_adv_p1 t2_1
3635 -> Nested Loop Semi Join
3636 Join Filter: ((t1_2.a = t2_2.a) AND (t1_2.c = t2_2.c))
3637 -> Seq Scan on plt1_adv_p2 t1_2
3639 -> Seq Scan on plt2_adv_p2 t2_2
3640 -> Nested Loop Semi Join
3641 Join Filter: ((t1_3.a = t2_3.a) AND (t1_3.c = t2_3.c))
3642 -> Seq Scan on plt1_adv_p3 t1_3
3644 -> Seq Scan on plt2_adv_p3 t2_3
3647 SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3658 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3660 --------------------------------------------------------------------
3665 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
3666 -> Seq Scan on plt2_adv_p1 t2_1
3668 -> Seq Scan on plt1_adv_p1 t1_1
3671 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
3672 -> Seq Scan on plt2_adv_p2 t2_2
3674 -> Seq Scan on plt1_adv_p2 t1_2
3677 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
3678 -> Seq Scan on plt2_adv_p3 t2_3
3680 -> Seq Scan on plt1_adv_p3 t1_3
3684 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3686 ---+------+---+------
3695 -- left join; currently we can't do partitioned join if there are no matched
3696 -- partitions on the nullable side
3698 SELECT t1.a, t1.c, t2.a, t2.c FROM plt2_adv t1 LEFT JOIN plt1_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3700 ---------------------------------------------------------
3704 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
3706 -> Seq Scan on plt1_adv_p1 t2_1
3707 -> Seq Scan on plt1_adv_p2 t2_2
3708 -> Seq Scan on plt1_adv_p3 t2_3
3711 -> Seq Scan on plt2_adv_extra t1_1
3713 -> Seq Scan on plt2_adv_p1 t1_2
3715 -> Seq Scan on plt2_adv_p2 t1_3
3717 -> Seq Scan on plt2_adv_p3 t1_4
3723 SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3725 --------------------------------------------------------------------
3729 -> Hash Right Anti Join
3730 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
3731 -> Seq Scan on plt2_adv_p1 t2_1
3733 -> Seq Scan on plt1_adv_p1 t1_1
3735 -> Hash Right Anti Join
3736 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
3737 -> Seq Scan on plt2_adv_p2 t2_2
3739 -> Seq Scan on plt1_adv_p2 t1_2
3741 -> Hash Right Anti Join
3742 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
3743 -> Seq Scan on plt2_adv_p3 t2_3
3745 -> Seq Scan on plt1_adv_p3 t1_3
3749 SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3756 -- anti join; currently we can't do partitioned join if there are no matched
3757 -- partitions on the nullable side
3759 SELECT t1.* FROM plt2_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt1_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3761 ---------------------------------------------------------
3764 -> Hash Right Anti Join
3765 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
3767 -> Seq Scan on plt1_adv_p1 t2_1
3768 -> Seq Scan on plt1_adv_p2 t2_2
3769 -> Seq Scan on plt1_adv_p3 t2_3
3772 -> Seq Scan on plt2_adv_extra t1_1
3774 -> Seq Scan on plt2_adv_p1 t1_2
3776 -> Seq Scan on plt2_adv_p2 t1_3
3778 -> Seq Scan on plt2_adv_p3 t1_4
3782 -- full join; currently we can't do partitioned join if there are no matched
3783 -- partitions on the nullable side
3785 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
3787 -------------------------------------------------------------------------
3789 Sort Key: t1.a, t2.a
3791 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
3792 Filter: ((COALESCE(t1.b, 0) < 10) AND (COALESCE(t2.b, 0) < 10))
3794 -> Seq Scan on plt2_adv_extra t2_1
3795 -> Seq Scan on plt2_adv_p1 t2_2
3796 -> Seq Scan on plt2_adv_p2 t2_3
3797 -> Seq Scan on plt2_adv_p3 t2_4
3800 -> Seq Scan on plt1_adv_p1 t1_1
3801 -> Seq Scan on plt1_adv_p2 t1_2
3802 -> Seq Scan on plt1_adv_p3 t1_3
3805 DROP TABLE plt2_adv_extra;
3806 -- Test cases where a partition on one side matches multiple partitions on
3807 -- the other side; we currently can't do partitioned join in such cases
3808 ALTER TABLE plt2_adv DETACH PARTITION plt2_adv_p2;
3809 -- Split plt2_adv_p2 into two partitions so that plt1_adv_p2 matches both
3810 CREATE TABLE plt2_adv_p2_1 PARTITION OF plt2_adv FOR VALUES IN ('0004');
3811 CREATE TABLE plt2_adv_p2_2 PARTITION OF plt2_adv FOR VALUES IN ('0006');
3812 INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (4, 6);
3816 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3818 ------------------------------------------------------
3822 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
3824 -> Seq Scan on plt2_adv_p1 t2_1
3825 -> Seq Scan on plt2_adv_p2_1 t2_2
3826 -> Seq Scan on plt2_adv_p2_2 t2_3
3827 -> Seq Scan on plt2_adv_p3 t2_4
3830 -> Seq Scan on plt1_adv_p1 t1_1
3832 -> Seq Scan on plt1_adv_p2 t1_2
3834 -> Seq Scan on plt1_adv_p3 t1_3
3840 SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3842 --------------------------------------------------------
3846 Hash Cond: ((t1.a = t2.a) AND (t1.c = t2.c))
3848 -> Seq Scan on plt1_adv_p1 t1_1
3850 -> Seq Scan on plt1_adv_p2 t1_2
3852 -> Seq Scan on plt1_adv_p3 t1_3
3856 -> Seq Scan on plt2_adv_p1 t2_1
3857 -> Seq Scan on plt2_adv_p2_1 t2_2
3858 -> Seq Scan on plt2_adv_p2_2 t2_3
3859 -> Seq Scan on plt2_adv_p3 t2_4
3864 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3866 ------------------------------------------------------
3870 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
3872 -> Seq Scan on plt2_adv_p1 t2_1
3873 -> Seq Scan on plt2_adv_p2_1 t2_2
3874 -> Seq Scan on plt2_adv_p2_2 t2_3
3875 -> Seq Scan on plt2_adv_p3 t2_4
3878 -> Seq Scan on plt1_adv_p1 t1_1
3880 -> Seq Scan on plt1_adv_p2 t1_2
3882 -> Seq Scan on plt1_adv_p3 t1_3
3888 SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3890 ------------------------------------------------------
3893 -> Hash Right Anti Join
3894 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
3896 -> Seq Scan on plt2_adv_p1 t2_1
3897 -> Seq Scan on plt2_adv_p2_1 t2_2
3898 -> Seq Scan on plt2_adv_p2_2 t2_3
3899 -> Seq Scan on plt2_adv_p3 t2_4
3902 -> Seq Scan on plt1_adv_p1 t1_1
3904 -> Seq Scan on plt1_adv_p2 t1_2
3906 -> Seq Scan on plt1_adv_p3 t1_3
3912 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
3914 -------------------------------------------------------------------------
3916 Sort Key: t1.a, t2.a
3918 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
3919 Filter: ((COALESCE(t1.b, 0) < 10) AND (COALESCE(t2.b, 0) < 10))
3921 -> Seq Scan on plt2_adv_p1 t2_1
3922 -> Seq Scan on plt2_adv_p2_1 t2_2
3923 -> Seq Scan on plt2_adv_p2_2 t2_3
3924 -> Seq Scan on plt2_adv_p3 t2_4
3927 -> Seq Scan on plt1_adv_p1 t1_1
3928 -> Seq Scan on plt1_adv_p2 t1_2
3929 -> Seq Scan on plt1_adv_p3 t1_3
3932 DROP TABLE plt2_adv_p2_1;
3933 DROP TABLE plt2_adv_p2_2;
3934 -- Restore plt2_adv_p2
3935 ALTER TABLE plt2_adv ATTACH PARTITION plt2_adv_p2 FOR VALUES IN ('0004', '0006');
3936 -- Test NULL partitions
3937 ALTER TABLE plt1_adv DETACH PARTITION plt1_adv_p1;
3938 -- Change plt1_adv_p1 to the NULL partition
3939 CREATE TABLE plt1_adv_p1_null PARTITION OF plt1_adv FOR VALUES IN (NULL, '0001', '0003');
3940 INSERT INTO plt1_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (1, 3);
3941 INSERT INTO plt1_adv VALUES (-1, -1, NULL);
3943 ALTER TABLE plt2_adv DETACH PARTITION plt2_adv_p3;
3944 -- Change plt2_adv_p3 to the NULL partition
3945 CREATE TABLE plt2_adv_p3_null PARTITION OF plt2_adv FOR VALUES IN (NULL, '0007', '0009');
3946 INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (7, 9);
3947 INSERT INTO plt2_adv VALUES (-1, -1, NULL);
3951 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3953 --------------------------------------------------------------------
3958 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
3959 -> Seq Scan on plt2_adv_p1 t2_1
3961 -> Seq Scan on plt1_adv_p1_null t1_1
3964 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
3965 -> Seq Scan on plt2_adv_p2 t2_2
3967 -> Seq Scan on plt1_adv_p2 t1_2
3970 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
3971 -> Seq Scan on plt2_adv_p3_null t2_3
3973 -> Seq Scan on plt1_adv_p3 t1_3
3977 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
3979 ---+------+---+------
3988 SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
3990 ----------------------------------------------------------------------
3995 Hash Cond: ((t1_1.a = t2_1.a) AND (t1_1.c = t2_1.c))
3996 -> Seq Scan on plt1_adv_p1_null t1_1
3999 -> Seq Scan on plt2_adv_p1 t2_1
4000 -> Nested Loop Semi Join
4001 Join Filter: ((t1_2.a = t2_2.a) AND (t1_2.c = t2_2.c))
4002 -> Seq Scan on plt1_adv_p2 t1_2
4004 -> Seq Scan on plt2_adv_p2 t2_2
4005 -> Nested Loop Semi Join
4006 Join Filter: ((t1_3.a = t2_3.a) AND (t1_3.c = t2_3.c))
4007 -> Seq Scan on plt1_adv_p3 t1_3
4009 -> Seq Scan on plt2_adv_p3_null t2_3
4012 SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
4023 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4025 --------------------------------------------------------------------
4030 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
4031 -> Seq Scan on plt2_adv_p1 t2_1
4033 -> Seq Scan on plt1_adv_p1_null t1_1
4036 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
4037 -> Seq Scan on plt2_adv_p2 t2_2
4039 -> Seq Scan on plt1_adv_p2 t1_2
4042 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
4043 -> Seq Scan on plt2_adv_p3_null t2_3
4045 -> Seq Scan on plt1_adv_p3 t1_3
4049 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4051 ----+------+---+------
4063 SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
4065 --------------------------------------------------------------------
4069 -> Hash Right Anti Join
4070 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
4071 -> Seq Scan on plt2_adv_p1 t2_1
4073 -> Seq Scan on plt1_adv_p1_null t1_1
4075 -> Hash Right Anti Join
4076 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
4077 -> Seq Scan on plt2_adv_p2 t2_2
4079 -> Seq Scan on plt1_adv_p2 t1_2
4081 -> Hash Right Anti Join
4082 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
4083 -> Seq Scan on plt2_adv_p3_null t2_3
4085 -> Seq Scan on plt1_adv_p3 t1_3
4089 SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
4099 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
4101 -----------------------------------------------------------------------------------
4103 Sort Key: t1.a, t2.a
4106 Hash Cond: ((t1_1.a = t2_1.a) AND (t1_1.c = t2_1.c))
4107 Filter: ((COALESCE(t1_1.b, 0) < 10) AND (COALESCE(t2_1.b, 0) < 10))
4108 -> Seq Scan on plt1_adv_p1_null t1_1
4110 -> Seq Scan on plt2_adv_p1 t2_1
4112 Hash Cond: ((t1_2.a = t2_2.a) AND (t1_2.c = t2_2.c))
4113 Filter: ((COALESCE(t1_2.b, 0) < 10) AND (COALESCE(t2_2.b, 0) < 10))
4114 -> Seq Scan on plt1_adv_p2 t1_2
4116 -> Seq Scan on plt2_adv_p2 t2_2
4118 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
4119 Filter: ((COALESCE(t1_3.b, 0) < 10) AND (COALESCE(t2_3.b, 0) < 10))
4120 -> Seq Scan on plt2_adv_p3_null t2_3
4122 -> Seq Scan on plt1_adv_p3 t1_3
4125 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
4127 ----+------+----+------
4140 DROP TABLE plt1_adv_p1_null;
4141 -- Restore plt1_adv_p1
4142 ALTER TABLE plt1_adv ATTACH PARTITION plt1_adv_p1 FOR VALUES IN ('0001', '0003');
4143 -- Add to plt1_adv the extra NULL partition containing only NULL values as the
4145 CREATE TABLE plt1_adv_extra PARTITION OF plt1_adv FOR VALUES IN (NULL);
4146 INSERT INTO plt1_adv VALUES (-1, -1, NULL);
4148 DROP TABLE plt2_adv_p3_null;
4149 -- Restore plt2_adv_p3
4150 ALTER TABLE plt2_adv ATTACH PARTITION plt2_adv_p3 FOR VALUES IN ('0007', '0009');
4154 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4156 --------------------------------------------------------------------
4161 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
4162 -> Seq Scan on plt2_adv_p1 t2_1
4164 -> Seq Scan on plt1_adv_p1 t1_1
4167 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
4168 -> Seq Scan on plt2_adv_p2 t2_2
4170 -> Seq Scan on plt1_adv_p2 t1_2
4173 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
4174 -> Seq Scan on plt2_adv_p3 t2_3
4176 -> Seq Scan on plt1_adv_p3 t1_3
4180 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4182 ---+------+---+------
4189 -- left join; currently we can't do partitioned join if there are no matched
4190 -- partitions on the nullable side
4192 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4194 ---------------------------------------------------------
4198 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
4200 -> Seq Scan on plt2_adv_p1 t2_1
4201 -> Seq Scan on plt2_adv_p2 t2_2
4202 -> Seq Scan on plt2_adv_p3 t2_3
4205 -> Seq Scan on plt1_adv_p1 t1_1
4207 -> Seq Scan on plt1_adv_p2 t1_2
4209 -> Seq Scan on plt1_adv_p3 t1_3
4211 -> Seq Scan on plt1_adv_extra t1_4
4215 -- full join; currently we can't do partitioned join if there are no matched
4216 -- partitions on the nullable side
4218 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
4220 -------------------------------------------------------------------------
4222 Sort Key: t1.a, t2.a
4224 Hash Cond: ((t1.a = t2.a) AND (t1.c = t2.c))
4225 Filter: ((COALESCE(t1.b, 0) < 10) AND (COALESCE(t2.b, 0) < 10))
4227 -> Seq Scan on plt1_adv_p1 t1_1
4228 -> Seq Scan on plt1_adv_p2 t1_2
4229 -> Seq Scan on plt1_adv_p3 t1_3
4230 -> Seq Scan on plt1_adv_extra t1_4
4233 -> Seq Scan on plt2_adv_p1 t2_1
4234 -> Seq Scan on plt2_adv_p2 t2_2
4235 -> Seq Scan on plt2_adv_p3 t2_3
4238 -- Add to plt2_adv the extra NULL partition containing only NULL values as the
4240 CREATE TABLE plt2_adv_extra PARTITION OF plt2_adv FOR VALUES IN (NULL);
4241 INSERT INTO plt2_adv VALUES (-1, -1, NULL);
4245 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4247 --------------------------------------------------------------------
4252 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
4253 -> Seq Scan on plt2_adv_p1 t2_1
4255 -> Seq Scan on plt1_adv_p1 t1_1
4258 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
4259 -> Seq Scan on plt2_adv_p2 t2_2
4261 -> Seq Scan on plt1_adv_p2 t1_2
4264 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
4265 -> Seq Scan on plt2_adv_p3 t2_3
4267 -> Seq Scan on plt1_adv_p3 t1_3
4271 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4273 ---+------+---+------
4282 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4284 ----------------------------------------------------------------------
4289 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
4290 -> Seq Scan on plt2_adv_p1 t2_1
4292 -> Seq Scan on plt1_adv_p1 t1_1
4295 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
4296 -> Seq Scan on plt2_adv_p2 t2_2
4298 -> Seq Scan on plt1_adv_p2 t1_2
4301 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
4302 -> Seq Scan on plt2_adv_p3 t2_3
4304 -> Seq Scan on plt1_adv_p3 t1_3
4306 -> Nested Loop Left Join
4307 Join Filter: ((t1_4.a = t2_4.a) AND (t1_4.c = t2_4.c))
4308 -> Seq Scan on plt1_adv_extra t1_4
4310 -> Seq Scan on plt2_adv_extra t2_4
4313 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4315 ----+------+---+------
4327 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
4329 -----------------------------------------------------------------------------------
4331 Sort Key: t1.a, t2.a
4334 Hash Cond: ((t1_1.a = t2_1.a) AND (t1_1.c = t2_1.c))
4335 Filter: ((COALESCE(t1_1.b, 0) < 10) AND (COALESCE(t2_1.b, 0) < 10))
4336 -> Seq Scan on plt1_adv_p1 t1_1
4338 -> Seq Scan on plt2_adv_p1 t2_1
4340 Hash Cond: ((t1_2.a = t2_2.a) AND (t1_2.c = t2_2.c))
4341 Filter: ((COALESCE(t1_2.b, 0) < 10) AND (COALESCE(t2_2.b, 0) < 10))
4342 -> Seq Scan on plt1_adv_p2 t1_2
4344 -> Seq Scan on plt2_adv_p2 t2_2
4346 Hash Cond: ((t1_3.a = t2_3.a) AND (t1_3.c = t2_3.c))
4347 Filter: ((COALESCE(t1_3.b, 0) < 10) AND (COALESCE(t2_3.b, 0) < 10))
4348 -> Seq Scan on plt1_adv_p3 t1_3
4350 -> Seq Scan on plt2_adv_p3 t2_3
4352 Hash Cond: ((t1_4.a = t2_4.a) AND (t1_4.c = t2_4.c))
4353 Filter: ((COALESCE(t1_4.b, 0) < 10) AND (COALESCE(t2_4.b, 0) < 10))
4354 -> Seq Scan on plt1_adv_extra t1_4
4356 -> Seq Scan on plt2_adv_extra t2_4
4359 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
4361 ----+------+----+------
4374 -- 3-way join to test the NULL partition of a join relation
4376 SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFT JOIN plt1_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10 ORDER BY t1.a;
4378 --------------------------------------------------------------------------------
4383 Hash Cond: ((t3_1.a = t1_1.a) AND (t3_1.c = t1_1.c))
4384 -> Seq Scan on plt1_adv_p1 t3_1
4387 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
4388 -> Seq Scan on plt2_adv_p1 t2_1
4390 -> Seq Scan on plt1_adv_p1 t1_1
4393 Hash Cond: ((t3_2.a = t1_2.a) AND (t3_2.c = t1_2.c))
4394 -> Seq Scan on plt1_adv_p2 t3_2
4397 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
4398 -> Seq Scan on plt2_adv_p2 t2_2
4400 -> Seq Scan on plt1_adv_p2 t1_2
4403 Hash Cond: ((t3_3.a = t1_3.a) AND (t3_3.c = t1_3.c))
4404 -> Seq Scan on plt1_adv_p3 t3_3
4407 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
4408 -> Seq Scan on plt2_adv_p3 t2_3
4410 -> Seq Scan on plt1_adv_p3 t1_3
4412 -> Nested Loop Left Join
4413 Join Filter: ((t1_4.a = t3_4.a) AND (t1_4.c = t3_4.c))
4414 -> Nested Loop Left Join
4415 Join Filter: ((t1_4.a = t2_4.a) AND (t1_4.c = t2_4.c))
4416 -> Seq Scan on plt1_adv_extra t1_4
4418 -> Seq Scan on plt2_adv_extra t2_4
4419 -> Seq Scan on plt1_adv_extra t3_4
4422 SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFT JOIN plt1_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10 ORDER BY t1.a;
4423 a | c | a | c | a | c
4424 ----+------+---+------+---+------
4426 1 | 0001 | | | 1 | 0001
4427 3 | 0003 | 3 | 0003 | 3 | 0003
4428 4 | 0004 | 4 | 0004 | 4 | 0004
4429 6 | 0006 | 6 | 0006 | 6 | 0006
4430 8 | 0008 | | | 8 | 0008
4431 9 | 0009 | 9 | 0009 | 9 | 0009
4434 DROP TABLE plt1_adv_extra;
4435 DROP TABLE plt2_adv_extra;
4436 -- Test default partitions
4437 ALTER TABLE plt1_adv DETACH PARTITION plt1_adv_p1;
4438 -- Change plt1_adv_p1 to the default partition
4439 ALTER TABLE plt1_adv ATTACH PARTITION plt1_adv_p1 DEFAULT;
4440 DROP TABLE plt1_adv_p3;
4442 DROP TABLE plt2_adv_p3;
4444 -- We can do partitioned join even if only one of relations has the default
4447 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4449 --------------------------------------------------------------------
4454 Hash Cond: ((t2_1.a = t1_2.a) AND (t2_1.c = t1_2.c))
4455 -> Seq Scan on plt2_adv_p1 t2_1
4457 -> Seq Scan on plt1_adv_p1 t1_2
4460 Hash Cond: ((t2_2.a = t1_1.a) AND (t2_2.c = t1_1.c))
4461 -> Seq Scan on plt2_adv_p2 t2_2
4463 -> Seq Scan on plt1_adv_p2 t1_1
4467 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4469 ---+------+---+------
4475 ALTER TABLE plt2_adv DETACH PARTITION plt2_adv_p2;
4476 -- Change plt2_adv_p2 to contain '0005' in addition to '0004' and '0006' as
4478 CREATE TABLE plt2_adv_p2_ext PARTITION OF plt2_adv FOR VALUES IN ('0004', '0005', '0006');
4479 INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (4, 5, 6);
4481 -- Partitioned join can't be applied because the default partition of plt1_adv
4482 -- matches plt2_adv_p1 and plt2_adv_p2_ext
4484 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4486 ------------------------------------------------------
4490 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
4492 -> Seq Scan on plt2_adv_p1 t2_1
4493 -> Seq Scan on plt2_adv_p2_ext t2_2
4496 -> Seq Scan on plt1_adv_p2 t1_1
4498 -> Seq Scan on plt1_adv_p1 t1_2
4502 ALTER TABLE plt2_adv DETACH PARTITION plt2_adv_p2_ext;
4503 -- Change plt2_adv_p2_ext to the default partition
4504 ALTER TABLE plt2_adv ATTACH PARTITION plt2_adv_p2_ext DEFAULT;
4506 -- Partitioned join can't be applied because the default partition of plt1_adv
4507 -- matches plt2_adv_p1 and plt2_adv_p2_ext
4509 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4511 ------------------------------------------------------
4515 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
4517 -> Seq Scan on plt2_adv_p1 t2_1
4518 -> Seq Scan on plt2_adv_p2_ext t2_2
4521 -> Seq Scan on plt1_adv_p2 t1_1
4523 -> Seq Scan on plt1_adv_p1 t1_2
4527 DROP TABLE plt2_adv_p2_ext;
4528 -- Restore plt2_adv_p2
4529 ALTER TABLE plt2_adv ATTACH PARTITION plt2_adv_p2 FOR VALUES IN ('0004', '0006');
4531 CREATE TABLE plt3_adv (a int, b int, c text) PARTITION BY LIST (c);
4532 CREATE TABLE plt3_adv_p1 PARTITION OF plt3_adv FOR VALUES IN ('0004', '0006');
4533 CREATE TABLE plt3_adv_p2 PARTITION OF plt3_adv FOR VALUES IN ('0007', '0009');
4534 INSERT INTO plt3_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (4, 6, 7, 9);
4536 -- 3-way join to test the default partition of a join relation
4538 SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFT JOIN plt3_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10 ORDER BY t1.a;
4540 --------------------------------------------------------------------------------
4545 Hash Cond: ((t3_1.a = t1_1.a) AND (t3_1.c = t1_1.c))
4546 -> Seq Scan on plt3_adv_p1 t3_1
4549 Hash Cond: ((t2_2.a = t1_1.a) AND (t2_2.c = t1_1.c))
4550 -> Seq Scan on plt2_adv_p2 t2_2
4552 -> Seq Scan on plt1_adv_p2 t1_1
4555 Hash Cond: ((t3_2.a = t1_2.a) AND (t3_2.c = t1_2.c))
4556 -> Seq Scan on plt3_adv_p2 t3_2
4559 Hash Cond: ((t2_1.a = t1_2.a) AND (t2_1.c = t1_2.c))
4560 -> Seq Scan on plt2_adv_p1 t2_1
4562 -> Seq Scan on plt1_adv_p1 t1_2
4566 SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFT JOIN plt3_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10 ORDER BY t1.a;
4567 a | c | a | c | a | c
4568 ---+------+---+------+---+------
4570 3 | 0003 | 3 | 0003 | |
4571 4 | 0004 | 4 | 0004 | 4 | 0004
4572 6 | 0006 | 6 | 0006 | 6 | 0006
4575 -- Test cases where one side has the default partition while the other side
4576 -- has the NULL partition
4577 DROP TABLE plt2_adv_p1;
4578 -- Add the NULL partition to plt2_adv
4579 CREATE TABLE plt2_adv_p1_null PARTITION OF plt2_adv FOR VALUES IN (NULL, '0001', '0003');
4580 INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (1, 3);
4581 INSERT INTO plt2_adv VALUES (-1, -1, NULL);
4584 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4586 --------------------------------------------------------------------
4591 Hash Cond: ((t2_1.a = t1_2.a) AND (t2_1.c = t1_2.c))
4592 -> Seq Scan on plt2_adv_p1_null t2_1
4594 -> Seq Scan on plt1_adv_p1 t1_2
4597 Hash Cond: ((t2_2.a = t1_1.a) AND (t2_2.c = t1_1.c))
4598 -> Seq Scan on plt2_adv_p2 t2_2
4600 -> Seq Scan on plt1_adv_p2 t1_1
4604 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4606 ---+------+---+------
4613 DROP TABLE plt2_adv_p1_null;
4614 -- Add the NULL partition that contains only NULL values as the key values
4615 CREATE TABLE plt2_adv_p1_null PARTITION OF plt2_adv FOR VALUES IN (NULL);
4616 INSERT INTO plt2_adv VALUES (-1, -1, NULL);
4619 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4621 ------------------------------------------------------
4625 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
4626 -> Seq Scan on plt2_adv_p2 t2
4628 -> Seq Scan on plt1_adv_p2 t1
4632 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
4634 ---+------+---+------
4639 DROP TABLE plt1_adv;
4640 DROP TABLE plt2_adv;
4641 DROP TABLE plt3_adv;
4642 -- Test interaction of partitioned join with partition pruning
4643 CREATE TABLE plt1_adv (a int, b int, c text) PARTITION BY LIST (c);
4644 CREATE TABLE plt1_adv_p1 PARTITION OF plt1_adv FOR VALUES IN ('0001');
4645 CREATE TABLE plt1_adv_p2 PARTITION OF plt1_adv FOR VALUES IN ('0002');
4646 CREATE TABLE plt1_adv_p3 PARTITION OF plt1_adv FOR VALUES IN ('0003');
4647 CREATE TABLE plt1_adv_p4 PARTITION OF plt1_adv FOR VALUES IN (NULL, '0004', '0005');
4648 INSERT INTO plt1_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (1, 2, 3, 4, 5);
4649 INSERT INTO plt1_adv VALUES (-1, -1, NULL);
4651 CREATE TABLE plt2_adv (a int, b int, c text) PARTITION BY LIST (c);
4652 CREATE TABLE plt2_adv_p1 PARTITION OF plt2_adv FOR VALUES IN ('0001', '0002');
4653 CREATE TABLE plt2_adv_p2 PARTITION OF plt2_adv FOR VALUES IN (NULL);
4654 CREATE TABLE plt2_adv_p3 PARTITION OF plt2_adv FOR VALUES IN ('0003');
4655 CREATE TABLE plt2_adv_p4 PARTITION OF plt2_adv FOR VALUES IN ('0004', '0005');
4656 INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (1, 2, 3, 4, 5);
4657 INSERT INTO plt2_adv VALUES (-1, -1, NULL);
4660 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10 ORDER BY t1.a;
4662 -----------------------------------------------------------------------------------------
4667 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
4668 -> Seq Scan on plt2_adv_p3 t2_1
4670 -> Seq Scan on plt1_adv_p3 t1_1
4671 Filter: ((b < 10) AND (c = ANY ('{0003,0004,0005}'::text[])))
4673 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
4674 -> Seq Scan on plt2_adv_p4 t2_2
4676 -> Seq Scan on plt1_adv_p4 t1_2
4677 Filter: ((b < 10) AND (c = ANY ('{0003,0004,0005}'::text[])))
4680 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10 ORDER BY t1.a;
4682 ---+------+---+------
4689 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IS NULL AND t1.b < 10 ORDER BY t1.a;
4691 --------------------------------------------------------
4695 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
4696 -> Seq Scan on plt2_adv_p4 t2
4698 -> Seq Scan on plt1_adv_p4 t1
4699 Filter: ((c IS NULL) AND (b < 10))
4702 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IS NULL AND t1.b < 10 ORDER BY t1.a;
4708 CREATE TABLE plt1_adv_default PARTITION OF plt1_adv DEFAULT;
4710 CREATE TABLE plt2_adv_default PARTITION OF plt2_adv DEFAULT;
4713 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10 ORDER BY t1.a;
4715 -----------------------------------------------------------------------------------------
4720 Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
4721 -> Seq Scan on plt2_adv_p3 t2_1
4723 -> Seq Scan on plt1_adv_p3 t1_1
4724 Filter: ((b < 10) AND (c = ANY ('{0003,0004,0005}'::text[])))
4726 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
4727 -> Seq Scan on plt2_adv_p4 t2_2
4729 -> Seq Scan on plt1_adv_p4 t1_2
4730 Filter: ((b < 10) AND (c = ANY ('{0003,0004,0005}'::text[])))
4733 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10 ORDER BY t1.a;
4735 ---+------+---+------
4742 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IS NULL AND t1.b < 10 ORDER BY t1.a;
4744 --------------------------------------------------------
4748 Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
4749 -> Seq Scan on plt2_adv_p4 t2
4751 -> Seq Scan on plt1_adv_p4 t1
4752 Filter: ((c IS NULL) AND (b < 10))
4755 SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IS NULL AND t1.b < 10 ORDER BY t1.a;
4761 DROP TABLE plt1_adv;
4762 DROP TABLE plt2_adv;
4763 -- Test the process_outer_partition() code path
4764 CREATE TABLE plt1_adv (a int, b int, c text) PARTITION BY LIST (c);
4765 CREATE TABLE plt1_adv_p1 PARTITION OF plt1_adv FOR VALUES IN ('0000', '0001', '0002');
4766 CREATE TABLE plt1_adv_p2 PARTITION OF plt1_adv FOR VALUES IN ('0003', '0004');
4767 INSERT INTO plt1_adv SELECT i, i, to_char(i % 5, 'FM0000') FROM generate_series(0, 24) i;
4769 CREATE TABLE plt2_adv (a int, b int, c text) PARTITION BY LIST (c);
4770 CREATE TABLE plt2_adv_p1 PARTITION OF plt2_adv FOR VALUES IN ('0002');
4771 CREATE TABLE plt2_adv_p2 PARTITION OF plt2_adv FOR VALUES IN ('0003', '0004');
4772 INSERT INTO plt2_adv SELECT i, i, to_char(i % 5, 'FM0000') FROM generate_series(0, 24) i WHERE i % 5 IN (2, 3, 4);
4774 CREATE TABLE plt3_adv (a int, b int, c text) PARTITION BY LIST (c);
4775 CREATE TABLE plt3_adv_p1 PARTITION OF plt3_adv FOR VALUES IN ('0001');
4776 CREATE TABLE plt3_adv_p2 PARTITION OF plt3_adv FOR VALUES IN ('0003', '0004');
4777 INSERT INTO plt3_adv SELECT i, i, to_char(i % 5, 'FM0000') FROM generate_series(0, 24) i WHERE i % 5 IN (1, 3, 4);
4779 -- This tests that when merging partitions from plt1_adv and plt2_adv in
4780 -- merge_list_bounds(), process_outer_partition() returns an already-assigned
4781 -- merged partition when re-called with plt1_adv_p1 for the second list value
4782 -- '0001' of that partition
4784 SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM (plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.c = t2.c)) FULL JOIN plt3_adv t3 ON (t1.c = t3.c) WHERE coalesce(t1.a, 0) % 5 != 3 AND coalesce(t1.a, 0) % 5 != 4 ORDER BY t1.c, t1.a, t2.a, t3.a;
4786 -----------------------------------------------------------------------------------------------
4788 Sort Key: t1.c, t1.a, t2.a, t3.a
4791 Hash Cond: (t1_1.c = t3_1.c)
4792 Filter: (((COALESCE(t1_1.a, 0) % 5) <> 3) AND ((COALESCE(t1_1.a, 0) % 5) <> 4))
4794 Hash Cond: (t1_1.c = t2_1.c)
4795 -> Seq Scan on plt1_adv_p1 t1_1
4797 -> Seq Scan on plt2_adv_p1 t2_1
4799 -> Seq Scan on plt3_adv_p1 t3_1
4801 Hash Cond: (t1_2.c = t3_2.c)
4802 Filter: (((COALESCE(t1_2.a, 0) % 5) <> 3) AND ((COALESCE(t1_2.a, 0) % 5) <> 4))
4804 Hash Cond: (t1_2.c = t2_2.c)
4805 -> Seq Scan on plt1_adv_p2 t1_2
4807 -> Seq Scan on plt2_adv_p2 t2_2
4809 -> Seq Scan on plt3_adv_p2 t3_2
4812 SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM (plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.c = t2.c)) FULL JOIN plt3_adv t3 ON (t1.c = t3.c) WHERE coalesce(t1.a, 0) % 5 != 3 AND coalesce(t1.a, 0) % 5 != 4 ORDER BY t1.c, t1.a, t2.a, t3.a;
4813 a | c | a | c | a | c
4814 ----+------+----+------+----+------
4820 1 | 0001 | | | 1 | 0001
4821 1 | 0001 | | | 6 | 0001
4822 1 | 0001 | | | 11 | 0001
4823 1 | 0001 | | | 16 | 0001
4824 1 | 0001 | | | 21 | 0001
4825 6 | 0001 | | | 1 | 0001
4826 6 | 0001 | | | 6 | 0001
4827 6 | 0001 | | | 11 | 0001
4828 6 | 0001 | | | 16 | 0001
4829 6 | 0001 | | | 21 | 0001
4830 11 | 0001 | | | 1 | 0001
4831 11 | 0001 | | | 6 | 0001
4832 11 | 0001 | | | 11 | 0001
4833 11 | 0001 | | | 16 | 0001
4834 11 | 0001 | | | 21 | 0001
4835 16 | 0001 | | | 1 | 0001
4836 16 | 0001 | | | 6 | 0001
4837 16 | 0001 | | | 11 | 0001
4838 16 | 0001 | | | 16 | 0001
4839 16 | 0001 | | | 21 | 0001
4840 21 | 0001 | | | 1 | 0001
4841 21 | 0001 | | | 6 | 0001
4842 21 | 0001 | | | 11 | 0001
4843 21 | 0001 | | | 16 | 0001
4844 21 | 0001 | | | 21 | 0001
4845 2 | 0002 | 2 | 0002 | |
4846 2 | 0002 | 7 | 0002 | |
4847 2 | 0002 | 12 | 0002 | |
4848 2 | 0002 | 17 | 0002 | |
4849 2 | 0002 | 22 | 0002 | |
4850 7 | 0002 | 2 | 0002 | |
4851 7 | 0002 | 7 | 0002 | |
4852 7 | 0002 | 12 | 0002 | |
4853 7 | 0002 | 17 | 0002 | |
4854 7 | 0002 | 22 | 0002 | |
4855 12 | 0002 | 2 | 0002 | |
4856 12 | 0002 | 7 | 0002 | |
4857 12 | 0002 | 12 | 0002 | |
4858 12 | 0002 | 17 | 0002 | |
4859 12 | 0002 | 22 | 0002 | |
4860 17 | 0002 | 2 | 0002 | |
4861 17 | 0002 | 7 | 0002 | |
4862 17 | 0002 | 12 | 0002 | |
4863 17 | 0002 | 17 | 0002 | |
4864 17 | 0002 | 22 | 0002 | |
4865 22 | 0002 | 2 | 0002 | |
4866 22 | 0002 | 7 | 0002 | |
4867 22 | 0002 | 12 | 0002 | |
4868 22 | 0002 | 17 | 0002 | |
4869 22 | 0002 | 22 | 0002 | |
4872 DROP TABLE plt1_adv;
4873 DROP TABLE plt2_adv;
4874 DROP TABLE plt3_adv;
4875 -- Tests for multi-level partitioned tables
4876 CREATE TABLE alpha (a double precision, b int, c text) PARTITION BY RANGE (a);
4877 CREATE TABLE alpha_neg PARTITION OF alpha FOR VALUES FROM ('-Infinity') TO (0) PARTITION BY RANGE (b);
4878 CREATE TABLE alpha_pos PARTITION OF alpha FOR VALUES FROM (0) TO (10.0) PARTITION BY LIST (c);
4879 CREATE TABLE alpha_neg_p1 PARTITION OF alpha_neg FOR VALUES FROM (100) TO (200);
4880 CREATE TABLE alpha_neg_p2 PARTITION OF alpha_neg FOR VALUES FROM (200) TO (300);
4881 CREATE TABLE alpha_neg_p3 PARTITION OF alpha_neg FOR VALUES FROM (300) TO (400);
4882 CREATE TABLE alpha_pos_p1 PARTITION OF alpha_pos FOR VALUES IN ('0001', '0003');
4883 CREATE TABLE alpha_pos_p2 PARTITION OF alpha_pos FOR VALUES IN ('0004', '0006');
4884 CREATE TABLE alpha_pos_p3 PARTITION OF alpha_pos FOR VALUES IN ('0008', '0009');
4885 INSERT INTO alpha_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 399) i WHERE i % 10 IN (1, 3, 4, 6, 8, 9);
4886 INSERT INTO alpha_pos SELECT 1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 399) i WHERE i % 10 IN (1, 3, 4, 6, 8, 9);
4888 CREATE TABLE beta (a double precision, b int, c text) PARTITION BY RANGE (a);
4889 CREATE TABLE beta_neg PARTITION OF beta FOR VALUES FROM (-10.0) TO (0) PARTITION BY RANGE (b);
4890 CREATE TABLE beta_pos PARTITION OF beta FOR VALUES FROM (0) TO ('Infinity') PARTITION BY LIST (c);
4891 CREATE TABLE beta_neg_p1 PARTITION OF beta_neg FOR VALUES FROM (100) TO (150);
4892 CREATE TABLE beta_neg_p2 PARTITION OF beta_neg FOR VALUES FROM (200) TO (300);
4893 CREATE TABLE beta_neg_p3 PARTITION OF beta_neg FOR VALUES FROM (350) TO (500);
4894 CREATE TABLE beta_pos_p1 PARTITION OF beta_pos FOR VALUES IN ('0002', '0003');
4895 CREATE TABLE beta_pos_p2 PARTITION OF beta_pos FOR VALUES IN ('0004', '0006');
4896 CREATE TABLE beta_pos_p3 PARTITION OF beta_pos FOR VALUES IN ('0007', '0009');
4897 INSERT INTO beta_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 149) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
4898 INSERT INTO beta_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(200, 299) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
4899 INSERT INTO beta_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(350, 499) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
4900 INSERT INTO beta_pos SELECT 1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 149) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
4901 INSERT INTO beta_pos SELECT 1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(200, 299) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
4902 INSERT INTO beta_pos SELECT 1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(350, 499) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
4905 SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b) WHERE t1.b >= 125 AND t1.b < 225 ORDER BY t1.a, t1.b;
4907 --------------------------------------------------------------------
4909 Sort Key: t1.a, t1.b
4912 Hash Cond: ((t1_1.a = t2_1.a) AND (t1_1.b = t2_1.b))
4913 -> Seq Scan on alpha_neg_p1 t1_1
4914 Filter: ((b >= 125) AND (b < 225))
4916 -> Seq Scan on beta_neg_p1 t2_1
4918 Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.b = t1_2.b))
4919 -> Seq Scan on beta_neg_p2 t2_2
4921 -> Seq Scan on alpha_neg_p2 t1_2
4922 Filter: ((b >= 125) AND (b < 225))
4924 Hash Cond: ((t2_4.a = t1_4.a) AND (t2_4.b = t1_4.b))
4926 -> Seq Scan on beta_pos_p1 t2_4
4927 -> Seq Scan on beta_pos_p2 t2_5
4928 -> Seq Scan on beta_pos_p3 t2_6
4931 -> Seq Scan on alpha_pos_p1 t1_4
4932 Filter: ((b >= 125) AND (b < 225))
4933 -> Seq Scan on alpha_pos_p2 t1_5
4934 Filter: ((b >= 125) AND (b < 225))
4935 -> Seq Scan on alpha_pos_p3 t1_6
4936 Filter: ((b >= 125) AND (b < 225))
4939 SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b) WHERE t1.b >= 125 AND t1.b < 225 ORDER BY t1.a, t1.b;
4940 a | b | c | a | b | c
4941 ----+-----+------+----+-----+------
4942 -1 | 126 | 0006 | -1 | 126 | 0006
4943 -1 | 129 | 0009 | -1 | 129 | 0009
4944 -1 | 133 | 0003 | -1 | 133 | 0003
4945 -1 | 134 | 0004 | -1 | 134 | 0004
4946 -1 | 136 | 0006 | -1 | 136 | 0006
4947 -1 | 139 | 0009 | -1 | 139 | 0009
4948 -1 | 143 | 0003 | -1 | 143 | 0003
4949 -1 | 144 | 0004 | -1 | 144 | 0004
4950 -1 | 146 | 0006 | -1 | 146 | 0006
4951 -1 | 149 | 0009 | -1 | 149 | 0009
4952 -1 | 203 | 0003 | -1 | 203 | 0003
4953 -1 | 204 | 0004 | -1 | 204 | 0004
4954 -1 | 206 | 0006 | -1 | 206 | 0006
4955 -1 | 209 | 0009 | -1 | 209 | 0009
4956 -1 | 213 | 0003 | -1 | 213 | 0003
4957 -1 | 214 | 0004 | -1 | 214 | 0004
4958 -1 | 216 | 0006 | -1 | 216 | 0006
4959 -1 | 219 | 0009 | -1 | 219 | 0009
4960 -1 | 223 | 0003 | -1 | 223 | 0003
4961 -1 | 224 | 0004 | -1 | 224 | 0004
4962 1 | 126 | 0006 | 1 | 126 | 0006
4963 1 | 129 | 0009 | 1 | 129 | 0009
4964 1 | 133 | 0003 | 1 | 133 | 0003
4965 1 | 134 | 0004 | 1 | 134 | 0004
4966 1 | 136 | 0006 | 1 | 136 | 0006
4967 1 | 139 | 0009 | 1 | 139 | 0009
4968 1 | 143 | 0003 | 1 | 143 | 0003
4969 1 | 144 | 0004 | 1 | 144 | 0004
4970 1 | 146 | 0006 | 1 | 146 | 0006
4971 1 | 149 | 0009 | 1 | 149 | 0009
4972 1 | 203 | 0003 | 1 | 203 | 0003
4973 1 | 204 | 0004 | 1 | 204 | 0004
4974 1 | 206 | 0006 | 1 | 206 | 0006
4975 1 | 209 | 0009 | 1 | 209 | 0009
4976 1 | 213 | 0003 | 1 | 213 | 0003
4977 1 | 214 | 0004 | 1 | 214 | 0004
4978 1 | 216 | 0006 | 1 | 216 | 0006
4979 1 | 219 | 0009 | 1 | 219 | 0009
4980 1 | 223 | 0003 | 1 | 223 | 0003
4981 1 | 224 | 0004 | 1 | 224 | 0004
4985 SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE ((t1.b >= 100 AND t1.b < 110) OR (t1.b >= 200 AND t1.b < 210)) AND ((t2.b >= 100 AND t2.b < 110) OR (t2.b >= 200 AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDER BY t1.a, t1.b, t2.b;
4987 --------------------------------------------------------------------------------------------------------------------------------------
4989 Sort Key: t1.a, t1.b, t2.b
4992 Hash Cond: ((t1_2.a = t2_2.a) AND (t1_2.c = t2_2.c))
4994 -> Seq Scan on alpha_neg_p1 t1_2
4995 Filter: ((c = ANY ('{0004,0009}'::text[])) AND (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210))))
4996 -> Seq Scan on alpha_neg_p2 t1_3
4997 Filter: ((c = ANY ('{0004,0009}'::text[])) AND (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210))))
5000 -> Seq Scan on beta_neg_p1 t2_2
5001 Filter: (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210)))
5002 -> Seq Scan on beta_neg_p2 t2_3
5003 Filter: (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210)))
5005 Join Filter: ((t1_4.a = t2_4.a) AND (t1_4.c = t2_4.c))
5006 -> Seq Scan on alpha_pos_p2 t1_4
5007 Filter: ((c = ANY ('{0004,0009}'::text[])) AND (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210))))
5008 -> Seq Scan on beta_pos_p2 t2_4
5009 Filter: (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210)))
5011 Join Filter: ((t1_5.a = t2_5.a) AND (t1_5.c = t2_5.c))
5012 -> Seq Scan on alpha_pos_p3 t1_5
5013 Filter: ((c = ANY ('{0004,0009}'::text[])) AND (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210))))
5014 -> Seq Scan on beta_pos_p3 t2_5
5015 Filter: (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210)))
5018 SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE ((t1.b >= 100 AND t1.b < 110) OR (t1.b >= 200 AND t1.b < 210)) AND ((t2.b >= 100 AND t2.b < 110) OR (t2.b >= 200 AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDER BY t1.a, t1.b, t2.b;
5019 a | b | c | a | b | c
5020 ----+-----+------+----+-----+------
5021 -1 | 104 | 0004 | -1 | 104 | 0004
5022 -1 | 104 | 0004 | -1 | 204 | 0004
5023 -1 | 109 | 0009 | -1 | 109 | 0009
5024 -1 | 109 | 0009 | -1 | 209 | 0009
5025 -1 | 204 | 0004 | -1 | 104 | 0004
5026 -1 | 204 | 0004 | -1 | 204 | 0004
5027 -1 | 209 | 0009 | -1 | 109 | 0009
5028 -1 | 209 | 0009 | -1 | 209 | 0009
5029 1 | 104 | 0004 | 1 | 104 | 0004
5030 1 | 104 | 0004 | 1 | 204 | 0004
5031 1 | 109 | 0009 | 1 | 109 | 0009
5032 1 | 109 | 0009 | 1 | 209 | 0009
5033 1 | 204 | 0004 | 1 | 104 | 0004
5034 1 | 204 | 0004 | 1 | 204 | 0004
5035 1 | 209 | 0009 | 1 | 109 | 0009
5036 1 | 209 | 0009 | 1 | 209 | 0009
5040 SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) WHERE ((t1.b >= 100 AND t1.b < 110) OR (t1.b >= 200 AND t1.b < 210)) AND ((t2.b >= 100 AND t2.b < 110) OR (t2.b >= 200 AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDER BY t1.a, t1.b;
5042 --------------------------------------------------------------------------------------------------------------------------------
5044 Sort Key: t1.a, t1.b
5047 Hash Cond: ((t1_1.a = t2_1.a) AND (t1_1.b = t2_1.b) AND (t1_1.c = t2_1.c))
5048 -> Seq Scan on alpha_neg_p1 t1_1
5049 Filter: ((c = ANY ('{0004,0009}'::text[])) AND (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210))))
5051 -> Seq Scan on beta_neg_p1 t2_1
5052 Filter: (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210)))
5054 Hash Cond: ((t1_2.a = t2_2.a) AND (t1_2.b = t2_2.b) AND (t1_2.c = t2_2.c))
5055 -> Seq Scan on alpha_neg_p2 t1_2
5056 Filter: ((c = ANY ('{0004,0009}'::text[])) AND (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210))))
5058 -> Seq Scan on beta_neg_p2 t2_2
5059 Filter: (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210)))
5061 Join Filter: ((t1_3.a = t2_3.a) AND (t1_3.b = t2_3.b) AND (t1_3.c = t2_3.c))
5062 -> Seq Scan on alpha_pos_p2 t1_3
5063 Filter: ((c = ANY ('{0004,0009}'::text[])) AND (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210))))
5064 -> Seq Scan on beta_pos_p2 t2_3
5065 Filter: (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210)))
5067 Join Filter: ((t1_4.a = t2_4.a) AND (t1_4.b = t2_4.b) AND (t1_4.c = t2_4.c))
5068 -> Seq Scan on alpha_pos_p3 t1_4
5069 Filter: ((c = ANY ('{0004,0009}'::text[])) AND (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210))))
5070 -> Seq Scan on beta_pos_p3 t2_4
5071 Filter: (((b >= 100) AND (b < 110)) OR ((b >= 200) AND (b < 210)))
5074 SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) WHERE ((t1.b >= 100 AND t1.b < 110) OR (t1.b >= 200 AND t1.b < 210)) AND ((t2.b >= 100 AND t2.b < 110) OR (t2.b >= 200 AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDER BY t1.a, t1.b;
5075 a | b | c | a | b | c
5076 ----+-----+------+----+-----+------
5077 -1 | 104 | 0004 | -1 | 104 | 0004
5078 -1 | 109 | 0009 | -1 | 109 | 0009
5079 -1 | 204 | 0004 | -1 | 204 | 0004
5080 -1 | 209 | 0009 | -1 | 209 | 0009
5081 1 | 104 | 0004 | 1 | 104 | 0004
5082 1 | 109 | 0009 | 1 | 109 | 0009
5083 1 | 204 | 0004 | 1 | 204 | 0004
5084 1 | 209 | 0009 | 1 | 209 | 0009
5087 -- partitionwise join with fractional paths
5088 CREATE TABLE fract_t (id BIGINT, PRIMARY KEY (id)) PARTITION BY RANGE (id);
5089 CREATE TABLE fract_t0 PARTITION OF fract_t FOR VALUES FROM ('0') TO ('1000');
5090 CREATE TABLE fract_t1 PARTITION OF fract_t FOR VALUES FROM ('1000') TO ('2000');
5092 INSERT INTO fract_t (id) (SELECT generate_series(0, 1999));
5094 -- verify plan; nested index only scans
5095 SET max_parallel_workers_per_gather = 0;
5096 SET enable_partitionwise_join = on;
5098 SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) ORDER BY x.id ASC LIMIT 10;
5100 -----------------------------------------------------------------------
5105 Merge Cond: (x_1.id = y_1.id)
5106 -> Index Only Scan using fract_t0_pkey on fract_t0 x_1
5107 -> Index Only Scan using fract_t0_pkey on fract_t0 y_1
5109 Merge Cond: (x_2.id = y_2.id)
5110 -> Index Only Scan using fract_t1_pkey on fract_t1 x_2
5111 -> Index Only Scan using fract_t1_pkey on fract_t1 y_2
5115 SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) ORDER BY x.id DESC LIMIT 10;
5117 --------------------------------------------------------------------------------
5121 -> Nested Loop Left Join
5122 -> Index Only Scan Backward using fract_t0_pkey on fract_t0 x_1
5123 -> Index Only Scan using fract_t0_pkey on fract_t0 y_1
5124 Index Cond: (id = x_1.id)
5125 -> Nested Loop Left Join
5126 -> Index Only Scan Backward using fract_t1_pkey on fract_t1 x_2
5127 -> Index Only Scan using fract_t1_pkey on fract_t1 y_2
5128 Index Cond: (id = x_2.id)
5133 RESET max_parallel_workers_per_gather;
5134 RESET enable_partitionwise_join;