statement ok
CREATE TABLE metrics (
  id       SERIAL PRIMARY KEY,
  nullable INT,
  name     STRING,
  INDEX    name_index (name)
)

statement ok
insert into metrics (id,nullable,name) values (1,NULL,'cpu'), (2,1,'cpu'), (3,NULL,'mem'), (4,2,'disk')

statement ok
CREATE TABLE metric_values (
  metric_id INT8,
  time      TIMESTAMPTZ,
  nullable  INT,
  value     INT8,
  PRIMARY KEY (metric_id, time),
  INDEX secondary (metric_id, nullable, time)
)

statement ok
insert into metric_values (metric_id, time, nullable, value) values
 (1,'2020-01-01 00:00:00+00:00',NULL,0),
 (1,'2020-01-01 00:00:01+00:00',1,1),
 (2,'2020-01-01 00:00:00+00:00',NULL,2),
 (2,'2020-01-01 00:00:01+00:00',2,3),
 (2,'2020-01-01 00:01:01+00:00',-11,4),
 (2,'2020-01-01 00:01:02+00:00',-10,5),
 (3,'2020-01-01 00:01:00+00:00',NULL,6),
 (3,'2020-01-01 00:01:01+00:00',3,7)

# metric_values_desc is a descending time version of metric_values.
statement ok
CREATE TABLE metric_values_desc (
  metric_id INT8,
  time      TIMESTAMPTZ,
  nullable  INT,
  value     INT8,
  PRIMARY KEY (metric_id, time DESC),
  INDEX secondary (metric_id, nullable DESC, time DESC)
)

statement ok
insert into metric_values_desc select * from metric_values

# The final statements below need some stats to chose the lookup join.
statement ok
ALTER TABLE metric_values INJECT STATISTICS
'[
 {
   "columns": ["metric_id"],
   "created_at": "2018-01-01 1:00:00.00000+00:00",
   "row_count": 1000,
   "distinct_count": 10
 },
 {
   "columns": ["time"],
   "created_at": "2018-01-01 1:30:00.00000+00:00",
   "row_count": 1000,
   "distinct_count": 1000
 },
 {
   "columns": ["nullable"],
   "created_at": "2018-01-01 1:30:00.00000+00:00",
   "row_count": 1000,
   "distinct_count": 10,
    "histo_buckets": [
      {"num_eq": 0, "num_range": 0, "distinct_range": 0, "upper_bound": "-10"},
      {"num_eq": 0, "num_range": 1000, "distinct_range": 10, "upper_bound": "0"}
    ],
    "histo_col_type": "INT"
 },
 {
    "columns": ["value"],
    "created_at": "2018-01-01 1:30:00.00000+00:00",
    "row_count": 1000,
    "distinct_count": 1000
  }
]'

statement ok
ALTER TABLE metrics INJECT STATISTICS
'[
 {
   "columns": ["id"],
   "created_at": "2018-01-01 1:00:00.00000+00:00",
   "row_count": 10,
   "distinct_count": 10
 },
 {
   "columns": ["nullable"],
   "created_at": "2018-01-01 1:30:00.00000+00:00",
   "row_count": 10,
   "distinct_count": 10
 },
 {
   "columns": ["name"],
   "created_at": "2018-01-01 1:30:00.00000+00:00",
   "row_count": 10,
   "distinct_count": 10
 }
]'

query ITIIIIT
SELECT *
FROM metric_values as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  time > '2020-01-01 00:00:00+00:00' AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:01 +0000 UTC  1    1  1  NULL  cpu
2  2020-01-01 00:00:01 +0000 UTC  2    3  2  1     cpu
2  2020-01-01 00:01:01 +0000 UTC  -11  4  2  1     cpu
2  2020-01-01 00:01:02 +0000 UTC  -10  5  2  1     cpu

query ITIIIIT
SELECT *
FROM metric_values_desc
INNER JOIN metrics
ON metric_id=id
WHERE
  time > '2020-01-01 00:00:00+00:00' AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:01 +0000 UTC  1    1  1  NULL  cpu
2  2020-01-01 00:00:01 +0000 UTC  2    3  2  1     cpu
2  2020-01-01 00:01:01 +0000 UTC  -11  4  2  1     cpu
2  2020-01-01 00:01:02 +0000 UTC  -10  5  2  1     cpu

query ITIIIIT
SELECT *
FROM metric_values
INNER JOIN metrics
ON metric_id=id
WHERE
  time >= '2020-01-01 00:00:00+00:00' AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:00 +0000 UTC  NULL  0  1  NULL  cpu
1  2020-01-01 00:00:01 +0000 UTC  1     1  1  NULL  cpu
2  2020-01-01 00:00:00 +0000 UTC  NULL  2  2  1     cpu
2  2020-01-01 00:00:01 +0000 UTC  2     3  2  1     cpu
2  2020-01-01 00:01:01 +0000 UTC  -11   4  2  1     cpu
2  2020-01-01 00:01:02 +0000 UTC  -10   5  2  1     cpu

query ITIIIIT
SELECT *
FROM metric_values_desc
INNER JOIN metrics
ON metric_id=id
WHERE
  time >= '2020-01-01 00:00:00+00:00' AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:00 +0000 UTC  NULL  0  1  NULL  cpu
1  2020-01-01 00:00:01 +0000 UTC  1     1  1  NULL  cpu
2  2020-01-01 00:00:00 +0000 UTC  NULL  2  2  1     cpu
2  2020-01-01 00:00:01 +0000 UTC  2     3  2  1     cpu
2  2020-01-01 00:01:01 +0000 UTC  -11   4  2  1     cpu
2  2020-01-01 00:01:02 +0000 UTC  -10   5  2  1     cpu

query ITIIIIT
SELECT *
FROM metric_values
INNER JOIN metrics
ON metric_id=id
WHERE
  time < '2020-01-01 00:00:00+00:00' AND
  name='cpu'
----

query ITIIIIT
SELECT *
FROM metric_values_desc
INNER JOIN metrics
ON metric_id=id
WHERE
  time < '2020-01-01 00:00:00+00:00' AND
  name='cpu'
----

query ITIIIIT
SELECT *
FROM metric_values
INNER JOIN metrics
ON metric_id=id
WHERE
  time <= '2020-01-01 00:00:00+00:00' AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:00 +0000 UTC  NULL  0  1  NULL  cpu
2  2020-01-01 00:00:00 +0000 UTC  NULL  2  2  1     cpu

query ITIIIIT
SELECT *
FROM metric_values_desc
INNER JOIN metrics
ON metric_id=id
WHERE
  time <= '2020-01-01 00:00:00+00:00' AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:00 +0000 UTC  NULL  0  1  NULL  cpu
2  2020-01-01 00:00:00 +0000 UTC  NULL  2  2  1     cpu

query ITIIIIT
SELECT *
FROM metric_values
INNER JOIN metrics
ON metric_id=id
WHERE
  time < '2020-01-01 00:00:10+00:00' AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:00 +0000 UTC  NULL  0  1  NULL  cpu
1  2020-01-01 00:00:01 +0000 UTC  1     1  1  NULL  cpu
2  2020-01-01 00:00:00 +0000 UTC  NULL  2  2  1     cpu
2  2020-01-01 00:00:01 +0000 UTC  2     3  2  1     cpu

query ITIIIIT
SELECT *
FROM metric_values_desc
INNER JOIN metrics
ON metric_id=id
WHERE
  time < '2020-01-01 00:00:10+00:00' AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:00 +0000 UTC  NULL  0  1  NULL  cpu
1  2020-01-01 00:00:01 +0000 UTC  1     1  1  NULL  cpu
2  2020-01-01 00:00:00 +0000 UTC  NULL  2  2  1     cpu
2  2020-01-01 00:00:01 +0000 UTC  2     3  2  1     cpu

query ITIIIIT
SELECT *
FROM metric_values
INNER JOIN metrics
ON metric_id=id
WHERE
  time BETWEEN '2020-01-01 00:00:00+00:00' AND '2020-01-01 00:10:00+00:00' AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:00 +0000 UTC  NULL  0  1  NULL  cpu
1  2020-01-01 00:00:01 +0000 UTC  1     1  1  NULL  cpu
2  2020-01-01 00:00:00 +0000 UTC  NULL  2  2  1     cpu
2  2020-01-01 00:00:01 +0000 UTC  2     3  2  1     cpu
2  2020-01-01 00:01:01 +0000 UTC  -11   4  2  1     cpu
2  2020-01-01 00:01:02 +0000 UTC  -10   5  2  1     cpu

query ITIIIIT
SELECT *
FROM metric_values_desc
INNER JOIN metrics
ON metric_id=id
WHERE
  time BETWEEN '2020-01-01 00:00:00+00:00' AND '2020-01-01 00:10:00+00:00' AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:00 +0000 UTC  NULL  0  1  NULL  cpu
1  2020-01-01 00:00:01 +0000 UTC  1     1  1  NULL  cpu
2  2020-01-01 00:00:00 +0000 UTC  NULL  2  2  1     cpu
2  2020-01-01 00:00:01 +0000 UTC  2     3  2  1     cpu
2  2020-01-01 00:01:01 +0000 UTC  -11   4  2  1     cpu
2  2020-01-01 00:01:02 +0000 UTC  -10   5  2  1     cpu

# Test lookup conditions w/ a left join.
query IITITII
SELECT *
FROM metrics
LEFT JOIN metric_values
ON metric_id=id
AND time BETWEEN '2020-01-01 00:00:00+00:00' AND '2020-01-01 00:10:00+00:00'
AND name='cpu'
ORDER BY value, id
----
3  NULL  mem   NULL  NULL                           NULL  NULL
4  2     disk  NULL  NULL                           NULL  NULL
1  NULL  cpu   1     2020-01-01 00:00:00 +0000 UTC  NULL  0
1  NULL  cpu   1     2020-01-01 00:00:01 +0000 UTC  1     1
2  1     cpu   2     2020-01-01 00:00:00 +0000 UTC  NULL  2
2  1     cpu   2     2020-01-01 00:00:01 +0000 UTC  2     3
2  1     cpu   2     2020-01-01 00:01:01 +0000 UTC  -11   4
2  1     cpu   2     2020-01-01 00:01:02 +0000 UTC  -10   5

# Test lookup conditions w/ a semi join.
query IIT
SELECT *
FROM metrics m
WHERE EXISTS (SELECT * FROM metric_values mv WHERE mv.metric_id = m.id AND time BETWEEN '2020-01-01 00:00:00+00:00' AND '2020-01-01 00:10:00+00:00')
ORDER BY m.id
----
1  NULL  cpu
2  1     cpu
3  NULL  mem

# Test NULL values in pre-join where conditions.
query ITIIIIT
SELECT *
FROM metric_values as v
INNER JOIN metrics as m
ON metric_id=id
AND v.nullable = m.nullable
WHERE
  time > '2020-01-01 00:00:00+00:00' AND
  name='cpu'
ORDER BY value
----

# Test NULL values in bounded lookup span.
query ITIIIIT
SELECT *
FROM metric_values as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  v.nullable BETWEEN -20 AND -10 AND
  name='cpu'
ORDER BY value
----
2  2020-01-01 00:01:01 +0000 UTC  -11  4  2  1  cpu
2  2020-01-01 00:01:02 +0000 UTC  -10  5  2  1  cpu

# Test NULL values in bounded lookup span (descending).
query ITIIIIT
SELECT *
FROM metric_values_desc as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  v.nullable BETWEEN -20 AND -10 AND
  name='cpu'
ORDER BY value
----
2  2020-01-01 00:01:01 +0000 UTC  -11  4  2  1  cpu
2  2020-01-01 00:01:02 +0000 UTC  -10  5  2  1  cpu

# Test NULL values in > unbounded lookup span.
query ITIIIIT
SELECT *
FROM metric_values as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  v.nullable > 1 AND
  name='cpu'
ORDER BY value
----
2  2020-01-01 00:00:01 +0000 UTC  2  3  2  1  cpu

# Test NULL values in > unbounded lookup span (descending).
query ITIIIIT
SELECT *
FROM metric_values_desc as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  v.nullable > 1 AND
  name='cpu'
ORDER BY value
----
2  2020-01-01 00:00:01 +0000 UTC  2  3  2  1  cpu

# Test NULL values in >= unbounded lookup span.
query ITIIIIT
SELECT *
FROM metric_values as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  v.nullable >= 1 AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:01 +0000 UTC  1  1  1  NULL  cpu
2  2020-01-01 00:00:01 +0000 UTC  2  3  2  1     cpu

# Test NULL values in >= unbounded lookup span (descending).
query ITIIIIT
SELECT *
FROM metric_values_desc as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  v.nullable >= 1 AND
  name='cpu'
ORDER BY value
----
1  2020-01-01 00:00:01 +0000 UTC  1  1  1  NULL  cpu
2  2020-01-01 00:00:01 +0000 UTC  2  3  2  1     cpu

# Test NULL values in < unbounded lookup span.
query ITIIIIT
SELECT *
FROM metric_values as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  v.nullable < -10 AND
  name='cpu'
ORDER BY value
----
2  2020-01-01 00:01:01 +0000 UTC  -11   4  2  1     cpu

# Test NULL values in < unbounded lookup span (descending).
query ITIIIIT
SELECT *
FROM metric_values_desc as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  v.nullable < -10 AND
  name='cpu'
ORDER BY value
----
2  2020-01-01 00:01:01 +0000 UTC  -11  4  2  1  cpu

# Test NULL values in <= unbounded lookup span.
query ITIIIIT
SELECT *
FROM metric_values as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  v.nullable <= -10 AND
  name='cpu'
ORDER BY value
----
2  2020-01-01 00:01:01 +0000 UTC  -11   4  2  1     cpu
2  2020-01-01 00:01:02 +0000 UTC  -10   5  2  1     cpu

# Test NULL values in <= unbounded lookup span (descending).
query ITIIIIT
SELECT *
FROM metric_values_desc as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  v.nullable <= -10 AND
  name='cpu'
ORDER BY value
----
2  2020-01-01 00:01:01 +0000 UTC  -11  4  2  1  cpu
2  2020-01-01 00:01:02 +0000 UTC  -10  5  2  1  cpu

# Test NULL values in WHERE equality conditions.
query ITIIIIT
SELECT *
FROM metric_values as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  time < '2020-01-01 00:00:10+00:00' AND
  name='cpu' AND
  v.nullable = m.nullable
ORDER BY value
----

# Test NULL values in simple equality condition.
query ITIIIIT
SELECT *
FROM metric_values as v
INNER JOIN metrics as m
ON metric_id=id
WHERE
  time < '2020-01-01 00:00:10+00:00' AND
  name='cpu' AND
  v.nullable = 1
ORDER BY value
----
1  2020-01-01 00:00:01 +0000 UTC  1  1  1  NULL  cpu

# Regression test for issue #68200.  This ensures that we properly construct the
# span to account for both ends of the inequality.
statement ok
CREATE TABLE order_line (ol_o_id INT8, ol_i_id INT8);
INSERT
INTO
  order_line (ol_o_id, ol_i_id)
VALUES
  (19, 6463), (20, 6463), (100, 6463), (101, 6463);
CREATE INDEX ol_io ON order_line (ol_i_id, ol_o_id);
CREATE TABLE stock (s_i_id INT8);
INSERT INTO stock (s_i_id) VALUES (6463)

query II rowsort
SELECT
  s_i_id, ol_o_id
FROM
  stock INNER LOOKUP JOIN order_line ON s_i_id = ol_i_id
WHERE
  ol_o_id BETWEEN 20 AND 100
----
6463  20
6463  100

# Make sure we don't confuse logic to handle constants and inequalities.
query II
SELECT
  s_i_id, ol_o_id
FROM
  stock INNER LOOKUP JOIN order_line ON s_i_id = ol_i_id
WHERE
  ol_o_id IN (19, 20, 21) AND ol_o_id >= 20
----
6463  20
