# LogicTest: 5node-dist 5node-dist-opt 5node-dist-metadata

# This test verifies that we correctly tighten spans during index selection as
# well as after partitioning spans in distsql.

################
# Schema setup #
################

statement ok
CREATE TABLE p1 (
  a INT,
  b INT,
  PRIMARY KEY (a, b),
  INDEX b (b)
)

statement ok
CREATE TABLE c1 (
  a INT,
  b INT,
  PRIMARY KEY (a,b)
) INTERLEAVE IN PARENT p1 (a, b)

statement ok
CREATE TABLE p2 (
  i INT PRIMARY KEY,
  d INT
)

statement ok
CREATE INDEX p2_id ON p2 (i, d) INTERLEAVE IN PARENT p2 (i)

statement ok
CREATE TABLE bytes_t (a BYTES PRIMARY KEY)

statement ok
CREATE TABLE decimal_t (a DECIMAL PRIMARY KEY)

#######################
# Insert dummy values #
#######################

statement ok
INSERT INTO p1 VALUES
  (1,10),
  (2,1),
  (2,2),
  (2,8),
  (3,5),
  (3,10),
  (4,1),
  (4,2),
  (4,4)

statement ok
INSERT INTO c1 VALUES
  (1,10),
  (2,1),
  (2,4),
  (2,8),
  (2,10),
  (4,2)

statement ok
INSERT INTO p2 VALUES
  (1, NULL),
  (2, 2),
  (3, 1),
  (4, NULL),
  (5, NULL),
  (6, 10),
  (7, 2),
  (8, 3)

statement ok
INSERT INTO bytes_t VALUES
  ('a'),
  ('aa'),
  ('b'),
  ('c'),
  ('ca')

statement ok
INSERT INTO decimal_t VALUES
  (1),
  (1.000001),
  (1.5),
  (2),
  (2.001)

############################
# Split ranges for distsql #
############################

# Perform some splits to exercise distsql partitioning as well.

# Create split points at X = 2.
# Also split at the beginning of each index (0 for ASC, 100 for DESC) to
# prevent interfering with previous indexes/tables.

# Prevent the merge queue from immediately discarding our splits.
statement ok
SET CLUSTER SETTING kv.range_merge.queue_enabled = false;

# p1 table (interleaved index)
statement ok
ALTER TABLE p1 SPLIT AT VALUES(2)

# Create a split at /2/#
statement ok
ALTER TABLE c1 SPLIT AT VALUES(2,1)

# Split index
statement ok
ALTER INDEX b SPLIT AT VALUES(0)

statement ok
ALTER INDEX b SPLIT AT VALUES(2)

# p2 table (interleaved index)
statement ok
ALTER TABLE p2 SPLIT AT VALUES(0)

statement ok
ALTER TABLE p2 SPLIT AT VALUES(2)

# Create a split at /2/#
statement ok
ALTER INDEX p2_id SPLIT AT VALUES(2)

#####################
# Distribute ranges #
#####################

# Distribute our ranges across the first 3 (for primary index) and last 2
# (for seconary indexes) nodes.

statement ok
ALTER TABLE p1 EXPERIMENTAL_RELOCATE SELECT ARRAY[i], i FROM generate_series(1,3) AS g(i)

statement ok
ALTER INDEX b EXPERIMENTAL_RELOCATE SELECT ARRAY[i+3], i FROM generate_series(1,2) AS g(i)

# Interleaved index table
statement ok
ALTER TABLE p2 EXPERIMENTAL_RELOCATE SELECT ARRAY[i], i FROM generate_series(1,3) as g(i)

#############################
# Verify range distribution #
#############################

# p1 table (interleaved table)

query TTITI colnames
SHOW EXPERIMENTAL_RANGES FROM TABLE p1
----
start_key    end_key      range_id  replicas  lease_holder
NULL         /2           1         {1}       1
/2           /2/1/#/54/1  2         {2}       2
/2/1/#/54/1  NULL         3         {3}       3

# Indexes

query TTITI colnames
SHOW EXPERIMENTAL_RANGES FROM INDEX b
----
start_key  end_key  range_id  replicas  lease_holder
NULL       /0       3         {3}       3
/0         /2       4         {4}       4
/2         NULL     5         {5}       5

# p2 table (interleaved index)

query TTITI colnames
SHOW EXPERIMENTAL_RANGES FROM TABLE p2
----
start_key  end_key    range_id  replicas  lease_holder
NULL       /0         5         {5}       5
/0         /2         6         {1}       1
/2         /2/#/55/2  7         {2}       2
/2/#/55/2  NULL       8         {3}       3

###############
# Query tests #
###############

# p1 table

# Secondary index should not be tightened.
query II rowsort
SELECT * FROM p1 WHERE b <= 3
----
2 1
2 2
4 1
4 2

# Partial predicate on primary key should not be tightened.
query II rowsort
SELECT * FROM p1 WHERE a <= 3
----
1 10
2 1
2 2
2 8
3 5
3 10

# Tighten end key if span contains full primary key.
query II rowsort
SELECT * FROM p1 WHERE a <= 3 AND b <= 3
----
2 1
2 2

# Mixed bounds.
query II rowsort
SELECT * FROM p1 WHERE a >= 2 AND b <= 3
----
2 1
2 2
4 1
4 2

query II rowsort
SELECT * FROM c1 WHERE a <= 3
----
1 10
2 1
2 4
2 8
2 10

# Tighten span on fully primary key.
query II rowsort
SELECT * FROM c1 WHERE a <= 3 AND b <= 3
----
2 1

# Table p2 with interleaved index.

# From the primary index.

# Lower bound (i >= 2)
query II rowsort
SELECT * FROM p2 WHERE i>= 2
----
2 2
3 1
4 NULL
5 NULL
6 10
7 2
8 3

# Upper bound (i <= 5)

query II rowsort
SELECT * FROM p2 WHERE i <= 5
----
1 NULL
2 2
3 1
4 NULL
5 NULL

# From the interleaved index: no tightening at all.

# Lower bound (i >= 1 AND d >= 2)
query II rowsort
SELECT * FROM p2@p2_id WHERE i>= 1 AND d >= 2
----
2 2
6 10
7 2
8 3

# Upper bound (i <= 6 AND d <= 5)
query II rowsort
SELECT * FROM p2@p2_id WHERE i <= 6 AND d <= 5
----
2 2
3 1

# IS NULL
query II rowsort
SELECT * FROM p2@p2_id WHERE i>= 1 AND d IS NULL
----
1 NULL
4 NULL
5 NULL

# IS NOT NULL
query II rowsort
SELECT * FROM p2@p2_id WHERE i>= 1 AND d IS NOT NULL
----
2 2
3 1
6 10
7 2
8 3

# String table
query T
SELECT * FROM bytes_t WHERE a = 'a'
----
a

# No tightening.
query T
SELECT * FROM bytes_t WHERE a < 'aa'
----
a

query R
SELECT * FROM decimal_t WHERE a = 1.00
----
1

# No tightening.

query R rowsort
SELECT * FROM decimal_t WHERE a < 2
----
1
1.000001
1.5
