skip under race

statement ok
CREATE TABLE abc (a INT, b INT, c INT, PRIMARY KEY (a, c));
INSERT INTO abc VALUES (1, 1, 2), (2, 1, 1), (2, NULL, 2)

statement ok
CREATE TABLE def (d INT, e INT, f INT, PRIMARY KEY (f, e));
INSERT INTO def VALUES (1, 1, 2), (2, 1, 1), (NULL, 2, 1)

statement ok
CREATE TABLE def_e_desc (d INT, e INT, f INT, PRIMARY KEY (f, e DESC));
INSERT INTO def_e_desc VALUES (1, 1, 2), (2, 1, 1), (NULL, 2, 1)

statement ok
CREATE TABLE def_e_decimal (d INT, e DECIMAL, f INT, PRIMARY KEY (f, e));
INSERT INTO def_e_decimal VALUES (1, 1, 2), (2, 1, 1), (NULL, 2, 1)

statement ok
CREATE TABLE float_xy (x FLOAT, y INT, INDEX asc_idx (x, y), INDEX desc_idx (x DESC, y));
INSERT INTO float_xy VALUES (1, 1), (2, 1), (NULL, 2), ('NaN'::FLOAT, 3), ('+Inf'::FLOAT, 4), ('-Inf'::FLOAT, 5);

statement ok
CREATE TABLE string_xy (x TEXT, y INT, INDEX asc_idx (x, y), INDEX desc_idx (x DESC, y));
INSERT INTO string_xy VALUES ('abc', 1), ('abcd', 2), ('bcd', 3), ('xyz', 4), ('', 5), (NULL, 6);

statement ok
CREATE TABLE time_xy (x TIME, y TIMESTAMP, INDEX x_idx (x), INDEX y_idx (y));
INSERT INTO time_xy
VALUES
('00:00:00'::TIME, '2016-06-22 19:10:25'::TIMESTAMP),
('24:00:00'::TIME, '2042-01-01 00:00:00'::TIMESTAMP),
('infinity'::TIME, '1970-01-01 00:00:00'::TIMESTAMP),
('00:52:12.19515'::TIME, NULL),
(NULL, 'infinity'::TIMESTAMP),
('-infinity'::TIME, '-infinity'::TIMESTAMP);

statement ok
CREATE TABLE gh (g INT, h INT, INDEX g_idx (g));
INSERT INTO gh VALUES (NULL, 1)

# Set up the statistics as if the first table is much smaller than the second.
# This will make lookup join into the second table be the best plan.
statement ok
ALTER TABLE abc INJECT STATISTICS '[
  {
    "columns": ["a"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 100,
    "distinct_count": 100
  }
]'

statement ok
ALTER TABLE def INJECT STATISTICS '[
  {
    "columns": ["f"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 10000
  }
]'

statement ok
ALTER TABLE def_e_desc INJECT STATISTICS '[
  {
    "columns": ["f"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 10000
  }
]'

statement ok
ALTER TABLE def_e_decimal INJECT STATISTICS '[
  {
    "columns": ["f"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 10000
  }
]'

statement ok
ALTER TABLE gh INJECT STATISTICS '[
  {
    "columns": ["g"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 10000
  }
]'

query IIIIII rowsort
SELECT * FROM abc JOIN def ON f = b
----
1  1  2  2     1  1
2  1  1  2     1  1
1  1  2  NULL  2  1
2  1  1  NULL  2  1

query IIIIII rowsort
SELECT * FROM abc JOIN def ON f = b AND e = c
----
1  1  2  NULL  2  1
2  1  1  2     1  1

query IIIIII rowsort
SELECT * FROM abc JOIN def ON f = b WHERE a > 1 AND e > 1
----
2  1  1  NULL  2  1

query IIIIII rowsort
SELECT * FROM abc JOIN def ON f = b AND a > 1 AND e > 1
----
2  1  1  NULL  2  1

query IIIIII
SELECT * FROM abc JOIN def_e_desc ON f = b AND a > 1 AND e > 1
----
2  1  1  NULL  2  1

query IIIIRI
SELECT * FROM abc JOIN def_e_decimal ON f = b AND a > 1 AND e > 1
----
2  1  1  NULL  2  1

# Filter on 'e' is a contradiction.
query IIIIII
SELECT * FROM abc JOIN def ON f = b AND a > 1 AND e < -9223372036854775808
----

# Filter on 'e' is a contradiction.
query IIIIII
SELECT * FROM abc JOIN def ON f = b AND a > 1 AND e > 9223372036854775807
----

# Filter on 'e' is a contradiction.
query IIIIII
SELECT * FROM abc JOIN def_e_desc ON f = b AND a > 1 AND e < -9223372036854775808
----

# Filter on 'e' is a contradiction.
query IIIIII
SELECT * FROM abc JOIN def_e_desc ON f = b AND a > 1 AND e > 9223372036854775807
----

# Filter right side of a lookup join with a restriction on an indexed column.
query IIIIII rowsort
SELECT * FROM abc JOIN def ON f = a WHERE f > 1
----
2  1  1  1  1  2
2  NULL  2  1  1  2

# Test lookup join with restriction relating the left and right side.
query IIIIII rowsort
SELECT * FROM abc JOIN def ON f = b WHERE a >= e
----
1  1  2  2  1  1
2  1  1  2  1  1
2  1  1  NULL  2  1

query IIIIII rowsort
SELECT * FROM abc JOIN def_e_desc ON f = b WHERE a >= e
----
1  1  2  2  1  1
2  1  1  2  1  1
2  1  1  NULL  2  1

query IIIIRI rowsort
SELECT * FROM abc JOIN def_e_decimal ON f = b WHERE a >= e
----
1  1  2  2  1  1
2  1  1  2  1  1
2  1  1  NULL  2  1

# Test lookup join with restriction relating the left and right side.
query IIIIII rowsort
SELECT * FROM abc JOIN def ON f = b AND a >= e
----
1  1  2  2  1  1
2  1  1  2  1  1
2  1  1  NULL  2  1

query IIIIII rowsort
SELECT * FROM abc JOIN def_e_desc ON f = b AND a >= e
----
1  1  2  2  1  1
2  1  1  2  1  1
2  1  1  NULL  2  1

query IIIIRI rowsort
SELECT * FROM abc JOIN def_e_decimal ON f = b AND a >= e
----
1  1  2  2  1  1
2  1  1  2  1  1
2  1  1  NULL  2  1

# Test lookup join with selecting a subset of the columns.
query III rowsort
SELECT a, b, e FROM abc JOIN def ON f = b WHERE a >= e
----
1  1  1
2  1  1
2  1  2

# Test lookup join on NULL column. (https://github.com/cockroachdb/cockroach/issues/27032)
query I
SELECT h FROM abc JOIN gh ON b = g
----

statement ok
CREATE TABLE data (a INT, b INT, c INT, d INT, PRIMARY KEY (a, b, c, d))

# Generate all combinations of values 1 to 10.
statement ok
INSERT INTO data SELECT a, b, c, d FROM
   generate_series(1, 10) AS a(a),
   generate_series(1, 10) AS b(b),
   generate_series(1, 10) AS c(c),
   generate_series(1, 10) AS d(d)

statement ok
ALTER TABLE data INJECT STATISTICS '[
  {
    "columns": ["a"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 100000,
    "distinct_count": 100000
  }
]'

# Ensure lookup join performs properly on input that has more than 100 rows.
query I
SELECT count(*)
FROM (SELECT * FROM data WHERE c = 1) AS l
NATURAL JOIN (SELECT * FROM data WHERE c > 0) AS r
----
1000

statement ok
CREATE TABLE foo (a int, b int); INSERT INTO foo VALUES (0, 1), (0, 2), (1, 1)

statement ok
CREATE TABLE bar (a int PRIMARY KEY, c int); INSERT INTO bar VALUES (0, 1), (1, 2), (2, 1)

query III rowsort
SELECT * FROM foo NATURAL JOIN bar
----
0  1  1
0  2  1
1  1  2

statement ok
CREATE TABLE books (title STRING, edition INT, shelf INT, PRIMARY KEY (title, edition));
INSERT INTO books VALUES
  ('SICP', 1, 2),
  ('Intro to Algo', 1, 1),
  ('Intro to Algo', 2, 1),
  ('Intro to Algo', 3, 2),
  ('Art of Computer Programming', 1, 2),
  ('Art of Computer Programming', 2, 2)

statement ok
CREATE TABLE books2 (title STRING, edition INT, shelf INT, PRIMARY KEY (title, edition));
INSERT INTO books2 VALUES
  ('SICP', 1, 2),
  ('Intro to Algo', 1, 1),
  ('Intro to Algo', 2, 1),
  ('Intro to Algo', 3, 2),
  ('Art of Computer Programming', 1, 2),
  ('Art of Computer Programming', 2, 2)

statement ok
ALTER TABLE books INJECT STATISTICS '[
  {
    "columns": ["title"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 100,
    "distinct_count": 100
  }
]'

statement ok
ALTER TABLE books2 INJECT STATISTICS '[
  {
    "columns": ["title"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 1000
  }
]'

statement ok
CREATE TABLE authors (name STRING, book STRING);
INSERT INTO authors VALUES
  ('Hal Abelson', 'SICP'),
  ('Geral Jay Sussman', 'SICP'),
  ('Thomas H Cormen', 'Intro to Algo'),
  ('Charles E Leiserson', 'Intro to Algo'),
  ('Ronald Rivest', 'Intro to Algo'),
  ('Clifford Stein', 'Intro to Algo'),
  ('Donald Knuth', 'Art of Computer Programming')

statement ok
ALTER TABLE authors INJECT STATISTICS '[
  {
    "columns": ["name"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 100,
    "distinct_count": 100
  }
]'

# Filter on a column that is not returned or in the equality columns.
query T rowsort
SELECT DISTINCT b1.title FROM books as b1 JOIN books2 as b2 ON b1.title = b2.title WHERE b1.shelf <> b2.shelf
----
Intro to Algo

query T rowsort
SELECT DISTINCT authors.name FROM books AS b1, books2 as b2, authors WHERE b1.title = b2.title AND authors.book = b1.title AND b1.shelf <> b2.shelf
----
Thomas H Cormen
Charles E Leiserson
Ronald Rivest
Clifford Stein

# Ensure lookup join preserves ordering from the left side.
query T
SELECT a.name FROM authors AS a JOIN books2 AS b2 ON a.book = b2.title ORDER BY a.name
----
Charles E Leiserson
Charles E Leiserson
Charles E Leiserson
Clifford Stein
Clifford Stein
Clifford Stein
Donald Knuth
Donald Knuth
Geral Jay Sussman
Hal Abelson
Ronald Rivest
Ronald Rivest
Ronald Rivest
Thomas H Cormen
Thomas H Cormen
Thomas H Cormen

####################################
#  LOOKUP JOIN ON SECONDARY INDEX  #
####################################

statement ok
CREATE TABLE small (a INT PRIMARY KEY, b INT, c INT, d INT)

statement ok
CREATE TABLE large (a INT, b INT, c INT, d INT, PRIMARY KEY (a, b), INDEX bc (b) STORING (c))

# Generate 10 rows for both tables.
statement ok
INSERT INTO small SELECT x, 2*x, 3*x, 4*x FROM
  generate_series(1, 10) AS a(x)

statement ok
INSERT INTO large SELECT x, 2*x, 3*x, 4*x FROM
  generate_series(1, 10) AS a(x)

statement ok
ALTER TABLE small INJECT STATISTICS '[
  {
    "columns": ["a"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 100,
    "distinct_count": 100
  }
]'

statement ok
ALTER TABLE large INJECT STATISTICS '[
  {
    "columns": ["a"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 10000
  }
]'

# Lookup join on covering secondary index
query II rowsort
SELECT small.a, large.c FROM small JOIN large ON small.a = large.b
----
2   3
4   6
6   9
8   12
10  15

# Lookup join on non-covering secondary index
query II rowsort
SELECT small.a, large.d FROM small JOIN large ON small.a = large.b
----
2   4
4   8
6   12
8   16
10  20

############################
#  LEFT OUTER LOOKUP JOIN  #
############################

# Left join against primary index
query II rowsort
SELECT small.b, large.a FROM small LEFT JOIN large ON small.b = large.a
----
2 2
4 4
6 6
8 8
10 10
12 NULL
14 NULL
16 NULL
18 NULL
20 NULL

# Left join should preserve input order.
query II
SELECT t1.a, t2.b FROM small t1 LEFT JOIN large t2 ON t1.a = t2.a AND t2.b % 6 = 0 ORDER BY t1.a
----
1   NULL
2   NULL
3   6
4   NULL
5   NULL
6   12
7   NULL
8   NULL
9   18
10  NULL

# Left join against covering secondary index
query II rowsort
SELECT small.c, large.c FROM small LEFT JOIN large ON small.c = large.b
----
3   NULL
6   9
9   NULL
12  18
15  NULL
18  27
21  NULL
24  NULL
27  NULL
30  NULL

# Left join against non-covering secondary index
query II rowsort
SELECT small.c, large.d FROM small LEFT JOIN large ON small.c = large.b
----
3   NULL
6   12
9   NULL
12  24
15  NULL
18  36
21  NULL
24  NULL
27  NULL
30  NULL

# Left join with ON filter on covering index
query II rowsort
SELECT small.c, large.c FROM small LEFT JOIN large ON small.c = large.b AND large.c < 20
----
3   NULL
6   9
9   NULL
12  18
15  NULL
18  NULL
21  NULL
24  NULL
27  NULL
30  NULL

## Left join with ON filter on non-covering index. Will execute as paired-joins.
query II rowsort
SELECT small.c, large.d FROM small LEFT JOIN large ON small.c = large.b AND large.d < 30
----
3   NULL
6   12
9   NULL
12  24
15  NULL
18  NULL
21  NULL
24  NULL
27  NULL
30  NULL

## Left semi join with ON filter on non-covering index. Will execute as paired-joins.
query I rowsort
SELECT small.c FROM small WHERE EXISTS(SELECT 1 FROM large WHERE small.c = large.b AND large.d < 30)
----
6
12

## Left anti join with ON filter on non-covering index. Will execute as paired-joins.
query I rowsort
SELECT small.c FROM small WHERE NOT EXISTS(SELECT 1 FROM large WHERE small.c = large.b AND large.d < 30)
----
3
9
15
18
21
24
27
30

###########################################################
#  LOOKUP JOINS ON IMPLICIT INDEX KEY COLUMNS             #
#  https://github.com/cockroachdb/cockroach/issues/31777  #
###########################################################
statement ok
CREATE TABLE t (a INT, b INT, c INT, d INT, e INT)

statement ok
CREATE TABLE u (a INT, b INT, c INT, d INT, e INT, PRIMARY KEY (a DESC, b, c))

statement ok
INSERT INTO t VALUES
  (1, 2, 3, 4, 5)

statement ok
INSERT INTO u VALUES
  (1, 2, 3, 4, 5),
  (2, 3, 4, 5, 6),
  (3, 4, 5, 6, 7)

# Test index with all primary key columns implicit.
statement ok
CREATE INDEX idx ON u (d)

query I
SELECT u.a FROM t JOIN u ON t.d = u.d AND t.a = u.a WHERE t.e = 5
----
1

# Test unique version of same index. (Lookup join should not use column a.)
statement ok
DROP INDEX u@idx

statement ok
CREATE UNIQUE INDEX idx ON u (d)

query I
SELECT u.a FROM t JOIN u ON t.d = u.d AND t.a = u.a WHERE t.e = 5
----
1

# Test index with first primary key column explicit and the rest implicit.
statement ok
DROP INDEX u@idx CASCADE

statement ok
CREATE INDEX idx ON u (d, a)

query I
SELECT u.a FROM t JOIN u ON t.d = u.d AND t.a = u.a AND t.b = u.b WHERE t.e = 5
----
1

# Test index with middle primary key column explicit and the rest implicit.
statement ok
DROP INDEX u@idx

statement ok
CREATE INDEX idx ON u (d, b)

query I
SELECT u.a FROM t JOIN u ON t.d = u.d AND t.a = u.a AND t.b = u.b WHERE t.e = 5
----
1

# Test index with last primary key column explicit and the rest implicit.
statement ok
DROP INDEX u@idx

statement ok
CREATE INDEX idx ON u (d, c)

query I
SELECT u.a FROM t JOIN u ON t.d = u.d AND t.a = u.a AND t.d = u.d WHERE t.e = 5
----
1

query IIIIII colnames,partialsort(4)
SELECT * FROM def JOIN abc ON a=f ORDER BY a
----
d     e  f  a  b     c
2     1  1  1  1     2
NULL  2  1  1  1     2
1     1  2  2  NULL  2
1     1  2  2  1     1

# Test lookup semi and anti join.
query III rowsort
SELECT * from abc WHERE EXISTS (SELECT * FROM def WHERE a=f)
----
1  1     2
2  1     1
2  NULL  2

query III rowsort
SELECT * from abc WHERE NOT EXISTS (SELECT * FROM def WHERE a=f)
----

query III rowsort
SELECT * from abc WHERE EXISTS (SELECT * FROM def WHERE a=f AND c=e)
----
1  1  2
2  1  1

query III rowsort
SELECT * from abc WHERE NOT EXISTS (SELECT * FROM def WHERE a=f AND c=e)
----
2  NULL  2

query III rowsort
SELECT * from abc WHERE EXISTS (SELECT * FROM def WHERE a=f AND d+b>1)
----
1  1  2
2  1  1

query III rowsort
SELECT * from abc WHERE NOT EXISTS (SELECT * FROM def WHERE a=f AND d+b>1)
----
2  NULL  2

query II
SELECT a,b from small WHERE EXISTS (SELECT a FROM data WHERE small.a=data.a) ORDER BY a
----
1   2
2   4
3   6
4   8
5   10
6   12
7   14
8   16
9   18
10  20

query II
SELECT a,b from small WHERE a+b<20 AND EXISTS (SELECT a FROM data WHERE small.a=data.a AND small.b+data.c>15) ORDER BY a
----
3  6
4  8
5  10
6  12

# Regression test for #50964.
statement ok
CREATE TABLE tab4 (
  pk INT8 PRIMARY KEY, col0 INT8, col1 FLOAT8, col2 STRING, col3 INT8, col4 FLOAT8, col5 STRING,
  UNIQUE (col3 DESC, col4 DESC)
)

query I
SELECT pk FROM tab4 WHERE col0 IN (SELECT col3 FROM tab4 WHERE col4 = 495.6) AND (col3 IS NULL)
----

###########################################################
#  LOOKUP JOINS WITH LOOKUP EXPRESSIONS                   #
#  https://github.com/cockroachdb/cockroach/issues/59615  #
###########################################################

# Regression test for #59615. Ensure that invalid lookup joins are not created
# for left and anti joins.
statement ok
CREATE TABLE t59615 (
  x INT NOT NULL CHECK (x in (1, 3)),
  y INT NOT NULL,
  z INT,
  PRIMARY KEY (x, y)
)

query IIII rowsort
SELECT * FROM (VALUES (1), (2)) AS u(y) LEFT JOIN t59615 t ON u.y = t.y
----
1  NULL  NULL  NULL
2  NULL  NULL  NULL

query I rowsort
SELECT * FROM (VALUES (1), (2)) AS u(y) WHERE NOT EXISTS (
  SELECT * FROM t59615 t WHERE u.y = t.y
)
----
1
2

# Regression test for #78681. Ensure that invalid lookup joins are not created
# for semi joins.
statement ok
CREATE TABLE t78681 (
  x INT NOT NULL CHECK (x in (1, 3)),
  y INT NOT NULL,
  PRIMARY KEY (x, y)
)

# Insert stats so that a lookup semi-join is selected.
statement ok
ALTER TABLE t78681 INJECT STATISTICS '[
  {
    "columns": ["x"],
    "created_at": "2018-05-01 1:00:00.00000+00:00",
    "row_count": 10000000,
    "distinct_count": 2
  }
]'

statement ok
INSERT INTO t78681 VALUES (1, 1), (3, 1)

query I rowsort
SELECT * FROM (VALUES (1), (2)) AS u(y) WHERE EXISTS (
  SELECT * FROM t78681 t WHERE u.y = t.y
)
----
1

statement ok
CREATE TABLE lookup_expr (
  r STRING NOT NULL CHECK (r IN ('east', 'west')),
  v INT NOT NULL,
  w INT,
  x INT,
  y INT NOT NULL CHECK (y IN (10, 20)),
  z INT NOT NULL CHECK (z = 5),
  PRIMARY KEY (r, v),
  INDEX (r, x, y, z, w)
)

statement ok
INSERT INTO lookup_expr VALUES
  ('east', 1, 1, 10, 10, 5),
  ('east', 2, NULL, 20, 10, 5),
  ('east', 3, 3, NULL, 10, 5),
  ('east', 4, 4, 40, 20, 5),
  ('east', 5, NULL, 50, 20, 5),
  ('west', 6, 1, 10, 20, 5),
  ('west', 7, NULL, NULL, 20, 5),
  ('west', 8, 2, 20, 20, 5),
  ('west', 9, 3, 30, 10, 5),
  ('west', 10, 4, 40, 10, 5)

query IITIIIII rowsort
SELECT * FROM (VALUES (1, 10), (2, 20), (3, NULL)) AS u(w, x) LEFT JOIN lookup_expr t
ON u.w = t.w AND u.x = t.x
----
1  10    east  1     1     10    10    5
1  10    west  6     1     10    20    5
2  20    west  8     2     20    20    5
3  NULL  NULL  NULL  NULL  NULL  NULL  NULL

query II rowsort
SELECT * FROM (VALUES (1, 10), (2, 20), (3, NULL)) AS u(w, x) WHERE NOT EXISTS (
  SELECT * FROM lookup_expr t WHERE u.w = t.w AND u.x = t.x
)
----
3  NULL

# Regression test for #79384. Do not generate unnecessary cross-joins on a
# lookup join's input when the lookup join uses a lookup expression.
statement ok
CREATE TABLE t79384a (
  k INT NOT NULL
)

statement ok
CREATE TABLE t79384b (
  a INT,
  b INT,
  c INT,
  INDEX (a, b, c)
)

statement ok
INSERT INTO t79384a VALUES (1)

statement ok
INSERT INTO t79384b VALUES (1, 1, 1)

# The joined tables have a single row each, so this query should never return
# more than one row.
query I
SELECT k FROM t79384a INNER LOOKUP JOIN t79384b ON k = a AND b IN (1, 2, 3) AND c > 0
----
1

# Regression test for #81968. Paired left joins should set all right columns
# for unmatched rows to NULL.
statement ok
CREATE TABLE items (
    id        INT NOT NULL PRIMARY KEY,
    chat_id   INT NOT NULL,
    author_id INT NOT NULL,
    INDEX chat_id_idx (chat_id)
);
CREATE TABLE views (
    chat_id INT NOT NULL,
    user_id INT NOT NULL,
    PRIMARY KEY (chat_id, user_id)
);
INSERT INTO views(chat_id, user_id) VALUES (1, 1);
INSERT INTO items(id, chat_id, author_id) VALUES
(1, 1, 1),
(2, 1, 1),
(3, 1, 1);

query I
SELECT (SELECT count(items.id)
        FROM items
        WHERE items.chat_id = views.chat_id
          AND items.author_id != views.user_id)
FROM views
WHERE chat_id = 1
  AND user_id = 1;
----
0

query IIIII
SELECT * FROM views LEFT LOOKUP JOIN items
ON items.chat_id = views.chat_id
AND items.author_id != views.user_id
WHERE views.chat_id = 1 and views.user_id = 1;
----
1  1  NULL  NULL  NULL

# Test that lookup joins can supply an ordering on input and lookup columns.
# Compare with the output of a hash join with the same ordering (which will
# have to sort its output).

statement ok
CREATE TABLE xyz (x INT, y INT, z INT, PRIMARY KEY(x, y DESC, z));

statement ok
CREATE TABLE uvw (u INT, v INT, w INT, PRIMARY KEY(u, v, w DESC));

statement ok
INSERT INTO xyz VALUES (1, 1, 1), (1, 1, 2), (1, 2, 3), (2, 1, 4), (2, 1, 5), (2, 1, 6), (3, 1, 7);

statement ok
INSERT INTO uvw VALUES (1, 1, 1), (1, 2, 2), (1, 2, 3), (2, 1, 4), (2, 1, 5), (2, 2, 6), (2, 2, 7);

query IIIIII colnames
SELECT * FROM xyz INNER LOOKUP JOIN uvw ON x = u ORDER BY x, y DESC, z, u, v, w DESC
----
x  y  z  u  v  w
1  2  3  1  1  1
1  2  3  1  2  3
1  2  3  1  2  2
1  1  1  1  1  1
1  1  1  1  2  3
1  1  1  1  2  2
1  1  2  1  1  1
1  1  2  1  2  3
1  1  2  1  2  2
2  1  4  2  1  5
2  1  4  2  1  4
2  1  4  2  2  7
2  1  4  2  2  6
2  1  5  2  1  5
2  1  5  2  1  4
2  1  5  2  2  7
2  1  5  2  2  6
2  1  6  2  1  5
2  1  6  2  1  4
2  1  6  2  2  7
2  1  6  2  2  6

query IIIIII colnames
SELECT * FROM xyz INNER HASH JOIN uvw ON x = u ORDER BY x, y DESC, z, u, v, w DESC
----
x  y  z  u  v  w
1  2  3  1  1  1
1  2  3  1  2  3
1  2  3  1  2  2
1  1  1  1  1  1
1  1  1  1  2  3
1  1  1  1  2  2
1  1  2  1  1  1
1  1  2  1  2  3
1  1  2  1  2  2
2  1  4  2  1  5
2  1  4  2  1  4
2  1  4  2  2  7
2  1  4  2  2  6
2  1  5  2  1  5
2  1  5  2  1  4
2  1  5  2  2  7
2  1  5  2  2  6
2  1  6  2  1  5
2  1  6  2  1  4
2  1  6  2  2  7
2  1  6  2  2  6

query IIIIII colnames
SELECT * FROM xyz INNER LOOKUP JOIN uvw ON x = u AND y = v ORDER BY u, x, v, y DESC, z, w DESC
----
x  y  z  u  v  w
1  1  1  1  1  1
1  1  2  1  1  1
1  2  3  1  2  3
1  2  3  1  2  2
2  1  4  2  1  5
2  1  4  2  1  4
2  1  5  2  1  5
2  1  5  2  1  4
2  1  6  2  1  5
2  1  6  2  1  4

query IIIIII colnames
SELECT * FROM xyz INNER HASH JOIN uvw ON x = u AND y = v ORDER BY u, x, v, y DESC, z, w DESC
----
x  y  z  u  v  w
1  1  1  1  1  1
1  1  2  1  1  1
1  2  3  1  2  3
1  2  3  1  2  2
2  1  4  2  1  5
2  1  4  2  1  4
2  1  5  2  1  5
2  1  5  2  1  4
2  1  6  2  1  5
2  1  6  2  1  4

# Test inequality lookup joins.
# Case with idxCol <= inputCol.
query IIIIII
SELECT a, b, c, d, e, f FROM abc INNER LOOKUP JOIN def ON f <= a ORDER BY a, b, c, d, e, f
----
1  1     2  NULL  2  1
1  1     2  2     1  1
2  NULL  2  NULL  2  1
2  NULL  2  1     1  2
2  NULL  2  2     1  1
2  1     1  NULL  2  1
2  1     1  1     1  2
2  1     1  2     1  1

# Case with idxCol >= inputCol (same output as last test).
query IIIIII
SELECT a, b, c, d, e, f FROM def INNER LOOKUP JOIN abc ON a >= f ORDER BY a, b, c, d, e, f
----
1  1     2  NULL  2  1
1  1     2  2     1  1
2  NULL  2  NULL  2  1
2  NULL  2  1     1  2
2  NULL  2  2     1  1
2  1     1  NULL  2  1
2  1     1  1     1  2
2  1     1  2     1  1

# Case with idxCol < inputCol.
query IIIIII
SELECT a, b, c, d, e, f FROM abc INNER LOOKUP JOIN def ON f < a ORDER BY a, b, c, d, e, f
----
2  NULL  2  NULL  2  1
2  NULL  2  2     1  1
2  1     1  NULL  2  1
2  1     1  2     1  1

# Case with idxCol > inputCol (same output as last test).
query IIIIII
SELECT a, b, c, d, e, f FROM def INNER LOOKUP JOIN abc ON a > f ORDER BY a, b, c, d, e, f
----
2  NULL  2  NULL  2  1
2  NULL  2  2     1  1
2  1     1  NULL  2  1
2  1     1  2     1  1

# Case where input column used as bound has null.
query IIIIII rowsort
SELECT * FROM def INNER LOOKUP JOIN abc ON a >= d
----
1  1  2  1  1     2
1  1  2  2  1     1
1  1  2  2  NULL  2
2  1  1  2  1     1
2  1  1  2  NULL  2

# Case where input column used as bound has null (idxCol > inputCol).
query IIIIII rowsort
SELECT * FROM def INNER LOOKUP JOIN abc ON a > d
----
1  1  2  2  1     1
1  1  2  2  NULL  2

# Case where input column used as bound has null (idxCol >= inputCol).
query IIIIII rowsort
SELECT * FROM def INNER LOOKUP JOIN abc ON a >= d
----
1  1  2  1  1     2
1  1  2  2  1     1
1  1  2  2  NULL  2
2  1  1  2  1     1
2  1  1  2  NULL  2

# Case where input column used as bound has null (idxCol < inputCol).
query IIIIII rowsort
SELECT * FROM def INNER LOOKUP JOIN abc ON a < d
----
2  1  1  1  1  2

# Case where input column used as bound has null (idxCol <= inputCol).
query IIIIII rowsort
SELECT * FROM def INNER LOOKUP JOIN abc ON a <= d
----
2  1  1  1  1     2
2  1  1  2  1     1
2  1  1  2  NULL  2
1  1  2  1  1     2

# Case with two inequalities.
query IIIIII
SELECT a, b, c, d, e, f FROM abc INNER LOOKUP JOIN def ON f < a AND f >= b ORDER BY a, b, c, d, e, f
----
2  1  1  NULL  2  1
2  1  1  2     1  1

# Case with two inequalities (same output as last test).
query IIIIII
SELECT a, b, c, d, e, f FROM def INNER LOOKUP JOIN abc ON f < a AND f >= b ORDER BY a, b, c, d, e, f
----
2  1  1  NULL  2  1
2  1  1  2     1  1

# Case with two inequalities, one is a constant.
query IIIIII rowsort
SELECT * FROM abc INNER LOOKUP JOIN def ON f < 2 AND f >= b
----
1  1  2  2     1  1
2  1  1  2     1  1
1  1  2  NULL  2  1
2  1  1  NULL  2  1

# Case with two inequalities, one is a constant.
query IIIIII rowsort
SELECT * FROM def INNER LOOKUP JOIN abc ON a < 2 AND a >= d
----
1  1  2  1  1  2

# Case with equality prefix.
query IIIIII rowsort
SELECT * FROM abc INNER LOOKUP JOIN def ON f = c AND e >= b
----
2  1  1  2     1  1
2  1  1  NULL  2  1
1  1  2  1     1  2

# Case with equality prefix.
query IIIIII
SELECT a, b, c, d, e, f FROM abc INNER LOOKUP JOIN def ON f = a AND e >= c ORDER BY a, b, c, d, e, f
----
1  1  2  NULL  2  1
2  1  1  1     1  2

# Case with equality prefix (same output as last test).
query IIIIII
SELECT a, b, c, d, e, f FROM def INNER LOOKUP JOIN abc ON f = a AND e >= c ORDER BY a, b, c, d, e, f
----
1  1  2  NULL  2  1
2  1  1  1     1  2

# Case with descending index column (idxCol < inputCol).
query IIIIII rowsort
SELECT * FROM def INNER LOOKUP JOIN def_e_desc AS def2 ON def.f = def2.f AND def2.e < def.d
----
2  1  1  2  1  1

# Case with descending index column (idxCol <= inputCol).
query IIIIII rowsort
SELECT * FROM def INNER LOOKUP JOIN def_e_desc AS def2
ON def.f = def2.f AND def2.e <= def.d ORDER BY def.d, def.e, def.f, def2.d, def2.e, def2.f
----
1  1  2  1     1  2
2  1  1  NULL  2  1
2  1  1  2     1  1

# Case with descending index column (idxCol > inputCol).
query IIIIII rowsort
SELECT * FROM def INNER LOOKUP JOIN def_e_desc AS def2 ON def.f = def2.f AND def2.e > def.d
----

# Case with descending index column (idxCol >= inputCol).
query IIIIII rowsort
SELECT * FROM def INNER LOOKUP JOIN def_e_desc AS def2 ON def.f = def2.f AND def2.e >= def.d
----
2  1  1  NULL  2  1
1  1  2  1     1  2

# Case with maximum and minimum integer bounds.
query IIII rowsort
SELECT * FROM (SELECT * FROM (VALUES (-9223372036854775807::INT), (9223372036854775807::INT))) v(x)
LEFT LOOKUP JOIN abc ON a < x
----
9223372036854775807   1     1     2
9223372036854775807   2     1     1
9223372036854775807   2     NULL  2
-9223372036854775807  NULL  NULL  NULL

# Case with maximum and minimum integer bounds.
query IIII rowsort
SELECT * FROM (SELECT * FROM (VALUES (-9223372036854775807::INT), (9223372036854775807::INT))) v(x)
LEFT LOOKUP JOIN abc ON a > x
----
-9223372036854775807  1     1     2
-9223372036854775807  2     1     1
-9223372036854775807  2     NULL  2
9223372036854775807   NULL  NULL  NULL

# Case with maximum and minimum integer bounds on descending column.
query IIII rowsort
SELECT * FROM (SELECT * FROM (VALUES (-9223372036854775807::INT), (9223372036854775807::INT))) v(x)
LEFT LOOKUP JOIN def_e_desc ON f IN (1, 2) AND e < x
----
9223372036854775807   NULL  2     1
9223372036854775807   2     1     1
9223372036854775807   1     1     2
-9223372036854775807  NULL  NULL  NULL

# Case with maximum and minimum integer bounds on descending column.
query IIII rowsort
SELECT * FROM (SELECT * FROM (VALUES (-9223372036854775807::INT), (9223372036854775807::INT))) v(x)
LEFT LOOKUP JOIN def_e_desc ON f IN (1, 2) AND e > x
----
-9223372036854775807  NULL  2     1
-9223372036854775807  2     1     1
-9223372036854775807  1     1     2
9223372036854775807   NULL  NULL  NULL

# Case with idxCol <= inputCol and decimal column type.
query IIIIRI
SELECT * FROM abc INNER LOOKUP JOIN def_e_decimal ON f = b AND e <= a::DECIMAL ORDER BY a, b, c, d, e, f
----
1  1  2  2     1  1
2  1  1  NULL  2  1
2  1  1  2     1  1

# Case with idxCol >= inputCol and decimal column type.
query IIIIRI
SELECT * FROM abc INNER LOOKUP JOIN def_e_decimal ON f = b AND e >= a::DECIMAL ORDER BY a, b, c, d, e, f
----
1  1  2  NULL  2  1
1  1  2  2     1  1
2  1  1  NULL  2  1

# Case with idxCol < inputCol and decimal column type.
query IIIIRI
SELECT * FROM abc INNER LOOKUP JOIN def_e_decimal ON f = b AND e < a::DECIMAL ORDER BY a, b, c, d, e, f
----
2  1  1  2  1  1

# Case with idxCol > inputCol and decimal column type.
query IIIIRI
SELECT * FROM abc INNER LOOKUP JOIN def_e_decimal ON f = b AND e > a::DECIMAL ORDER BY a, b, c, d, e, f
----
1  1  2  NULL  2  1

# Case with idxCol <= inputCol and float column type.
query IIIFI
SELECT * FROM abc INNER LOOKUP JOIN float_xy@asc_idx ON x <= a::FLOAT ORDER BY a, b, c, x, y
----
1  1     2  NaN   3
1  1     2  -Inf  5
1  1     2  1     1
2  NULL  2  NaN   3
2  NULL  2  -Inf  5
2  NULL  2  1     1
2  NULL  2  2     1
2  1     1  NaN   3
2  1     1  -Inf  5
2  1     1  1     1
2  1     1  2     1

# Case with idxCol >= inputCol and float column type.
query IIIFI
SELECT * FROM abc INNER LOOKUP JOIN float_xy@asc_idx ON x >= a::FLOAT ORDER BY a, b, c, x, y
----
1  1     2  1     1
1  1     2  2     1
1  1     2  +Inf  4
2  NULL  2  2     1
2  NULL  2  +Inf  4
2  1     1  2     1
2  1     1  +Inf  4

# Case with idxCol < inputCol and float column type.
query IIIFI
SELECT * FROM abc INNER LOOKUP JOIN float_xy@asc_idx ON x < a::FLOAT ORDER BY a, b, c, x, y
----
1  1     2  NaN   3
1  1     2  -Inf  5
2  NULL  2  NaN   3
2  NULL  2  -Inf  5
2  NULL  2  1     1
2  1     1  NaN   3
2  1     1  -Inf  5
2  1     1  1     1

# Case with idxCol > inputCol and float column type.
query IIIFI
SELECT * FROM abc INNER LOOKUP JOIN float_xy@asc_idx ON x > a::FLOAT ORDER BY a, b, c, x, y
----
1  1     2  2     1
1  1     2  +Inf  4
2  NULL  2  +Inf  4
2  1     1  +Inf  4

# Case with idxCol <= inputCol and float column type. Index is descending.
query IIIFI
SELECT * FROM abc INNER LOOKUP JOIN float_xy@desc_idx ON x <= a::FLOAT ORDER BY a, b, c, x, y
----
1  1     2  NaN   3
1  1     2  -Inf  5
1  1     2  1     1
2  NULL  2  NaN   3
2  NULL  2  -Inf  5
2  NULL  2  1     1
2  NULL  2  2     1
2  1     1  NaN   3
2  1     1  -Inf  5
2  1     1  1     1
2  1     1  2     1

# Case with idxCol >= inputCol and float column type. Index is descending.
query IIIFI
SELECT * FROM abc INNER LOOKUP JOIN float_xy@desc_idx ON x >= a::FLOAT ORDER BY a, b, c, x, y
----
1  1     2  1     1
1  1     2  2     1
1  1     2  +Inf  4
2  NULL  2  2     1
2  NULL  2  +Inf  4
2  1     1  2     1
2  1     1  +Inf  4

# Case with idxCol < inputCol and float column type. Index is descending.
query IIIFI
SELECT * FROM abc INNER LOOKUP JOIN float_xy@desc_idx ON x < a::FLOAT ORDER BY a, b, c, x, y
----
1  1     2  NaN   3
1  1     2  -Inf  5
2  NULL  2  NaN   3
2  NULL  2  -Inf  5
2  NULL  2  1     1
2  1     1  NaN   3
2  1     1  -Inf  5
2  1     1  1     1

# Case with idxCol > inputCol and float column type. Index is descending.
query IIIFI
SELECT * FROM abc INNER LOOKUP JOIN float_xy@desc_idx ON x > a::FLOAT ORDER BY a, b, c, x, y
----
1  1     2  2     1
1  1     2  +Inf  4
2  NULL  2  +Inf  4
2  1     1  +Inf  4

query TITI
SELECT * FROM string_xy xy1 INNER LOOKUP JOIN string_xy xy2 ON xy2.x < xy1.x ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
abc   1  ·     5
abcd  2  ·     5
abcd  2  abc   1
bcd   3  ·     5
bcd   3  abc   1
bcd   3  abcd  2
xyz   4  ·     5
xyz   4  abc   1
xyz   4  abcd  2
xyz   4  bcd   3

query TITI
SELECT * FROM string_xy xy1 INNER LOOKUP JOIN string_xy xy2 ON xy2.x > xy1.x ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
·     5  abc   1
·     5  abcd  2
·     5  bcd   3
·     5  xyz   4
abc   1  abcd  2
abc   1  bcd   3
abc   1  xyz   4
abcd  2  bcd   3
abcd  2  xyz   4
bcd   3  xyz   4

query TITI
SELECT * FROM string_xy xy1 INNER LOOKUP JOIN string_xy xy2 ON xy2.x <= xy1.x ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
·     5  ·     5
abc   1  ·     5
abc   1  abc   1
abcd  2  ·     5
abcd  2  abc   1
abcd  2  abcd  2
bcd   3  ·     5
bcd   3  abc   1
bcd   3  abcd  2
bcd   3  bcd   3
xyz   4  ·     5
xyz   4  abc   1
xyz   4  abcd  2
xyz   4  bcd   3
xyz   4  xyz   4

query TITI
SELECT * FROM string_xy xy1 INNER LOOKUP JOIN string_xy xy2 ON xy2.x >= xy1.x ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
·     5  ·     5
·     5  abc   1
·     5  abcd  2
·     5  bcd   3
·     5  xyz   4
abc   1  abc   1
abc   1  abcd  2
abc   1  bcd   3
abc   1  xyz   4
abcd  2  abcd  2
abcd  2  bcd   3
abcd  2  xyz   4
bcd   3  bcd   3
bcd   3  xyz   4
xyz   4  xyz   4

query TTTT
SELECT * FROM time_xy xy1 INNER LOOKUP JOIN time_xy xy2 ON xy2.x < xy1.x ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
0000-01-01 00:52:12.19515 +0000 UTC   NULL                             0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 00:52:12.19515 +0000 UTC   NULL                             0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000  0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000  0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000  0000-01-01 00:52:12.19515 +0000 UTC   NULL
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000  0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000  0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000  0000-01-01 00:52:12.19515 +0000 UTC   NULL
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000  0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000

query TTTT
SELECT * FROM time_xy xy1 INNER LOOKUP JOIN time_xy xy2 ON xy2.x > xy1.x ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-01 00:52:12.19515 +0000 UTC   NULL
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-01 00:52:12.19515 +0000 UTC   NULL
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 00:52:12.19515 +0000 UTC   NULL                              0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 00:52:12.19515 +0000 UTC   NULL                              0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000   0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000

query TTTT
SELECT * FROM time_xy xy1 INNER LOOKUP JOIN time_xy xy2 ON xy2.x <= xy1.x ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 00:52:12.19515 +0000 UTC   NULL                              0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 00:52:12.19515 +0000 UTC   NULL                              0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 00:52:12.19515 +0000 UTC   NULL                              0000-01-01 00:52:12.19515 +0000 UTC   NULL
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000   0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000   0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000   0000-01-01 00:52:12.19515 +0000 UTC   NULL
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000   0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000   0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000   0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000   0000-01-01 00:52:12.19515 +0000 UTC   NULL
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000   0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000   0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000

query TTTT
SELECT * FROM time_xy xy1 INNER LOOKUP JOIN time_xy xy2 ON xy2.x >= xy1.x ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-01 00:52:12.19515 +0000 UTC   NULL
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-01 00:52:12.19515 +0000 UTC   NULL
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 00:52:12.19515 +0000 UTC   NULL                              0000-01-01 00:52:12.19515 +0000 UTC   NULL
0000-01-01 00:52:12.19515 +0000 UTC   NULL                              0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 00:52:12.19515 +0000 UTC   NULL                              0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000   0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000   0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000   0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000

query TTTT
SELECT * FROM time_xy xy1 INNER LOOKUP JOIN time_xy xy2 ON xy2.y < xy1.y ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
NULL                                  infinity  0000-01-01 00:00:00 +0000 UTC         -infinity
NULL                                  infinity  0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
NULL                                  infinity  0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
NULL                                  infinity  0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000           0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000           0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000

query TTTT
SELECT * FROM time_xy xy1 INNER LOOKUP JOIN time_xy xy2 ON xy2.y > xy1.y ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
0000-01-01 00:00:00 +0000 UTC         -infinity  NULL                                  infinity
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         -infinity  0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   NULL                                  infinity
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000   0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000   NULL                                  infinity
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000   0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000   0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000   NULL                                  infinity

query TTTT
SELECT * FROM time_xy xy1 INNER LOOKUP JOIN time_xy xy2 ON xy2.y <= xy1.y ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
NULL                                  infinity  NULL                                  infinity
NULL                                  infinity  0000-01-01 00:00:00 +0000 UTC         -infinity
NULL                                  infinity  0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
NULL                                  infinity  0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
NULL                                  infinity  0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         -infinity          0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000           0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000           0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000           0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000           0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000

query TTTT
SELECT * FROM time_xy xy1 INNER LOOKUP JOIN time_xy xy2 ON xy2.y >= xy1.y ORDER BY xy1.x, xy1.y, xy2.x, xy2.y
----
NULL                                  infinity  NULL                                  infinity
0000-01-01 00:00:00 +0000 UTC         -infinity          NULL                                  infinity
0000-01-01 00:00:00 +0000 UTC         -infinity          0000-01-01 00:00:00 +0000 UTC         -infinity
0000-01-01 00:00:00 +0000 UTC         -infinity          0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         -infinity          0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         -infinity          0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000           NULL                                  infinity
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000           0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000           NULL                                  infinity
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000           0000-01-01 00:00:00 +0000 UTC         2016-06-22 19:10:25 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000           0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000
0000-01-01 23:59:59.999999 +0000 UTC  1970-01-01 00:00:00 +0000 +0000           0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000           NULL                                  infinity
0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000           0000-01-02 00:00:00 +0000 UTC         2042-01-01 00:00:00 +0000 +0000

statement ok
SET variable_inequality_lookup_join_enabled=false

statement error pq: could not produce a query plan conforming to the LOOKUP JOIN hint
SELECT a, b, c, d, e, f FROM abc INNER LOOKUP JOIN def ON f <= a ORDER BY a, b, c, d, e, f

statement error pq: could not produce a query plan conforming to the LOOKUP JOIN hint
SELECT a, b, c, d, e, f FROM def INNER LOOKUP JOIN abc ON a >= f ORDER BY a, b, c, d, e, f

statement error pq: could not produce a query plan conforming to the LOOKUP JOIN hint
SELECT a, b, c, d, e, f FROM abc INNER LOOKUP JOIN def ON f < a AND f >= b ORDER BY a, b, c, d, e, f

statement ok
RESET variable_inequality_lookup_join_enabled


subtest regression_89576

# Regression test for #89576. Lookup joins should not try to produce virtual
# computed columns directly from primary indexes.
statement ok
CREATE TABLE t89576 (
  k INT PRIMARY KEY,
  s STRING,
  v STRING AS (lower(s)) VIRTUAL NOT NULL,
  INDEX (v)
);
INSERT INTO t89576 VALUES (1, 'foo')

query T
SELECT t2.v
FROM t89576 AS t1
LEFT JOIN t89576 AS t2
ON (t2.v) = (t1.v)
AND (t2.s) = (t1.s)
----
foo

# TODO(#90771): We no longer explore lookup joins for this query, but it
# should be possible by projecting virtual computed column expressions after the
# upper join in the paired joiner. When this is supported, this query should
# succeed and we should turn this test directive into "query T" and verify the
# result matches the one in the query above.
statement error pgcode XXUUU could not produce a query plan conforming to the LOOKUP JOIN hint
SELECT t2.v
FROM t89576 AS t1
LEFT LOOKUP JOIN t89576 AS t2
ON (t2.v) = (t1.v)
AND (t2.s) = (t1.s)

# A handful of tests that have a lookup join for which we have "lookup columns
# are key". These are "regression tests" if #108489 were to be implemented.
statement ok
CREATE TABLE t108489_1 (k1 INT PRIMARY KEY, FAMILY (k1));
CREATE TABLE t108489_2 (k2 INT PRIMARY KEY, i2 INT, u2 INT, INDEX (i2, u2), UNIQUE INDEX (u2), FAMILY (k2, i2, u2));
CREATE TABLE t108489_3 (k3 INT PRIMARY KEY, i3 INT, u3 INT, v3 INT, w3 INT, INDEX (i3, u3) STORING (v3, w3), UNIQUE INDEX (u3), FAMILY (k3, i3, u3), FAMILY (v3), FAMILY (w3));
INSERT INTO t108489_1 VALUES (1);
INSERT INTO t108489_2 VALUES (1, 1, 1);
INSERT INTO t108489_3 VALUES (1, 1, 1, 1, 1);

query I
SELECT k2 FROM t108489_1 INNER LOOKUP JOIN t108489_2 ON i2 = k1 AND u2 = 1 WHERE k1 = 1;
----
1

query I
SELECT k3 FROM t108489_1 INNER LOOKUP JOIN t108489_3 ON i3 = k1 AND u3 = 1 WHERE k1 = 1;
----
1

query II
SELECT k3, w3 FROM t108489_1 INNER LOOKUP JOIN t108489_3 ON i3 = k1 AND u3 = 1 WHERE k1 = 1;
----
1 1

query III
SELECT k3, v3, w3 FROM t108489_1 INNER LOOKUP JOIN t108489_3 ON i3 = k1 AND u3 = 1 WHERE k1 = 1;
----
1 1 1

# Regression test for incorrectly using OutOfOrder mode of the streamer with
# multiple column families (#113013).

statement ok
CREATE TABLE l_113013 (r_id INT, l_id INT, PRIMARY KEY (r_id, l_id), INDEX l_id_idx(l_id));
CREATE TABLE r_113013 (id INT PRIMARY KEY, c1 STRING NOT NULL, c2 STRING NOT NULL, c3 STRING NOT NULL, FAMILY f1 (id, c1), FAMILY f2 (c2), FAMILY f3 (c3));
ALTER TABLE r_113013 SPLIT AT VALUES (2);
INSERT INTO l_113013 VALUES (1, 1), (2, 1);
INSERT INTO r_113013 VALUES (1, 'c1', 'c2', repeat('c3', 2000)), (2, 'c1', 'c2', 'c3');

query II rowsort
SELECT length(c1), length(c3) FROM l_113013 l INNER JOIN r_113013 r ON l.r_id = r.id WHERE l.l_id = 1;
----
2  4000
2  2

# Regression test for incorrectly treating cross-range ScanRequests by the
# Streamer when "equality columns are key" in the lookup join (#101823).
statement ok
CREATE TABLE l_101823 (a INT, b INT, PRIMARY KEY (a, b));
INSERT INTO l_101823 VALUES (1, 1);
CREATE TABLE r_101823 (k INT PRIMARY KEY, u INT, v INT, w BOOL, UNIQUE INDEX (u), UNIQUE INDEX (u, v, w));
INSERT INTO r_101823 VALUES (1, 1, 1, false);
ALTER INDEX r_101823_u_v_w_key SPLIT AT VALUES (1, 1, false), (1, 1, true);

query I
SELECT count(v) FROM l_101823 LEFT LOOKUP JOIN r_101823 ON a = u AND b = v;
----
1

subtest regression_124732

# Regression test for incorrectly remapping equal columns with non-identical
# types (#124732).
statement ok
CREATE TABLE table_1_124732 (col1_6 REGCLASS);

statement ok
CREATE TABLE table_3_124732 (
  col3_0 OID,
  col3_7 STRING AS (col3_0::STRING) VIRTUAL PRIMARY KEY
);

statement ok
INSERT INTO table_1_124732 (col1_6) VALUES (0);
INSERT INTO table_3_124732 (col3_0) VALUES (0);

query T
SELECT col1_6 FROM table_1_124732 INNER HASH JOIN table_3_124732 ON col3_0 = col1_6;
----
-

statement error pgcode XXUUU pq: could not produce a query plan conforming to the LOOKUP JOIN hint
SELECT col1_6 FROM table_1_124732 INNER LOOKUP JOIN table_3_124732 ON col3_0 = col1_6;

# Regression test for incorrectly remapping columns in a composite-sensitive
# expression to produce a lookup join (#124732).
statement ok
CREATE TABLE t_124732 (
  i DECIMAL,
  v STRING AS (i::STRING) VIRTUAL,
  PRIMARY KEY (v, i)
);

statement ok
INSERT INTO t_124732 VALUES (1.000);

statement error pgcode XXUUU pq: could not produce a query plan conforming to the LOOKUP JOIN hint
SELECT * FROM (VALUES (1::DECIMAL)) AS v(i)
INNER LOOKUP JOIN t_124732 ON v.i = t_124732.i;

query RRT
SELECT * FROM (VALUES (1::DECIMAL)) AS v(i)
INNER HASH JOIN t_124732 ON v.i = t_124732.i;
----
1  1.000  1.000

subtest end

# Regression test for #134697. Constant projections for lookup joins should be
# correctly typed.
statement ok
CREATE TABLE t134697 (
  a INT,
  b BIT(2),
  vb VARBIT(2),
  c CHAR(2),
  vc VARCHAR(2),
  d DECIMAL(6, 2),
  INDEX (b, a),
  INDEX (vb, a),
  INDEX (c, a),
  INDEX (vc, a),
  INDEX (d, a)
)

statement ok
CREATE TABLE t134697_x (
  x INT PRIMARY KEY
)

statement ok
INSERT INTO t134697 VALUES (1, '11', '11', 'ab', 'ab', 1234.12)

statement ok
INSERT INTO t134697_x VALUES (1);

query IT
SELECT a, b FROM t134697_x
JOIN t134697 ON a = x AND b = '111';
----

# This should return zero rows, like the non-hinted query above.
query IT
SELECT a, b FROM t134697_x
INNER LOOKUP JOIN t134697 ON a = x AND b = '111';
----

query IT
SELECT a, vb FROM t134697_x
JOIN t134697 ON a = x AND vb = '111';
----

# This should return zero rows, like the non-hinted query above.
query IT
SELECT a, vb FROM t134697_x
INNER LOOKUP JOIN t134697 ON a = x AND vb = '111';
----

query IT
SELECT a, c FROM t134697_x
JOIN t134697 ON a = x AND c = 'abc';
----

# This should return zero rows, like the non-hinted query above.
query IT
SELECT a, c FROM t134697_x
INNER LOOKUP JOIN t134697 ON a = x AND c = 'abc';
----

query IT
SELECT a, vc FROM t134697_x
JOIN t134697 ON a = x AND vc = 'abc';
----

# This should return zero rows, like the non-hinted query above.
query IT
SELECT a, vc FROM t134697_x
INNER LOOKUP JOIN t134697 ON a = x AND vc = 'abc';
----

query IT
SELECT a, d FROM t134697_x
JOIN t134697 ON a = x AND d = 1234.123412::DECIMAL(8, 4);
----

# This should return zero rows, like the non-hinted query above.
query IT
SELECT a, d FROM t134697_x
INNER LOOKUP JOIN t134697 ON a = x AND d = 1234.1234::DECIMAL(8, 4);
----
