123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608 |
- --
- -- JOIN
- -- Test JOIN clauses
- --
- CREATE TABLE J1_TBL (
- i integer,
- j integer,
- t text
- );
- CREATE TABLE J2_TBL (
- i integer,
- k integer
- );
- INSERT INTO J1_TBL VALUES (1, 4, 'one');
- INSERT INTO J1_TBL VALUES (2, 3, 'two');
- INSERT INTO J1_TBL VALUES (3, 2, 'three');
- INSERT INTO J1_TBL VALUES (4, 1, 'four');
- INSERT INTO J1_TBL VALUES (5, 0, 'five');
- INSERT INTO J1_TBL VALUES (6, 6, 'six');
- INSERT INTO J1_TBL VALUES (7, 7, 'seven');
- INSERT INTO J1_TBL VALUES (8, 8, 'eight');
- INSERT INTO J1_TBL VALUES (0, NULL, 'zero');
- INSERT INTO J1_TBL VALUES (NULL, NULL, 'null');
- INSERT INTO J1_TBL VALUES (NULL, 0, 'zero');
- INSERT INTO J2_TBL VALUES (1, -1);
- INSERT INTO J2_TBL VALUES (2, 2);
- INSERT INTO J2_TBL VALUES (3, -3);
- INSERT INTO J2_TBL VALUES (2, 4);
- INSERT INTO J2_TBL VALUES (5, -5);
- INSERT INTO J2_TBL VALUES (5, -5);
- INSERT INTO J2_TBL VALUES (0, NULL);
- INSERT INTO J2_TBL VALUES (NULL, NULL);
- INSERT INTO J2_TBL VALUES (NULL, 0);
- -- useful in some tests below
- create temp table onerow();
- --
- -- CORRELATION NAMES
- -- Make sure that table/column aliases are supported
- -- before diving into more complex join syntax.
- --
- SELECT *
- FROM J1_TBL AS tx;
- i | j | t
- ---+---+-------
- 1 | 4 | one
- 2 | 3 | two
- 3 | 2 | three
- 4 | 1 | four
- 5 | 0 | five
- 6 | 6 | six
- 7 | 7 | seven
- 8 | 8 | eight
- 0 | | zero
- | | null
- | 0 | zero
- (11 rows)
- SELECT *
- FROM J1_TBL tx;
- i | j | t
- ---+---+-------
- 1 | 4 | one
- 2 | 3 | two
- 3 | 2 | three
- 4 | 1 | four
- 5 | 0 | five
- 6 | 6 | six
- 7 | 7 | seven
- 8 | 8 | eight
- 0 | | zero
- | | null
- | 0 | zero
- (11 rows)
- SELECT *
- FROM J1_TBL AS t1 (a, b, c);
- a | b | c
- ---+---+-------
- 1 | 4 | one
- 2 | 3 | two
- 3 | 2 | three
- 4 | 1 | four
- 5 | 0 | five
- 6 | 6 | six
- 7 | 7 | seven
- 8 | 8 | eight
- 0 | | zero
- | | null
- | 0 | zero
- (11 rows)
- SELECT *
- FROM J1_TBL t1 (a, b, c);
- a | b | c
- ---+---+-------
- 1 | 4 | one
- 2 | 3 | two
- 3 | 2 | three
- 4 | 1 | four
- 5 | 0 | five
- 6 | 6 | six
- 7 | 7 | seven
- 8 | 8 | eight
- 0 | | zero
- | | null
- | 0 | zero
- (11 rows)
- SELECT *
- FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, d) USING (a)
- ORDER BY a, d;
- a | b | c | d
- ---+---+-------+----
- 0 | | zero |
- 1 | 4 | one | -1
- 2 | 3 | two | 2
- 2 | 3 | two | 4
- 3 | 2 | three | -3
- 5 | 0 | five | -5
- 5 | 0 | five | -5
- (7 rows)
- -- test join using aliases
- SELECT * FROM J1_TBL JOIN J2_TBL USING (i) WHERE J1_TBL.t = 'one'; -- ok
- i | j | t | k
- ---+---+-----+----
- 1 | 4 | one | -1
- (1 row)
- SELECT *
- FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (k = 1);
- i | j | t | k
- ---+---+---+---
- (0 rows)
- --
- -- More complicated constructs
- --
- --
- -- Multiway full join
- --
- CREATE TABLE t1 (name TEXT, n INTEGER);
- CREATE TABLE t2 (name TEXT, n INTEGER);
- CREATE TABLE t3 (name TEXT, n INTEGER);
- INSERT INTO t1 VALUES ( 'bb', 11 );
- INSERT INTO t2 VALUES ( 'bb', 12 );
- INSERT INTO t2 VALUES ( 'cc', 22 );
- INSERT INTO t2 VALUES ( 'ee', 42 );
- INSERT INTO t3 VALUES ( 'bb', 13 );
- INSERT INTO t3 VALUES ( 'cc', 23 );
- INSERT INTO t3 VALUES ( 'dd', 33 );
- -- Test for propagation of nullability constraints into sub-joins
- create temp table x (x1 int, x2 int);
- insert into x values (1,11);
- insert into x values (2,22);
- insert into x values (3,null);
- insert into x values (4,44);
- insert into x values (5,null);
- create temp table y (y1 int, y2 int);
- insert into y values (1,111);
- insert into y values (2,222);
- insert into y values (3,333);
- insert into y values (4,null);
- select * from x;
- x1 | x2
- ----+----
- 1 | 11
- 2 | 22
- 3 |
- 4 | 44
- 5 |
- (5 rows)
- select * from y;
- y1 | y2
- ----+-----
- 1 | 111
- 2 | 222
- 3 | 333
- 4 |
- (4 rows)
- select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
- on (x1 = xx1);
- x1 | x2 | y1 | y2 | xx1 | xx2
- ----+----+----+-----+-----+-----
- 1 | 11 | 1 | 111 | 1 | 11
- 2 | 22 | 2 | 222 | 2 | 22
- 3 | | 3 | 333 | 3 |
- 4 | 44 | 4 | | 4 | 44
- 5 | | | | 5 |
- (5 rows)
- select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
- on (x1 = xx1 and xx2 is not null);
- x1 | x2 | y1 | y2 | xx1 | xx2
- ----+----+----+-----+-----+-----
- 1 | 11 | 1 | 111 | 1 | 11
- 2 | 22 | 2 | 222 | 2 | 22
- 3 | | 3 | 333 | |
- 4 | 44 | 4 | | 4 | 44
- 5 | | | | |
- (5 rows)
- -- these should NOT give the same answers as above
- select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
- on (x1 = xx1) where (x2 is not null);
- x1 | x2 | y1 | y2 | xx1 | xx2
- ----+----+----+-----+-----+-----
- 1 | 11 | 1 | 111 | 1 | 11
- 2 | 22 | 2 | 222 | 2 | 22
- 4 | 44 | 4 | | 4 | 44
- (3 rows)
- select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
- on (x1 = xx1) where (y2 is not null);
- x1 | x2 | y1 | y2 | xx1 | xx2
- ----+----+----+-----+-----+-----
- 1 | 11 | 1 | 111 | 1 | 11
- 2 | 22 | 2 | 222 | 2 | 22
- 3 | | 3 | 333 | 3 |
- (3 rows)
- select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
- on (x1 = xx1) where (xx2 is not null);
- x1 | x2 | y1 | y2 | xx1 | xx2
- ----+----+----+-----+-----+-----
- 1 | 11 | 1 | 111 | 1 | 11
- 2 | 22 | 2 | 222 | 2 | 22
- 4 | 44 | 4 | | 4 | 44
- (3 rows)
- --
- -- regression test: check for bug with propagation of implied equality
- -- to outside an IN
- --
- select count(*) from tenk1 a where unique1 in
- (select unique1 from tenk1 b join tenk1 c using (unique1)
- where b.unique2 = 42);
- count
- -------
- 1
- (1 row)
- -- try that with GEQO too
- begin;
- rollback;
- --
- -- regression test: check a case where join_clause_is_movable_into() gives
- -- an imprecise result, causing an assertion failure
- --
- select count(*)
- from
- (select t3.tenthous as x1, coalesce(t1.stringu1, t2.stringu1) as x2
- from tenk1 t1
- left join tenk1 t2 on t1.unique1 = t2.unique1
- join tenk1 t3 on t1.unique2 = t3.unique2) ss,
- tenk1 t4,
- tenk1 t5
- where t4.thousand = t5.unique1 and ss.x1 = t4.tenthous and ss.x2 = t5.stringu1;
- count
- -------
- 1000
- (1 row)
- select count(*) from
- (select * from tenk1 x order by x.thousand, x.twothousand, x.fivethous) x
- left join
- (select * from tenk1 y order by y.unique2) y
- on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2;
- count
- -------
- 10000
- (1 row)
- --
- -- Clean up
- --
- DROP TABLE t1;
- DROP TABLE t2;
- DROP TABLE t3;
- DROP TABLE J1_TBL;
- DROP TABLE J2_TBL;
- -- Both DELETE and UPDATE allow the specification of additional tables
- -- to "join" against to determine which rows should be modified.
- CREATE TEMP TABLE t1 (a int, b int);
- CREATE TEMP TABLE t2 (a int, b int);
- CREATE TEMP TABLE t3 (x int, y int);
- INSERT INTO t1 VALUES (5, 10);
- INSERT INTO t1 VALUES (15, 20);
- INSERT INTO t1 VALUES (100, 100);
- INSERT INTO t1 VALUES (200, 1000);
- INSERT INTO t2 VALUES (200, 2000);
- INSERT INTO t3 VALUES (5, 20);
- INSERT INTO t3 VALUES (6, 7);
- INSERT INTO t3 VALUES (7, 8);
- INSERT INTO t3 VALUES (500, 100);
- --
- -- regression test for 8.1 merge right join bug
- --
- CREATE TEMP TABLE tt1 ( tt1_id int4, joincol int4 );
- INSERT INTO tt1 VALUES (1, 11);
- INSERT INTO tt1 VALUES (2, NULL);
- CREATE TEMP TABLE tt2 ( tt2_id int4, joincol int4 );
- INSERT INTO tt2 VALUES (21, 11);
- INSERT INTO tt2 VALUES (22, 11);
- select count(*) from tenk1 a, tenk1 b
- where a.hundred = b.thousand and (b.fivethous % 10) < 10;
- count
- --------
- 100000
- (1 row)
- --
- -- regression test for 8.2 bug with improper re-ordering of left joins
- --
- create temp table tt3(f1 int, f2 text);
- insert into tt3 select x, repeat('xyzzy', 100) from generate_series(1,10000) x;
- create index tt3i on tt3(f1);
- create temp table tt4(f1 int);
- insert into tt4 values (0),(1),(9999);
- --
- -- regression test for proper handling of outer joins within antijoins
- --
- create temp table tt4x(c1 int, c2 int, c3 int);
- --
- -- regression test for problems of the sort depicted in bug #3494
- --
- create temp table tt5(f1 int, f2 int);
- create temp table tt6(f1 int, f2 int);
- insert into tt5 values(1, 10);
- insert into tt5 values(1, 11);
- insert into tt6 values(1, 9);
- insert into tt6 values(1, 2);
- insert into tt6 values(2, 9);
- --
- -- regression test for problems of the sort depicted in bug #3588
- --
- create temp table xx (pkxx int);
- create temp table yy (pkyy int, pkxx int);
- insert into xx values (1);
- insert into xx values (2);
- insert into xx values (3);
- insert into yy values (101, 1);
- insert into yy values (201, 2);
- insert into yy values (301, NULL);
- --
- -- regression test for improper pushing of constants across outer-join clauses
- -- (as seen in early 8.2.x releases)
- --
- create temp table zt1 (f1 int primary key);
- create temp table zt2 (f2 int primary key);
- create temp table zt3 (f3 int primary key);
- insert into zt1 values(53);
- insert into zt2 values(53);
- select * from
- zt2 left join zt3 on (f2 = f3)
- left join zt1 on (f3 = f1)
- where f2 = 53;
- f2 | f3 | f1
- ----+----+----
- 53 | |
- (1 row)
- --
- -- test for sane behavior with noncanonical merge clauses, per bug #4926
- --
- begin;
- create temp table a (i integer);
- create temp table b (x integer, y integer);
- select * from a left join b on i = x and i = y and x = i;
- i | x | y
- ---+---+---
- (0 rows)
- rollback;
- --
- -- test handling of merge clauses using record_ops
- --
- begin;
- create temp table tidv (idv mycomptype);
- create index on tidv (idv);
- rollback;
- --
- -- test incorrect failure to NULL pulled-up subexpressions
- --
- begin;
- create temp table a (
- code char not null,
- constraint a_pk primary key (code)
- );
- create temp table b (
- a char not null,
- num integer not null,
- constraint b_pk primary key (a, num)
- );
- create temp table c (
- name char not null,
- a char,
- constraint c_pk primary key (name)
- );
- insert into a (code) values ('p');
- insert into a (code) values ('q');
- insert into b (a, num) values ('p', 1);
- insert into b (a, num) values ('p', 2);
- insert into c (name, a) values ('A', 'p');
- insert into c (name, a) values ('B', 'q');
- insert into c (name, a) values ('C', null);
- rollback;
- --
- -- test incorrect handling of placeholders that only appear in targetlists,
- -- per bug #6154
- --
- SELECT * FROM
- ( SELECT 1 as key1 ) sub1
- LEFT JOIN
- ( SELECT sub3.key3, sub4.value2, COALESCE(sub4.value2, 66) as value3 FROM
- ( SELECT 1 as key3 ) sub3
- LEFT JOIN
- ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM
- ( SELECT 1 as key5 ) sub5
- LEFT JOIN
- ( SELECT 2 as key6, 42 as value1 ) sub6
- ON sub5.key5 = sub6.key6
- ) sub4
- ON sub4.key5 = sub3.key3
- ) sub2
- ON sub1.key1 = sub2.key3;
- key1 | key3 | value2 | value3
- ------+------+--------+--------
- 1 | 1 | 1 | 1
- (1 row)
- -- test the path using join aliases, too
- SELECT * FROM
- ( SELECT 1 as key1 ) sub1
- LEFT JOIN
- ( SELECT sub3.key3, value2, COALESCE(value2, 66) as value3 FROM
- ( SELECT 1 as key3 ) sub3
- LEFT JOIN
- ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM
- ( SELECT 1 as key5 ) sub5
- LEFT JOIN
- ( SELECT 2 as key6, 42 as value1 ) sub6
- ON sub5.key5 = sub6.key6
- ) sub4
- ON sub4.key5 = sub3.key3
- ) sub2
- ON sub1.key1 = sub2.key3;
- key1 | key3 | value2 | value3
- ------+------+--------+--------
- 1 | 1 | 1 | 1
- (1 row)
- --
- -- nested nestloops can require nested PlaceHolderVars
- --
- create temp table nt1 (
- id int primary key,
- a1 boolean,
- a2 boolean
- );
- insert into nt1 values (1,true,true);
- insert into nt1 values (2,true,false);
- insert into nt1 values (3,false,false);
- select * from
- int8_tbl t1 left join
- (select q1 as x, 42 as y from int8_tbl t2) ss
- on t1.q2 = ss.x
- where
- 1 = (select 1 from int8_tbl t3 where ss.y is not null limit 1)
- order by 1,2;
- q1 | q2 | x | y
- ------------------+------------------+------------------+----
- 123 | 4567890123456789 | 4567890123456789 | 42
- 123 | 4567890123456789 | 4567890123456789 | 42
- 123 | 4567890123456789 | 4567890123456789 | 42
- 4567890123456789 | 123 | 123 | 42
- 4567890123456789 | 123 | 123 | 42
- 4567890123456789 | 4567890123456789 | 4567890123456789 | 42
- 4567890123456789 | 4567890123456789 | 4567890123456789 | 42
- 4567890123456789 | 4567890123456789 | 4567890123456789 | 42
- (8 rows)
- select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from
- tenk1 t1
- inner join int4_tbl i1
- left join (select v1.x2, v2.y1, 11 AS d1
- from (values(1,0)) v1(x1,x2)
- left join (values(3,1)) v2(y1,y2)
- on v1.x1 = v2.y2) subq1
- on (i1.f1 = subq1.x2)
- on (t1.unique2 = subq1.d1)
- left join tenk1 t2
- on (subq1.y1 = t2.unique1)
- where t1.unique2 < 42 and t1.stringu1 > t2.stringu2;
- unique2 | stringu1 | unique1 | stringu2
- ---------+----------+---------+----------
- 11 | WFAAAA | 3 | LKIAAA
- (1 row)
- select count(*) from
- tenk1 a join tenk1 b on a.unique1 = b.unique2
- left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand
- join int4_tbl on b.thousand = f1;
- count
- -------
- 10
- (1 row)
- select f1, unique2, case when unique2 is null then f1 else 0 end
- from int4_tbl a left join tenk1 b on f1 = unique2
- where (case when unique2 is null then f1 else 0 end) = 0;
- f1 | unique2 | case
- ----+---------+------
- 0 | 0 | 0
- (1 row)
- --
- -- test join removal
- --
- begin;
- CREATE TEMP TABLE a (id int PRIMARY KEY, b_id int);
- CREATE TEMP TABLE b (id int PRIMARY KEY, c_id int);
- CREATE TEMP TABLE c (id int PRIMARY KEY);
- CREATE TEMP TABLE d (a int, b int);
- INSERT INTO b VALUES (0, 0), (1, NULL);
- INSERT INTO c VALUES (0), (1);
- INSERT INTO d VALUES (1,3), (2,2), (3,1);
- rollback;
- create temp table parent (k int primary key, pd int);
- create temp table child (k int unique, cd int);
- insert into parent values (1, 10), (2, 20), (3, 30);
- insert into child values (1, 100), (4, 400);
- -- check for a 9.0rc1 bug: join removal breaks pseudoconstant qual handling
- select p.* from
- parent p left join child c on (p.k = c.k)
- where p.k = 1 and p.k = 2;
- k | pd
- ---+----
- (0 rows)
- select p.* from
- (parent p left join child c on (p.k = c.k)) join parent x on p.k = x.k
- where p.k = 1 and p.k = 2;
- k | pd
- ---+----
- (0 rows)
- -- bug 5255: this is not optimizable by join removal
- begin;
- CREATE TEMP TABLE a (id int PRIMARY KEY);
- CREATE TEMP TABLE b (id int PRIMARY KEY, a_id int);
- INSERT INTO a VALUES (0), (1);
- INSERT INTO b VALUES (0, 0), (1, NULL);
- rollback;
- -- another join removal bug: this is not optimizable, either
- begin;
- create temp table innertab (id int8 primary key, dat1 int8);
- insert into innertab values(123, 42);
- rollback;
- -- another join removal bug: we must clean up correctly when removing a PHV
- begin;
- create temp table uniquetbl (f1 text unique);
- rollback;
- create table join_ut1 (a int, b int, c varchar);
- insert into join_ut1 values (101, 101, 'y'), (2, 2, 'z');
- drop table join_ut1;
- --
- -- test estimation behavior with multi-column foreign key and constant qual
- --
- begin;
- create table fkest (x integer, x10 integer, x10b integer, x100 integer);
- insert into fkest select x, x/10, x/10, x/100 from generate_series(1,1000) x;
- rollback;
- --
- -- test that foreign key join estimation performs sanely for outer joins
- --
- begin;
- create table fkest (a int, b int, c int unique, primary key(a,b));
- create table fkest1 (a int, b int, primary key(a,b));
- insert into fkest select x/10, x%10, x from generate_series(1,1000) x;
- insert into fkest1 select x/10, x%10 from generate_series(1,1000) x;
- rollback;
- --
- -- test planner's ability to mark joins as unique
- --
- create table j1 (id int primary key);
- create table j2 (id int primary key);
- create table j3 (id int);
- insert into j1 values(1),(2),(3);
- insert into j2 values(1),(2),(3);
- insert into j3 values(1),(1);
- drop table j1;
- drop table j2;
- drop table j3;
- -- test more complex permutations of unique joins
- create table j1 (id1 int, id2 int, primary key(id1,id2));
- create table j2 (id1 int, id2 int, primary key(id1,id2));
- create table j3 (id1 int, id2 int, primary key(id1,id2));
- insert into j1 values(1,1),(1,2);
- insert into j2 values(1,1);
- insert into j3 values(1,1);
- -- need an additional row in j2, if we want j2_id1_idx to be preferred
- insert into j2 values(1,2);
- drop table j1;
- drop table j2;
- drop table j3;
|