should be it
This commit is contained in:
53
external/duckdb/test/sql/join/semianti/10406-anti-on-ints-strings.test
vendored
Normal file
53
external/duckdb/test/sql/join/semianti/10406-anti-on-ints-strings.test
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
# name: test/sql/join/semianti/10406-anti-on-ints-strings.test
|
||||
# description: github reported bug
|
||||
# group: [semianti]
|
||||
|
||||
statement ok
|
||||
create table test_str(k varchar);
|
||||
|
||||
statement ok
|
||||
create table test_str_del(pk varchar);
|
||||
|
||||
statement ok
|
||||
create table test_int(k bigint);
|
||||
|
||||
statement ok
|
||||
create table test_int_del(pk bigint);
|
||||
|
||||
statement ok
|
||||
insert into test_str values('abc'), ('def');
|
||||
|
||||
statement ok
|
||||
insert into test_int values(1), (2);
|
||||
|
||||
query I rowsort
|
||||
select l.* from test_str l anti join test_str_del r on l.k = r.pk;
|
||||
----
|
||||
abc
|
||||
def
|
||||
|
||||
query I rowsort
|
||||
select l.* from test_int l anti join test_int_del r on l.k = r.pk;
|
||||
----
|
||||
1
|
||||
2
|
||||
|
||||
statement ok
|
||||
insert into test_int VALUES (NULL);
|
||||
|
||||
query I rowsort
|
||||
select l.* from test_int l anti join test_int_del r on l.k is not distinct from r.pk;
|
||||
----
|
||||
1
|
||||
2
|
||||
NULL
|
||||
|
||||
statement ok
|
||||
insert into test_int_del VALUES (NULL);
|
||||
|
||||
# NULL is now not distinct from null
|
||||
query I rowsort
|
||||
select l.* from test_int l anti join test_int_del r on l.k is not distinct from r.pk;
|
||||
----
|
||||
1
|
||||
2
|
||||
166
external/duckdb/test/sql/join/semianti/antijoin.test
vendored
Normal file
166
external/duckdb/test/sql/join/semianti/antijoin.test
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
# name: test/sql/join/semianti/antijoin.test
|
||||
# description: Test positional joins
|
||||
# group: [semianti]
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification
|
||||
|
||||
statement ok
|
||||
CREATE TABLE left_table (a INTEGER, b INTEGER, c INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES(42, 1, 1), (43, 1, 1);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE right_table (a INTEGER, b INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES(42, 1);
|
||||
|
||||
# STAR expression expands only the left table
|
||||
query III
|
||||
SELECT * FROM left_table ANTI JOIN right_table ON left_table.a = right_table.a;
|
||||
----
|
||||
43 1 1
|
||||
|
||||
# can filter on columns in left table
|
||||
query III
|
||||
SELECT * FROM left_table ANTI JOIN right_table ON left_table.a = right_table.a WHERE a > 5;
|
||||
----
|
||||
43 1 1
|
||||
|
||||
# can have list type expressions in the condition
|
||||
query III
|
||||
SELECT * FROM left_table ANTI JOIN right_table ON ([left_table.a, left_table.b] = [right_table.a, right_table.b]);
|
||||
----
|
||||
43 1 1
|
||||
|
||||
# right table can be a subquery
|
||||
query III
|
||||
SELECT * FROM left_table ANTI JOIN (SELECT a as foo from right_table where b = 1) buzz ON left_table.a = buzz.foo
|
||||
----
|
||||
43 1 1
|
||||
|
||||
# Should throw error when filtering on column in right table
|
||||
statement error
|
||||
SELECT * FROM left_table ANTI JOIN right_table ON left_table.a = right_table.a WHERE right_table.a < 43;
|
||||
----
|
||||
Binder Error
|
||||
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES (43, 1, 5), (43, 1, 5), (43, 1, 5), (43, 1, 5);
|
||||
|
||||
# left results are not deduplicated
|
||||
query III
|
||||
SELECT * FROM left_table ANTI JOIN right_table ON (left_table.a = right_table.a);
|
||||
----
|
||||
43 1 1
|
||||
43 1 5
|
||||
43 1 5
|
||||
43 1 5
|
||||
43 1 5
|
||||
|
||||
query I
|
||||
CREATE TABLE other (a INTEGER, b INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO other VALUES (42, 1), (43, 1);
|
||||
|
||||
# a table that is the result of a join can also be anti joined on
|
||||
query III
|
||||
SELECT * FROM left_table
|
||||
ANTI JOIN (select right_table.a FROM right_table JOIN other ON (other.a = right_table.a)) joined_right_table
|
||||
ON left_table.a = joined_right_table.a;
|
||||
----
|
||||
43 1 1
|
||||
43 1 5
|
||||
43 1 5
|
||||
43 1 5
|
||||
43 1 5
|
||||
|
||||
statement ok
|
||||
DELETE FROM left_table where c=5;
|
||||
|
||||
# USING COLUMNS also works
|
||||
query III
|
||||
SELECT * FROM left_table ANTI JOIN right_table USING (a);
|
||||
----
|
||||
43 1 1
|
||||
|
||||
# natural anti join works
|
||||
query III
|
||||
SELECT * FROM left_table NATURAL ANTI JOIN right_table;
|
||||
----
|
||||
43 1 1
|
||||
|
||||
query III
|
||||
SELECT * FROM left_table
|
||||
NATURAL ANTI JOIN (select right_table.a FROM right_table JOIN other ON (other.a = right_table.a)) joined_right_table;
|
||||
----
|
||||
43 1 1
|
||||
|
||||
# right_table.a and left_table.a have the value 42
|
||||
# only left_table.a has the value 43
|
||||
# test inequality joins
|
||||
query III
|
||||
SELECT * FROM left_table ANTI JOIN right_table ON (left_table.a <> right_table.a) ORDER BY a, c;
|
||||
----
|
||||
42 1 1
|
||||
|
||||
|
||||
# range joins
|
||||
query III
|
||||
SELECT * FROM left_table ANTI JOIN right_table ON (left_table.a > right_table.a);
|
||||
----
|
||||
42 1 1
|
||||
|
||||
|
||||
statement ok
|
||||
SELECT * from left_table, right_table;
|
||||
|
||||
# complex condition resulting in an any join
|
||||
query III
|
||||
SELECT * FROM left_table ANTI JOIN right_table ON (left_table.a + right_table.a = 85 OR left_table.a + right_table.b = 84) order by left_table.a, left_table.c;
|
||||
----
|
||||
42 1 1
|
||||
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES (1, 42), (1, 42);
|
||||
|
||||
# Insert more values so that the scan side in the cross product is the right hand side
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES (42, 1, 5), (42, 1, 5), (42, 1, 5), (2000, 20000, 200000);
|
||||
|
||||
# complex condition resulting in an any join
|
||||
query III
|
||||
SELECT * FROM left_table ANTI JOIN right_table ON (left_table.a + right_table.a = 85 OR left_table.a + right_table.b = 84) order by left_table.a, left_table.c;
|
||||
----
|
||||
2000 20000 200000
|
||||
|
||||
# correlated subqueries
|
||||
query II
|
||||
SELECT a as outer_a, (SELECT MAX(right_table.b) FROM right_table where right_table.a != outer_a) right_table_b FROM left_table ANTI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
43 42
|
||||
2000 42
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES (1, 20);
|
||||
|
||||
# correlated subqueries
|
||||
query II
|
||||
SELECT a as outer_a, (SELECT MAX(b) FROM right_table where right_table.a != outer_a) right_table_b FROM left_table ANTI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
43 42
|
||||
2000 42
|
||||
|
||||
statement ok
|
||||
SET scalar_subquery_error_on_multiple_rows=false
|
||||
|
||||
# this is probably not deterministic
|
||||
query II
|
||||
SELECT a as outer_a, (SELECT b FROM right_table where right_table.a != outer_a) right_table_b FROM left_table ANTI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
43 20
|
||||
2000 20
|
||||
87
external/duckdb/test/sql/join/semianti/plan_blockwise_NL_join_with_mutliple_conditions.test
vendored
Normal file
87
external/duckdb/test/sql/join/semianti/plan_blockwise_NL_join_with_mutliple_conditions.test
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
# name: test/sql/join/semianti/plan_blockwise_NL_join_with_mutliple_conditions.test
|
||||
# description: Test anti ijoin results
|
||||
# group: [semianti]
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification
|
||||
|
||||
statement ok
|
||||
create table t1 as select * from values (1, 2), (2, 4), (3, 8), (6, 25), (1, 25) t(a, b);
|
||||
|
||||
statement ok
|
||||
create table t2 as select * from values (4), (5) t(b);
|
||||
|
||||
query II
|
||||
select * from t1 semi join t2 on t1.a < t2.b and t1.b > t2.b order by all;
|
||||
----
|
||||
1 25
|
||||
3 8
|
||||
|
||||
query II
|
||||
select * from t1 anti join t2 on t1.a < t2.b and t1.b < t2.b order by all;
|
||||
----
|
||||
1 25
|
||||
3 8
|
||||
6 25
|
||||
|
||||
query II
|
||||
Explain select * from t1 anti join t2 on t1.a < t2.b and t1.b < t2.b order by all;
|
||||
----
|
||||
physical_plan <REGEX>:.*BLOCKWISE_NL_JOIN.*
|
||||
|
||||
query II
|
||||
select * from t1 anti join t2 on t1.a < t2.b and t1.b < t2.b order by all;
|
||||
----
|
||||
1 25
|
||||
3 8
|
||||
6 25
|
||||
|
||||
query II
|
||||
select * from t1 semi join t2 on t1.a < t2.b or t1.b < t2.b order by all;
|
||||
----
|
||||
1 2
|
||||
1 25
|
||||
2 4
|
||||
3 8
|
||||
|
||||
query II
|
||||
select * from t1 semi join t2 on (t1.a < t2.b and t1.b < t2.b) or (t1.a < t2.b and t1.b = 4) order by all;
|
||||
----
|
||||
1 2
|
||||
2 4
|
||||
|
||||
|
||||
query II
|
||||
select * from t1 semi join t2 on (t1.a < t2.b or t1.b < t2.b) and (t1.a = 1 or t1.b = 4) order by all;
|
||||
----
|
||||
1 2
|
||||
1 25
|
||||
2 4
|
||||
|
||||
|
||||
statement ok
|
||||
CREATE TABLE flattened ("start" varchar, "end" varchar);
|
||||
|
||||
statement ok
|
||||
insert into flattened values ('2023-03-15T00:00:00Z', '2023-03-20T00:00:00Z');
|
||||
|
||||
statement ok
|
||||
create table input_table as select * from VALUES
|
||||
('1', '2023-03-14T00:00:00Z', 2),
|
||||
('2', '2023-03-15T00:00:00Z', 4),
|
||||
('3', '2023-03-16T00:00:00Z', 7),
|
||||
('4', '2023-03-17T00:00:00Z', 3),
|
||||
('5', '2023-03-18T00:00:00Z', 2),
|
||||
('6', '2023-03-19T23:59:59Z', 4),
|
||||
('7', '2023-03-20T00:00:00Z', 7),
|
||||
('8', '2023-03-21T00:00:00Z', 3) t(user_id, timestamp, value);
|
||||
|
||||
|
||||
query III
|
||||
SELECT * FROM input_table
|
||||
ANTI JOIN flattened
|
||||
ON input_table."timestamp" >= flattened.start AND input_table."timestamp" < flattened.end;
|
||||
----
|
||||
1 2023-03-14T00:00:00Z 2
|
||||
7 2023-03-20T00:00:00Z 7
|
||||
8 2023-03-21T00:00:00Z 3
|
||||
149
external/duckdb/test/sql/join/semianti/right_anti.test
vendored
Normal file
149
external/duckdb/test/sql/join/semianti/right_anti.test
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
# name: test/sql/join/semianti/right_anti.test
|
||||
# description: Test positional joins
|
||||
# group: [semianti]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE left_table (a INTEGER, b INTEGER, c INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES (42, 1, 1), (43, 1, 1), (42, 1, 1), (41, 1, 1), (41, 2, 2), (41, 7, 7);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE right_table (a INTEGER, b INTEGER);
|
||||
|
||||
# insert 2x values into right table. This means it will be forced to be the probe side
|
||||
statement ok
|
||||
INSERT INTO right_table select 41, range as b from range(375);
|
||||
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table ANTI JOIN right_table ON left_table.a = right_table.a;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
# still flips with filter
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table ANTI JOIN right_table ON left_table.a = right_table.a WHERE a > 5;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
# still flips with equality condition on tuples
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table ANTI JOIN right_table ON ([left_table.a, left_table.b] = [right_table.a, right_table.b]);
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
# right table can be a subquery, but using equality we still flip
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table ANTI JOIN (SELECT a as foo from right_table where b > 5) buzz ON left_table.a = buzz.foo
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES (43, 1, 5), (43, 1, 5), (43, 1, 5), (43, 1, 5);
|
||||
|
||||
query I
|
||||
CREATE TABLE other (a INTEGER, b INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO other VALUES (42, 1), (43, 1);
|
||||
|
||||
# Still flip on intermediate table that is joined
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table
|
||||
ANTI JOIN (select right_table.a FROM right_table JOIN other ON (other.a = right_table.a)) joined_right_table
|
||||
ON left_table.a = joined_right_table.a;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
|
||||
statement ok
|
||||
DELETE FROM left_table where c=5;
|
||||
|
||||
# USING COLUMNS also works,
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table ANTI JOIN right_table USING (a);
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
# natural anti join works
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table NATURAL ANTI JOIN right_table;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table
|
||||
NATURAL ANTI JOIN (select right_table.a FROM right_table JOIN other ON (other.a = right_table.a)) joined_right_table;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
# right_table.a and left_table.a have the value 42
|
||||
# only left_table.a has the value 43
|
||||
# test flip on inequalities as well
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table ANTI JOIN right_table ON (left_table.a <> right_table.a) ORDER BY a, c;
|
||||
----
|
||||
analyzed_plan <!REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
|
||||
# range joins do *not* flip
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table ANTI JOIN right_table ON (left_table.a > right_table.a);
|
||||
----
|
||||
analyzed_plan <!REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
|
||||
# complex condition resulting in an any join DOES *NOT* flip
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table ANTI JOIN right_table ON (left_table.a + right_table.a = 85 OR left_table.a + right_table.b = 84) order by left_table.a, left_table.c;
|
||||
----
|
||||
analyzed_plan <!REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES (1, 42), (1, 42);
|
||||
|
||||
# Insert more values so that the scan side in the cross product is the right hand side
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES (42, 1, 5), (42, 1, 5), (42, 1, 5), (2000, 20000, 200000);
|
||||
|
||||
# complex condition resulting in an any join does *NOT* flip
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table ANTI JOIN right_table ON (left_table.a + right_table.a = 85 OR left_table.a + right_table.b = 84) order by left_table.a, left_table.c;
|
||||
----
|
||||
analyzed_plan <!REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
# correlated subqueries can flip
|
||||
query II
|
||||
explain analyze SELECT a as outer_a, (SELECT MAX(right_table.b) FROM right_table where right_table.a != outer_a) right_table_b FROM left_table ANTI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES (1, 20);
|
||||
|
||||
# correlated subqueries
|
||||
query II
|
||||
explain analyze SELECT a as outer_a, (SELECT MAX(b) FROM right_table where right_table.a != outer_a) right_table_b FROM left_table ANTI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
statement ok
|
||||
SET scalar_subquery_error_on_multiple_rows=false
|
||||
|
||||
query II
|
||||
explain analyze SELECT a as outer_a, (SELECT right_table.b FROM right_table where right_table.a != outer_a) right_table_b FROM left_table ANTI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES (1, 20);
|
||||
|
||||
# correlated subqueries
|
||||
query II
|
||||
explain analyze SELECT a as outer_a, (SELECT b FROM right_table where right_table.a != outer_a) right_table_b FROM left_table ANTI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_ANTI.*
|
||||
|
||||
|
||||
148
external/duckdb/test/sql/join/semianti/right_semi.test
vendored
Normal file
148
external/duckdb/test/sql/join/semianti/right_semi.test
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
# name: test/sql/join/semianti/right_semi.test
|
||||
# description: Test positional joins
|
||||
# group: [semianti]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE left_table (a INTEGER, b INTEGER, c INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES (41, 1, 1), (42, 1, 1), (42, 1, 1), (43, 1, 1), (45, 2, 2), (46, 7, 7);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE right_table (a INTEGER, b INTEGER);
|
||||
|
||||
# insert 2x values into right table. This means it will be forced to be the probe side
|
||||
statement ok
|
||||
INSERT INTO right_table select 41, range as b from range(375);
|
||||
|
||||
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table SEMI JOIN right_table ON left_table.a = right_table.a;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
# still flips with filter
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table SEMI JOIN right_table ON left_table.a = right_table.a WHERE a > 5;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
# still flips with equality condition on tuples
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table SEMI JOIN right_table ON ([left_table.a, left_table.b] = [right_table.a, right_table.b]);
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
# right table can be a subquery, but using equality we still flip
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table SEMI JOIN (SELECT a as foo from right_table where b > 1) buzz ON left_table.a = buzz.foo
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES (43, 1, 5), (43, 1, 5), (43, 1, 5), (43, 1, 5);
|
||||
|
||||
query I
|
||||
CREATE TABLE other (a INTEGER, b INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO other VALUES (42, 1), (43, 1);
|
||||
|
||||
# Still flip on intermediate table that is joined
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table
|
||||
SEMI JOIN (select right_table.a FROM right_table JOIN other ON (other.a = right_table.a)) joined_right_table
|
||||
ON left_table.a = joined_right_table.a;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
statement ok
|
||||
DELETE FROM left_table where c=5;
|
||||
|
||||
# USING COLUMNS also works,
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table SEMI JOIN right_table USING (a);
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
# natural anti join works
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table NATURAL SEMI JOIN right_table;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table
|
||||
NATURAL SEMI JOIN (select right_table.a FROM right_table JOIN other ON (other.a = right_table.a)) joined_right_table;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
# right_table.a and left_table.a have the value 42
|
||||
# only left_table.a has the value 43
|
||||
# test flip on inequalities as well
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table SEMI JOIN right_table ON (left_table.a <> right_table.a) ORDER BY a, c;
|
||||
----
|
||||
analyzed_plan <!REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
|
||||
# range joins do *not* flip
|
||||
query II
|
||||
EXPLAIN ANALYZE SELECT * FROM left_table SEMI JOIN right_table ON (left_table.a > right_table.a);
|
||||
----
|
||||
analyzed_plan <!REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
|
||||
# complex condition resulting in an any join DOES *NOT* flip
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table SEMI JOIN right_table ON (left_table.a + right_table.a = 85 OR left_table.a + right_table.b = 84) order by left_table.a, left_table.c;
|
||||
----
|
||||
analyzed_plan <!REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES (1, 42), (1, 42);
|
||||
|
||||
# Insert more values so that the scan side in the cross product is the right hand side
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES (42, 1, 5), (42, 1, 5), (42, 1, 5), (2000, 20000, 200000);
|
||||
|
||||
# complex condition resulting in an any join does *NOT* flip
|
||||
query II
|
||||
explain analyze SELECT * FROM left_table SEMI JOIN right_table ON (left_table.a + right_table.a = 85 OR left_table.a + right_table.b = 84) order by left_table.a, left_table.c;
|
||||
----
|
||||
analyzed_plan <!REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
# correlated subqueries can flip
|
||||
query II
|
||||
explain analyze SELECT a as outer_a, (SELECT MAX(right_table.b) FROM right_table where right_table.a != outer_a) right_table_b FROM left_table SEMI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES (1, 20);
|
||||
|
||||
# correlated subqueries
|
||||
query II
|
||||
explain analyze SELECT a as outer_a, (SELECT MAX(b) FROM right_table where right_table.a != outer_a) right_table_b FROM left_table SEMI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
statement ok
|
||||
SET scalar_subquery_error_on_multiple_rows=false
|
||||
|
||||
query II
|
||||
explain analyze SELECT a as outer_a, (SELECT right_table.b FROM right_table where right_table.a != outer_a) right_table_b FROM left_table SEMI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES (1, 20);
|
||||
|
||||
# correlated subqueries
|
||||
query II
|
||||
explain analyze SELECT a as outer_a, (SELECT b FROM right_table where right_table.a != outer_a) right_table_b FROM left_table SEMI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
analyzed_plan <REGEX>:.*RIGHT_SEMI.*
|
||||
|
||||
169
external/duckdb/test/sql/join/semianti/semijoin.test
vendored
Normal file
169
external/duckdb/test/sql/join/semianti/semijoin.test
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
# name: test/sql/join/semianti/semijoin.test
|
||||
# description: Test semi joins
|
||||
# group: [semianti]
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification
|
||||
|
||||
statement ok
|
||||
CREATE TABLE left_table (a INTEGER, b INTEGER, c INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES(42, 1, 1), (43, 1, 1);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE right_table (a INTEGER, b INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES(42, 1);
|
||||
|
||||
# * expression expands all of the left table
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN right_table ON left_table.a = right_table.a;
|
||||
----
|
||||
42 1 1
|
||||
|
||||
# can filter on columns in left table
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN right_table ON left_table.a = right_table.a WHERE a > 5;
|
||||
----
|
||||
42 1 1
|
||||
|
||||
# can have list type expressions in the condition
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN right_table ON ([left_table.a, left_table.b] = [right_table.a, right_table.b]);
|
||||
----
|
||||
42 1 1
|
||||
|
||||
# right table can be a subquery
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN (SELECT a as foo from right_table where b = 1) buzz ON left_table.a = buzz.foo
|
||||
----
|
||||
42 1 1
|
||||
|
||||
# Should throw error when filtering on column in right table
|
||||
statement error
|
||||
SELECT * FROM left_table SEMI JOIN right_table ON left_table.a = right_table.a WHERE right_table.a < 43;
|
||||
----
|
||||
Binder Error
|
||||
|
||||
# left results are not deduplicated
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES (42, 1, 5), (42, 1, 5), (42, 1, 5), (42, 1, 5);
|
||||
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN right_table ON (left_table.a = right_table.a);
|
||||
----
|
||||
42 1 1
|
||||
42 1 5
|
||||
42 1 5
|
||||
42 1 5
|
||||
42 1 5
|
||||
|
||||
query I
|
||||
CREATE TABLE other (a INTEGER, b INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO other VALUES (42, 1), (43, 1);
|
||||
|
||||
# a table that is the result of a join can also be semi joined on
|
||||
query III
|
||||
SELECT * FROM left_table
|
||||
SEMI JOIN (select right_table.a FROM right_table JOIN other ON (other.a = right_table.a)) joined_right_table
|
||||
ON left_table.a = joined_right_table.a;
|
||||
----
|
||||
42 1 1
|
||||
42 1 5
|
||||
42 1 5
|
||||
42 1 5
|
||||
42 1 5
|
||||
|
||||
statement ok
|
||||
DELETE FROM left_table where c=5;
|
||||
|
||||
# USING COLUMNS also works
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN right_table USING (a);
|
||||
----
|
||||
42 1 1
|
||||
|
||||
# natural semi join also works
|
||||
query III
|
||||
SELECT * FROM left_table NATURAL SEMI JOIN right_table;
|
||||
----
|
||||
42 1 1
|
||||
|
||||
# also with subqueries
|
||||
query III
|
||||
SELECT * FROM left_table
|
||||
NATURAL SEMI JOIN (select right_table.a FROM right_table JOIN other ON (other.a = right_table.a)) joined_right_table;
|
||||
----
|
||||
42 1 1
|
||||
|
||||
# test correlated queries
|
||||
|
||||
# right_table.a and left_table.a have the value 42
|
||||
# only left_table.a has the value 43
|
||||
# test inequality joins
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN right_table ON (left_table.a <> right_table.a) ORDER BY a, c;
|
||||
----
|
||||
43 1 1
|
||||
|
||||
# range joins
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN right_table ON (left_table.a > right_table.a);
|
||||
----
|
||||
43 1 1
|
||||
|
||||
# complex condition resulting in an any join
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN right_table ON (left_table.a + right_table.a = 85 OR left_table.a + right_table.b = 84) order by left_table.a, left_table.c;
|
||||
----
|
||||
43 1 1
|
||||
|
||||
statement ok
|
||||
INSERT INTO right_table VALUES (1, 42), (1, 42);
|
||||
|
||||
# Insert more values so that the scan side in the cross product is the right hand side
|
||||
statement ok
|
||||
INSERT INTO left_table VALUES (42, 1, 5), (42, 1, 5), (42, 1, 5), (2000, 20000, 200000);
|
||||
|
||||
# complex condition resulting in an any join
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN right_table ON (left_table.a + right_table.a = 85 OR left_table.a + right_table.b = 84) order by left_table.a, left_table.c;
|
||||
----
|
||||
42 1 1
|
||||
42 1 5
|
||||
42 1 5
|
||||
42 1 5
|
||||
43 1 1
|
||||
|
||||
# complex condition resulting in an any join
|
||||
query III
|
||||
SELECT * FROM left_table SEMI JOIN right_table ON ((left_table.a = NULL AND right_table.a = NULL) OR left_table.a = right_table.a) order by left_table.a, left_table.c;
|
||||
----
|
||||
42 1 1
|
||||
42 1 5
|
||||
42 1 5
|
||||
42 1 5
|
||||
|
||||
# correlated subqueries
|
||||
query II
|
||||
SELECT a as outer_a, (SELECT ANY_VALUE(b) FROM right_table where right_table.a != outer_a) right_table_b FROM left_table SEMI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
42 42
|
||||
42 42
|
||||
42 42
|
||||
42 42
|
||||
|
||||
statement ok
|
||||
SET scalar_subquery_error_on_multiple_rows=false
|
||||
|
||||
query II
|
||||
SELECT a as outer_a, (SELECT b FROM right_table where right_table.a != outer_a) right_table_b FROM left_table SEMI JOIN right_table ON (left_table.a = right_table.a) Order by outer_a, right_table_b;
|
||||
----
|
||||
42 42
|
||||
42 42
|
||||
42 42
|
||||
42 42
|
||||
55
external/duckdb/test/sql/join/semianti/test_simple_anti_join.test
vendored
Normal file
55
external/duckdb/test/sql/join/semianti/test_simple_anti_join.test
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
# name: test/sql/join/semianti/test_simple_anti_join.test
|
||||
# description: Test semi joins
|
||||
# group: [semianti]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE t0(c0 VARCHAR);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE t1(c1 VARCHAR);
|
||||
|
||||
statement ok
|
||||
INSERT INTO t1(c1) VALUES (NULL);
|
||||
|
||||
statement ok
|
||||
INSERT INTO t0(c0) VALUES (1);
|
||||
|
||||
query I
|
||||
select * FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t0 WHERE null);
|
||||
----
|
||||
NULL
|
||||
|
||||
query I
|
||||
select * FROM t1 WHERE EXISTS (SELECT 1 FROM t0 WHERE ((t0.c0) != (t1.c1)));
|
||||
----
|
||||
|
||||
query I
|
||||
select * FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t0 WHERE ((t0.c0)!=(t1.c1))); -- wrong, no row
|
||||
----
|
||||
NULL
|
||||
|
||||
statement ok
|
||||
create table lineitem (l_orderkey int, l_suppkey int, l_partkey int);
|
||||
|
||||
statement ok
|
||||
insert into lineitem values (1,1,42),(1,2,43),(3,3,44),(4,5,45),(5,5,46),(6,5,47);
|
||||
|
||||
query III rowsort
|
||||
select * from lineitem l1 where exists (
|
||||
select * from lineitem l2
|
||||
where
|
||||
l2.l_orderkey = l1.l_orderkey
|
||||
and l2.l_suppkey <> l1.l_suppkey
|
||||
);
|
||||
----
|
||||
1 1 42
|
||||
1 2 43
|
||||
|
||||
|
||||
query II
|
||||
select c0, EXISTS (select * from t1 where c1 != c0) from t0;
|
||||
----
|
||||
1 false
|
||||
Reference in New Issue
Block a user