# LogicTest: local-opt


# ------------------------------------------------------------------------------
# Numeric References Tests.
# These are put at the beginning of the file to ensure the numeric table
# reference is 53 (the numeric reference of the first table).
# If the numbering scheme in cockroach changes, this test will break.
# These tests replicate the tests at sql/table_ref_test.go. The reason
# for duplication is to include tests within the opt testing framework
# TODO(madhavsuresh): get the numeric reference ID in a less brittle fashion
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE num_ref (a INT PRIMARY KEY, xx INT, b INT, c INT, INDEX bc (b,c))

statement ok
CREATE TABLE num_ref_hidden (a INT, b INT)

statement ok
ALTER TABLE num_ref RENAME COLUMN b TO d

statement ok
ALTER TABLE num_ref RENAME COLUMN a TO p

statement ok
ALTER TABLE num_ref DROP COLUMN xx

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53 AS num_ref_alias]
----
scan  ·      ·                (p, d, c)  ·
·     table  num_ref@primary  ·          ·
·     spans  ALL              ·          ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(4) AS num_ref_alias]
----
scan  ·      ·                (c)  ·
·     table  num_ref@primary  ·    ·
·     spans  ALL              ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(1,4) AS num_ref_alias]
----
scan  ·      ·                (p, c)  ·
·     table  num_ref@primary  ·       ·
·     spans  ALL              ·       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(1,3,4) AS num_ref_alias]
----
scan  ·      ·                (p, d, c)  ·
·     table  num_ref@primary  ·          ·
·     spans  ALL              ·          ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(4,3,1) AS num_ref_alias]
----
render     ·         ·                (c, d, p)  ·
 │         render 0  c                ·          ·
 │         render 1  d                ·          ·
 │         render 2  p                ·          ·
 └── scan  ·         ·                (p, d, c)  ·
·          table     num_ref@primary  ·          ·
·          spans     ALL              ·          ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(4,3,1) AS num_ref_alias(col1,col2,col3)]
----
render     ·         ·                (col1, col2, col3)  ·
 │         render 0  c                ·                   ·
 │         render 1  d                ·                   ·
 │         render 2  p                ·                   ·
 └── scan  ·         ·                (p, d, c)           ·
·          table     num_ref@primary  ·                   ·
·          spans     ALL              ·                   ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(4,3,1) AS num_ref_alias]@bc
----
render     ·         ·           (c, d, p)  ·
 │         render 0  c           ·          ·
 │         render 1  d           ·          ·
 │         render 2  p           ·          ·
 └── scan  ·         ·           (p, d, c)  ·
·          table     num_ref@bc  ·          ·
·          spans     ALL         ·          ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(4) AS num_ref_alias]@bc
----
scan  ·      ·           (c)  ·
·     table  num_ref@bc  ·    ·
·     spans  ALL         ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(3) AS num_ref_alias]@bc
----
scan  ·      ·           (d)  ·
·     table  num_ref@bc  ·    ·
·     spans  ALL         ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(1) AS num_ref_alias]@bc
----
scan  ·      ·           (p)  ·
·     table  num_ref@bc  ·    ·
·     spans  ALL         ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(1) AS num_ref_alias]@[1]
----
scan  ·      ·                (p)  ·
·     table  num_ref@primary  ·    ·
·     spans  ALL              ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(1) AS num_ref_alias]@[2]
----
scan  ·      ·           (p)  ·
·     table  num_ref@bc  ·    ·
·     spans  ALL         ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(3) AS num_ref_alias]@[1]
----
scan  ·      ·                (d)  ·
·     table  num_ref@primary  ·    ·
·     spans  ALL              ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(3) AS num_ref_alias]@[2]
----
scan  ·      ·           (d)  ·
·     table  num_ref@bc  ·    ·
·     spans  ALL         ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(4) AS num_ref_alias]@[1]
----
scan  ·      ·                (c)  ·
·     table  num_ref@primary  ·    ·
·     spans  ALL              ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [53(4) AS num_ref_alias]@[2]
----
scan  ·      ·           (c)  ·
·     table  num_ref@bc  ·    ·
·     spans  ALL         ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [54(1,3) AS num_ref_alias]
----
scan  ·      ·                       (a)  ·
·     table  num_ref_hidden@primary  ·    ·
·     spans  ALL                     ·    ·


query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [54(3) AS num_ref_alias]
----
scan  ·      ·                       ()  ·
·     table  num_ref_hidden@primary  ·   ·
·     spans  ALL                     ·   ·

query TTTTT
EXPLAIN (VERBOSE) SELECT rowid FROM [54(3) AS num_ref_alias]
----
scan  ·      ·                       (rowid[hidden])  ·
·     table  num_ref_hidden@primary  ·                ·
·     spans  ALL                     ·                ·

query error pq: \[666\(1\) AS num_ref_alias\]: relation \"\[666\]\" does not exist
EXPLAIN (VERBOSE) SELECT * FROM [666(1) AS num_ref_alias]

query error pq: column \[666\] does not exist
EXPLAIN (VERBOSE) SELECT * FROM [53(666) AS num_ref_alias]

query error pq: column \[2\] does not exist
EXPLAIN (VERBOSE) SELECT * FROM [53(2) AS num_ref_alias]

query error pq: an explicit list of column IDs must include at least one column
EXPLAIN (VERBOSE) SELECT * FROM [53() AS num_ref_alias]

query error pq: an explicit list of column IDs must include at least one column
EXPLAIN (VERBOSE) SELECT 1 FROM [53() as num_ref_alias]

statement ok
DROP TABLE num_ref

query error pq: \[53\(1\) AS num_ref_alias\]: table is being dropped
EXPLAIN (VERBOSE) SELECT * FROM [53(1) AS num_ref_alias]

# ------------------------------------------------------------------------------
# Basic filter combinations.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE a (x INT PRIMARY KEY, y INT);

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM a WHERE x > 1
----
scan  ·      ·          (x, y)  ·
·     table  a@primary  ·       ·
·     spans  /2-        ·       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM a WHERE y > 10
----
scan  ·       ·          (x, y)  ·
·     table   a@primary  ·       ·
·     spans   ALL        ·       ·
·     filter  y > 10     ·       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM a WHERE x > 1 AND x < 3
----
scan  ·      ·          (x, y)  ·
·     table  a@primary  ·       ·
·     spans  /2-/2/#    ·       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM a WHERE x > 1 AND y < 30
----
scan  ·       ·          (x, y)  ·
·     table   a@primary  ·       ·
·     spans   /2-        ·       ·
·     filter  y < 30     ·       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT x + 1 AS r FROM a
----
render     ·         ·          (r)  ·
 │         render 0  x + 1      ·    ·
 └── scan  ·         ·          (x)  ·
·          table     a@primary  ·    ·
·          spans     ALL        ·    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT x AS a, x + 1 AS b, y, y + 1 AS c, x + y AS d FROM a
----
render     ·         ·          (a, b, y, c, d)  ·
 │         render 0  x          ·                ·
 │         render 1  x + 1      ·                ·
 │         render 2  y          ·                ·
 │         render 3  y + 1      ·                ·
 │         render 4  x + y      ·                ·
 └── scan  ·         ·          (x, y)           ·
·          table     a@primary  ·                ·
·          spans     ALL        ·                ·

query TTTTT
EXPLAIN (VERBOSE) SELECT u * v + v AS r FROM (SELECT x + 3, y + 10 FROM a) AS foo(u, v)
----
render          ·         ·                                       (r)                       ·
 │              render 0  "?column?" + ("?column?" * "?column?")  ·                         ·
 └── render     ·         ·                                       ("?column?", "?column?")  ·
      │         render 0  x + 3                                   ·                         ·
      │         render 1  y + 10                                  ·                         ·
      └── scan  ·         ·                                       (x, y)                    ·
·               table     a@primary                               ·                         ·
·               spans     ALL                                     ·                         ·

query TTTTT
EXPLAIN (VERBOSE) SELECT x, x, y, x FROM a
----
render     ·         ·          (x, x, y, x)  ·
 │         render 0  x          ·             ·
 │         render 1  x          ·             ·
 │         render 2  y          ·             ·
 │         render 3  x          ·             ·
 └── scan  ·         ·          (x, y)        ·
·          table     a@primary  ·             ·
·          spans     ALL        ·             ·

query TTTTT
EXPLAIN (VERBOSE) SELECT x + 1 AS a, x + y AS b FROM a WHERE x + y > 20
----
render     ·         ·             (a, b)  ·
 │         render 0  x + 1         ·       ·
 │         render 1  x + y         ·       ·
 └── scan  ·         ·             (x, y)  ·
·          table     a@primary     ·       ·
·          spans     ALL           ·       ·
·          filter    (x + y) > 20  ·       ·

statement ok
DROP TABLE a

# ------------------------------------------------------------------------------
# Test with a hidden column.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE b (x INT, y INT);

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM b
----
scan  ·      ·          (x, y)  ·
·     table  b@primary  ·       ·
·     spans  ALL        ·       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT x, y, rowid FROM b WHERE rowid > 0
----
scan  ·      ·          (x, y, rowid[hidden])  ·
·     table  b@primary  ·                      ·
·     spans  /1-        ·                      ·

statement ok
DROP TABLE b

# ------------------------------------------------------------------------------
# Test with storing columns.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE t (
  a INT PRIMARY KEY,
  b INT,
  c INT,
  d INT,
  INDEX b_idx (b) STORING (c, d),
  UNIQUE INDEX c_idx (c) STORING (b, d)
)

query TTBITTBB colnames
SHOW INDEXES FROM t
----
table_name  index_name  non_unique  seq_in_index  column_name  direction  storing  implicit
t           primary     false       1             a            ASC        false    false
t           b_idx       true        1             b            ASC        false    false
t           b_idx       true        2             c            N/A        true     false
t           b_idx       true        3             d            N/A        true     false
t           b_idx       true        4             a            ASC        false    true
t           c_idx       false       1             c            ASC        false    false
t           c_idx       false       2             b            N/A        true     false
t           c_idx       false       3             d            N/A        true     false
t           c_idx       false       4             a            ASC        false    true

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

statement ok
SET tracing = on,kv,results; SELECT * FROM t@b_idx; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /t/b_idx/2/1/c/d -> /3/4
output row: [1 2 3 4]

statement ok
SET tracing = on,kv,results; SELECT * FROM t@c_idx; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /t/c_idx/3/b/d -> /2/4
output row: [1 2 3 4]

# Test index backfill for UNIQUE and non-UNIQUE indexes with STORING columns.

statement ok
CREATE INDEX d_idx ON t (d) STORING (b)

statement ok
SET tracing = on,kv,results; SELECT a, b, d FROM t@d_idx; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /t/d_idx/4/1/b -> /2
output row: [1 2 4]

statement ok
CREATE UNIQUE INDEX a_idx ON t (a) STORING (b)

statement ok
SET tracing = on,kv,results; SELECT a, b FROM t@a_idx; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /t/a_idx/1/b -> /2
output row: [1 2]

# Test that unspecified storing values are treated like NULL values.
statement ok
INSERT INTO t (a) VALUES (2)

statement ok
INSERT INTO t VALUES (3)

statement ok
SET tracing = on,kv,results; SELECT * FROM t@b_idx; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /t/b_idx/NULL/2 -> NULL
output row: [2 NULL NULL NULL]
fetched: /t/b_idx/NULL/3 -> NULL
output row: [3 NULL NULL NULL]
fetched: /t/b_idx/2/1/c/d -> /3/4
output row: [1 2 3 4]

# Regression test for #14601.

statement ok
CREATE TABLE t14601 (a STRING, b BOOL)

statement ok
CREATE INDEX i14601 ON t14601 (a) STORING (b)

query TTT
EXPLAIN SELECT a FROM t14601 ORDER BY a
----
scan  ·      ·
·     table  t14601@i14601
·     spans  ALL

# Updates were broken too.

statement ok
CREATE TABLE t14601a (
  a STRING,
  b BOOL,
  c INT,
  FAMILY f1 (a),
  FAMILY f2 (b),
  FAMILY f3 (c)
)

statement ok
CREATE INDEX i14601a ON t14601a (a) STORING (b, c)

query TTT
EXPLAIN SELECT a, b FROM t14601a ORDER BY a
----
scan  ·      ·
·     table  t14601a@i14601a
·     spans  ALL

statement ok
DROP index i14601a

statement ok
CREATE UNIQUE INDEX i14601a ON t14601a (a) STORING (b)

query TTT
EXPLAIN SELECT a, b FROM t14601a ORDER BY a
----
scan  ·      ·
·     table  t14601a@i14601a
·     spans  ALL

statement ok
DROP TABLE t; DROP TABLE t14601; DROP TABLE t14601a

# ------------------------------------------------------------------------------
# String inequality filter.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE c (n INT PRIMARY KEY, str STRING, INDEX str(str DESC));

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM c WHERE str >= 'moo'
----
scan  ·      ·                  (n, str)  ·
·     table  c@str              ·         ·
·     spans  -/"moo"/PrefixEnd  ·         ·

statement ok
DROP TABLE c

# ------------------------------------------------------------------------------
# "*" must expand to zero columns if there are zero columns to select.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE nocols(x INT); ALTER TABLE nocols DROP COLUMN x

query TTTTT
EXPLAIN (VERBOSE) SELECT 1 AS a, * FROM nocols
----
render     ·         ·               (a)  ·
 │         render 0  1               ·    ·
 └── scan  ·         ·               ()   ·
·          table     nocols@primary  ·    ·
·          spans     ALL             ·    ·

statement ok
DROP TABLE nocols

# ------------------------------------------------------------------------------
# Ensure that index is used when indexed column has collation.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE coll (
  a STRING COLLATE da,
  b INT,
  c BOOL,
  PRIMARY KEY (a, b),
  INDEX (b, a) STORING (c)
)

query TTTTT
EXPLAIN (TYPES) SELECT a, b FROM coll ORDER BY a, b
----
scan  ·      ·             (a collatedstring{da}, b int)  +a,+b
·     table  coll@primary  ·                              ·
·     spans  ALL           ·                              ·

query TTTTT
EXPLAIN (TYPES) SELECT b, a FROM coll ORDER BY b, a
----
render     ·         ·                        (b int, a collatedstring{da})  ·
 │         render 0  (b)[int]                 ·                              ·
 │         render 1  (a)[collatedstring{da}]  ·                              ·
 └── scan  ·         ·                        (a collatedstring{da}, b int)  +b,+a
·          table     coll@coll_b_a_idx        ·                              ·
·          spans     ALL                      ·                              ·

statement ok
DROP TABLE coll

# ------------------------------------------------------------------------------
# Ensure correct index is used when indexed column is computed.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE computed (
  k INT PRIMARY KEY,
  a JSON,
  b TEXT AS (a->>'q') STORED,
  INDEX (b)
)

query TTTTT
EXPLAIN (TYPES) SELECT b FROM computed ORDER BY b
----
scan  ·      ·                        (b string)  +b
·     table  computed@computed_b_idx  ·           ·
·     spans  ALL                      ·           ·

statement ok
DROP TABLE computed

# ------------------------------------------------------------------------------
# Ensure that Select filter probes expected date/time key/values that are in
# different column families.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE dt (
  a TIMESTAMP PRIMARY KEY,
  b DATE,
  c INTERVAL,
  UNIQUE (b),
  UNIQUE (c),
  FAMILY (a),
  FAMILY (b),
  FAMILY (c)
)

statement ok
INSERT INTO dt VALUES
  ('2015-08-30 03:34:45.34567', '2015-08-30', '34h2s'),
  ('2015-08-25 04:45:45.53453', '2015-08-25', '2h45m2s234ms'),
  ('2015-08-29 23:10:09.98763', '2015-08-29', '234h45m2s234ms')

statement ok
SET tracing = on,kv,results; SELECT * FROM dt WHERE a = '2015-08-25 04:45:45.53453+02:00'::timestamp; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /dt/primary/'2015-08-25 04:45:45.53453+00:00' -> NULL
fetched: /dt/primary/'2015-08-25 04:45:45.53453+00:00'/b -> '2015-08-25'
fetched: /dt/primary/'2015-08-25 04:45:45.53453+00:00'/c -> '2h45m2s234ms'
output row: ['2015-08-25 04:45:45.53453+00:00' '2015-08-25' '2h45m2s234ms']

statement ok
SET tracing = on,kv,results; SELECT b FROM dt WHERE b < '2015-08-29'::date; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /dt/dt_b_key/'2015-08-25' -> /'2015-08-25 04:45:45.53453+00:00'
output row: ['2015-08-25']

statement ok
SET tracing = on,kv,results; SELECT c FROM dt WHERE c < '234h45m2s234ms'::interval; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /dt/dt_c_key/'2h45m2s234ms' -> /'2015-08-25 04:45:45.53453+00:00'
output row: ['2h45m2s234ms']
fetched: /dt/dt_c_key/'34h2s' -> /'2015-08-30 03:34:45.34567+00:00'
output row: ['34h2s']

statement ok
DROP TABLE dt

# ------------------------------------------------------------------------------
# Ensure that decimal values result in correct scan spans.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE dec (d decimal, v decimal(3, 1), primary key (d, v))

query TTTTT
EXPLAIN (TYPES) SELECT * FROM dec WHERE d IS NaN and v IS NaN
----
scan  ·      ·                    (d decimal, v decimal)  ·
·     table  dec@primary          ·                       ·
·     spans  /NaN/NaN-/NaN/NaN/#  ·                       ·

# The NaN suffix is decimalNaNDesc, not decimalNaN(Asc).
query TTTTT
EXPLAIN (TYPES) SELECT * FROM dec WHERE d = 'Infinity' and v = 'Infinity'
----
scan  ·      ·                                        (d decimal, v decimal)  ·
·     table  dec@primary                              ·                       ·
·     spans  /Infinity/Infinity-/Infinity/Infinity/#  ·                       ·

query TTTTT
EXPLAIN (TYPES) SELECT * FROM dec WHERE d = '-Infinity' and v = '-Infinity'
----
scan  ·      ·                                            (d decimal, v decimal)  ·
·     table  dec@primary                                  ·                       ·
·     spans  /-Infinity/-Infinity-/-Infinity/-Infinity/#  ·                       ·

statement ok
DROP TABLE dec

# Test composite encoding of DECIMAL type in indexes.
statement ok
CREATE TABLE c (
  a INT PRIMARY KEY,
  b DECIMAL(2,2),
  INDEX b_idx (b)
)

statement ok
INSERT INTO c VALUES(1, 0.4)

# Test that unspecifying b is like specifying NULL.
statement ok
INSERT INTO c (a) VALUES(2)

statement ok
INSERT INTO c VALUES(3)

statement ok
SET tracing = on,kv,results; SELECT * FROM c@b_idx; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /c/b_idx/NULL/2 -> NULL
output row: [2 NULL]
fetched: /c/b_idx/NULL/3 -> NULL
output row: [3 NULL]
fetched: /c/b_idx/0.4/1/b -> /0.40
output row: [1 0.40]

# ------------------------------------------------------------------------------
# Verify that lookups for Decimal NaN use indices when possible:
# - `WHERE d IS NaN` should perform a point lookup.
# - `WHERE d = 'NaN'` should also perform a point lookup.
# - `WHERE isnan(d)` is a function so it can't perform a point lookup.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE dec2 (d decimal null, index (d))

query TTTTT
EXPLAIN (TYPES) SELECT * FROM dec2 WHERE d IS NaN
----
scan  ·      ·                (d decimal)  ·
·     table  dec2@dec2_d_idx  ·            ·
·     spans  /NaN-/-Infinity  ·            ·

query TTTTT
EXPLAIN (TYPES) SELECT * FROM dec2 WHERE d = 'NaN'
----
scan  ·      ·                (d decimal)  ·
·     table  dec2@dec2_d_idx  ·            ·
·     spans  /NaN-/-Infinity  ·            ·

query TTTTT
EXPLAIN (TYPES) SELECT * FROM dec2 WHERE isnan(d)
----
scan  ·       ·                            (d decimal)  ·
·     table   dec2@primary                 ·            ·
·     spans   ALL                          ·            ·
·     filter  (isnan((d)[decimal]))[bool]  ·            ·

statement ok
DROP TABLE dec2

# ------------------------------------------------------------------------------
# Verify that lookups for Float NaN use indices when possible:
# - `WHERE f IS NaN` should perform a point lookup.
# - `WHERE f = 'NaN'` should also perform a point lookup.
# - `WHERE isnan(f)` is a function so it can't perform a point lookup.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE flt (f float null, unique index (f))

query TTTTT
EXPLAIN (TYPES) SELECT * FROM flt WHERE f IS NaN
----
scan  ·      ·                    (f float)  ·
·     table  flt@flt_f_key        ·          ·
·     spans  /NaN-/NaN/PrefixEnd  ·          ·

query TTTTT
EXPLAIN (TYPES) SELECT * FROM flt WHERE f = 'NaN'
----
scan  ·      ·                    (f float)  ·
·     table  flt@flt_f_key        ·          ·
·     spans  /NaN-/NaN/PrefixEnd  ·          ·

query TTTTT
EXPLAIN (TYPES) SELECT * FROM flt WHERE isnan(f)
----
scan  ·       ·                          (f float)  ·
·     table   flt@primary                ·          ·
·     spans   ALL                        ·          ·
·     filter  (isnan((f)[float]))[bool]  ·          ·

statement ok
DROP TABLE flt

# ------------------------------------------------------------------------------
# Verify we create the correct spans for negative numbers with extra
# operations.
# ------------------------------------------------------------------------------

statement ok
CREATE TABLE num (
  i int null,
  unique index (i),
  f float null,
  unique index (f),
  d decimal null,
  unique index (d),
  n interval null,
  unique index (n)
)

query TTTTT
EXPLAIN (TYPES) SELECT i FROM num WHERE i = -1:::INT
----
scan  ·      ·              (i int)  ·
·     table  num@num_i_key  ·        ·
·     spans  /-1-/0         ·        ·

query TTTTT
EXPLAIN (TYPES) SELECT f FROM num WHERE f = -1:::FLOAT
----
scan  ·      ·                  (f float)  ·
·     table  num@num_f_key      ·          ·
·     spans  /-1-/-1/PrefixEnd  ·          ·

query TTTTT
EXPLAIN (TYPES) SELECT d FROM num WHERE d = -1:::DECIMAL
----
scan  ·      ·                  (d decimal)  ·
·     table  num@num_d_key      ·            ·
·     spans  /-1-/-1/PrefixEnd  ·            ·

query TTTTT
EXPLAIN (TYPES) SELECT n FROM num WHERE n = -'1h':::INTERVAL
----
scan  ·      ·              (n interval)  ·
·     table  num@num_n_key  ·             ·
·     spans  /-1h-/1d-25h   ·             ·

statement ok
DROP TABLE num

# ------------------------------------------------------------------------------
# ANY, ALL tests.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE abc (a INT, b INT, C INT)

statement ok
INSERT INTO abc VALUES (1, 10, 100), (2, 20, 200), (3, 30, 300)

query III
SELECT * FROM abc WHERE a = ANY(SELECT a FROM abc WHERE b = 10)
----
1 10 100

query III
SELECT * FROM abc WHERE a < ANY(SELECT a FROM abc WHERE b = 30) ORDER BY a
----
1 10 100
2 20 200

query III
SELECT * FROM abc WHERE a > ANY(SELECT a FROM abc WHERE b = 30)
----

query III
SELECT * FROM abc WHERE a < ALL(SELECT b FROM abc) ORDER BY a
----
1 10 100
2 20 200
3 30 300

query III
SELECT * FROM abc WHERE a < ALL(SELECT a FROM abc WHERE a >= 2)
----
1 10 100

query III
SELECT * FROM abc WHERE a < ALL(SELECT a FROM abc)
----

statement ok
DROP TABLE abc

# ------------------------------------------------------------------------------
# IN tests.
# ------------------------------------------------------------------------------
# Regression tests for #22670.
query B
SELECT 1 IN (1, 2)
----
true

query B
SELECT NULL IN (1, 2)
----
NULL

query B
SELECT 1 IN (1, NULL)
----
true

query B
SELECT 1 IN (NULL, 2)
----
NULL

query B
SELECT (1, NULL) IN ((1, 1))
----
NULL

query B
SELECT (2, NULL) IN ((1, 1))
----
false

query B
SELECT (1, 1) IN ((1, NULL))
----
NULL

query B
SELECT (1, 1) IN ((2, NULL))
----
false

# Tests with a tuple coming from a subquery.
query B
SELECT NULL::int IN (SELECT * FROM (VALUES (1)) AS t(a))
----
NULL

query B
SELECT (1, NULL::int) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b))
----
NULL

query B
SELECT (2, NULL::int) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b))
----
false

query B
SELECT (NULL::int, 1) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b))
----
NULL

query B
SELECT (NULL::int, 2) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b))
----
false

query B
SELECT (NULL::int, NULL::int) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b))
----
NULL

query B
SELECT NULL::int NOT IN (SELECT * FROM (VALUES (1)) AS t(a))
----
NULL

query B
SELECT (1, NULL::int) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b))
----
NULL

query B
SELECT (2, NULL::int) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b))
----
true

query B
SELECT (NULL::int, 1) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b))
----
NULL

query B
SELECT (NULL::int, 2) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b))
----
true

query B
SELECT (NULL::int, NULL::int) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b))
----
NULL

# Tests with an empty IN tuple.
query B
SELECT NULL::int IN (SELECT * FROM (VALUES (1)) AS t(a) WHERE a > 1)
----
false

query B
SELECT (1, NULL::int) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1)
----
false

query B
SELECT (NULL::int, 1) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1)
----
false

query B
SELECT (NULL::int, NULL::int) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1)
----
false

query B
SELECT NULL::int NOT IN (SELECT * FROM (VALUES (1)) AS t(a) WHERE a > 1)
----
true

query B
SELECT (1, NULL::int) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1)
----
true

query B
SELECT (NULL::int, 1) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1)
----
true

query B
SELECT (NULL::int, NULL::int) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1)
----
true

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

# Ensure that (non-top-level) render nodes get populated with the correct ordering.
query TTTTT
EXPLAIN (VERBOSE) SELECT a + x FROM (SELECT a, b + c AS x FROM abcd) ORDER BY a
----
render          ·         ·             ("?column?")  ·
 │              render 0  a + x         ·             ·
 └── render     ·         ·             (x, a)        +a
      │         render 0  b + c         ·             ·
      │         render 1  a             ·             ·
      └── scan  ·         ·             (a, b, c)     +a
·               table     abcd@primary  ·             ·
·               spans     ALL           ·             ·

query TTTTT
EXPLAIN (VERBOSE) SELECT a + x FROM (SELECT a, b, a + b + c AS x FROM abcd) ORDER BY b
----
render               ·         ·                  ("?column?")     ·
 │                   render 0  "?column?"         ·                ·
 └── sort            ·         ·                  ("?column?", b)  +b
      │              order     +b                 ·                ·
      └── render     ·         ·                  ("?column?", b)  ·
           │         render 0  a + (c + (a + b))  ·                ·
           │         render 1  b                  ·                ·
           └── scan  ·         ·                  (a, b, c)        ·
·                    table     abcd@primary       ·                ·
·                    spans     ALL                ·                ·


query TTTTT
EXPLAIN (VERBOSE) SELECT a + x FROM (SELECT a, b, a + b + c AS x FROM abcd) ORDER BY a DESC, b DESC
----
render             ·         ·             ("?column?")  ·
 │                 render 0  a + x         ·             ·
 └── render        ·         ·             (x, a, b)     -a,-b
      │            render 0  c + (a + b)   ·             ·
      │            render 1  a             ·             ·
      │            render 2  b             ·             ·
      └── revscan  ·         ·             (a, b, c)     -a,-b
·                  table     abcd@primary  ·             ·
·                  spans     ALL           ·             ·

# Ensure that filter nodes (and filtered scan nodes) get populated with the correct ordering.
query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM abcd WHERE a > b ORDER BY a
----
scan  ·       ·             (a, b, c, d)  +a
·     table   abcd@primary  ·             ·
·     spans   ALL           ·             ·
·     filter  a > b         ·             ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM abcd WHERE a > b ORDER BY a DESC, b DESC
----
sort       ·       ·             (a, b, c, d)  -a,-b
 │         order   -a,-b         ·             ·
 └── scan  ·       ·             (a, b, c, d)  ·
·          table   abcd@primary  ·             ·
·          spans   ALL           ·             ·
·          filter  a > b         ·             ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM (SELECT a, b FROM abcd LIMIT 10) WHERE a > b ORDER BY a
----
filter     ·       ·             (a, b)  +a
 │         filter  a > b         ·       ·
 └── scan  ·       ·             (a, b)  +a
·          table   abcd@primary  ·       ·
·          spans   ALL           ·       ·
·          limit   10            ·       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM (SELECT a, a+b+c AS x FROM (SELECT * FROM abcd LIMIT 10)) WHERE x > 100 ORDER BY a
----
render          ·         ·                    (a, x)     ·
 │              render 0  a                    ·          ·
 │              render 1  c + (a + b)          ·          ·
 └── filter     ·         ·                    (a, b, c)  +a
      │         filter    (c + (a + b)) > 100  ·          ·
      └── scan  ·         ·                    (a, b, c)  +a
·               table     abcd@primary         ·          ·
·               spans     ALL                  ·          ·
·               limit     10                   ·          ·
