# LogicTest: local

# ------------------------------------------------------------------------------
# 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
----
render     ·      ·
 └── 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
----
render     ·      ·
 └── 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
----
render     ·      ·
 └── scan  ·      ·
·          table  t14601a@i14601a
·          spans  ALL

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

# ------------------------------------------------------------------------------
# Ensure that correct 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 TTT
EXPLAIN SELECT a, b FROM coll ORDER BY a, b
----
render     ·      ·
 └── scan  ·      ·
·          table  coll@primary
·          spans  ALL

query TTT
EXPLAIN SELECT b, a FROM coll ORDER BY b, a
----
render     ·      ·
 └── scan  ·      ·
·          table  coll@coll_b_a_idx
·          spans  ALL

# ------------------------------------------------------------------------------
# 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 TTT
EXPLAIN SELECT b FROM computed ORDER BY b
----
render     ·      ·
 └── scan  ·      ·
·          table  computed@computed_b_idx
·          spans  ALL

# ------------------------------------------------------------------------------
# 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']

# ------------------------------------------------------------------------------
# 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 TTT
EXPLAIN SELECT * FROM dec WHERE d IS NaN and v IS NaN
----
scan  ·      ·
·     table  dec@primary
·     spans  /NaN/NaN-/NaN/NaN/#

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

query TTT
EXPLAIN SELECT * FROM dec WHERE d = '-Infinity' and v = '-Infinity'
----
scan  ·      ·
·     table  dec@primary
·     spans  /-Infinity/-Infinity-/-Infinity/-Infinity/#

# 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 TTT
EXPLAIN SELECT * FROM dec2 WHERE d IS NaN
----
render     ·      ·
 └── scan  ·      ·
·          table  dec2@dec2_d_idx
·          spans  /NaN-/-Infinity

query TTT
EXPLAIN SELECT * FROM dec2 WHERE d = 'NaN'
----
render     ·      ·
 └── scan  ·      ·
·          table  dec2@dec2_d_idx
·          spans  /NaN-/-Infinity

query TTT
EXPLAIN SELECT * FROM dec2 WHERE isnan(d)
----
render     ·       ·
 └── scan  ·       ·
·          table   dec2@dec2_d_idx
·          spans   ALL
·          filter  isnan(d)

# ------------------------------------------------------------------------------
# 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 TTT
EXPLAIN SELECT * FROM flt WHERE f IS NaN
----
render     ·      ·
 └── scan  ·      ·
·          table  flt@flt_f_key
·          spans  /NaN-/NaN/PrefixEnd

query TTT
EXPLAIN SELECT * FROM flt WHERE f = 'NaN'
----
render     ·      ·
 └── scan  ·      ·
·          table  flt@flt_f_key
·          spans  /NaN-/NaN/PrefixEnd

query TTT
EXPLAIN SELECT * FROM flt WHERE isnan(f)
----
render     ·       ·
 └── scan  ·       ·
·          table   flt@flt_f_key
·          spans   ALL
·          filter  isnan(f)
