# LogicTest: 5node

# 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)
)

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

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

statement ok
CREATE TABLE bytes_t (a BYTES PRIMARY KEY)

statement ok
CREATE TABLE decimal_t (a DECIMAL PRIMARY KEY)

############################
# 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.

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)

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

query TTTI colnames
SELECT start_key, end_key, replicas, lease_holder from [SHOW RANGES FROM TABLE p1 WITH DETAILS]
ORDER BY lease_holder, start_key
----
start_key           end_key                   replicas  lease_holder
<before:/Table/72>  …/1/2                     {1}       1
…/1/2               …/2/0                     {3}       3
…/2/0               …/2/2                     {4}       4
…/2/2               <after:/Table/107/1/2/1>  {5}       5

# Indexes

query TTTI colnames
SELECT start_key, end_key, replicas, lease_holder from [SHOW RANGES FROM INDEX b WITH DETAILS]
ORDER BY lease_holder, start_key
----
start_key                end_key                   replicas  lease_holder
<before:/Table/106/1/2>  …/0                       {3}       3
…/0                      …/2                       {4}       4
…/2                      <after:/Table/107/1/2/1>  {5}       5

query TTTI colnames
SELECT start_key, end_key, replicas, lease_holder from [SHOW RANGES FROM TABLE p2 WITH DETAILS]
ORDER BY lease_holder, start_key
----
start_key                  end_key       replicas  lease_holder
<before:/Table/107/1/2/1>  …/1/0         {1}       1
…/1/0                      …/1/2         {1}       1
…/2                        …/2/2         {1}       1
…/2/2                      …/3           {1}       1
…/3                        <after:/Max>  {1}       1
…/1/2                      …/2           {3}       3

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

# p1 table

# Secondary index should not be tightened.
query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p1 WHERE b <= 3] WHERE info LIKE '%spans%'
----
  spans: -/4

# Partial predicate on primary key should not be tightened.
query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p1 WHERE a <= 3] WHERE info LIKE '%spans%'
----
  spans: -/4

# Tighten end key if span contains full primary key.
query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p1 WHERE a <= 3 AND b <= 3] WHERE info LIKE '%spans%'
----
      spans: -/3/4

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p1 WHERE a <= 3 AND b < 4] WHERE info LIKE '%spans%'
----
      spans: -/3/4

# Mixed bounds.
query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p1 WHERE a >= 2 AND b <= 3] WHERE info LIKE '%spans%'
----
      spans: /2-

# Edge cases.

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p1 WHERE a <= 0 AND b <= 0] WHERE info LIKE '%spans%'
----
      spans: -/0/1

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p1 WHERE a <= -1 AND b <= -1] WHERE info LIKE '%spans%'
----
      spans: -/-1/0

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p1 WHERE a = 1 AND b <= -9223372036854775808] WHERE info LIKE '%spans%'
----
  spans: /1-/1/-9223372036854775807

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p1 WHERE a = 1 AND b <= 9223372036854775807] WHERE info LIKE '%spans%'
----
  spans: /1-/1/9223372036854775807/PrefixEnd

# Partial primary key does not tighten.

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM c1 WHERE a <= 3] WHERE info LIKE '%spans%'
----
  spans: -/4

# Tighten span on fully primary key.
query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM c1 WHERE a <= 3 AND b <= 3] WHERE info LIKE '%spans%'
----
      spans: -/3/4

# From the primary index.

# Lower bound (i >= 2)
query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p2 WHERE i >= 2] WHERE info LIKE '%spans%'
----
  spans: /2-

# Upper bound (i <= 5)

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p2 WHERE i <= 5] WHERE info LIKE '%spans%'
----
  spans: -/6

# Lower bound (i >= 1 AND d >= 2)

# Note 53/2 refers to the 2nd index (after primary index) of table p2.
query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p2@p2_id WHERE i >= 1 AND d >= 2] WHERE info LIKE '%spans%'
----
      spans: /1/2-

# Upper bound (i <= 6 AND d <= 5)

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p2@p2_id WHERE i <= 6 AND d <= 5] WHERE info LIKE '%spans%'
----
      spans: -/6/6

# IS NULL

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p2@p2_id WHERE i >= 1 AND d IS NULL] WHERE info LIKE '%spans%'
----
      spans: /1/NULL-

# IS NOT NULL

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM p2@p2_id WHERE i >= 1 AND d IS NOT NULL] WHERE info LIKE '%spans%'
----
      spans: /1/!NULL-

# String table

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM bytes_t WHERE a = 'a'] WHERE info LIKE '%spans%'
----
  spans: /"a"/0

# No tightening.

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM bytes_t WHERE a < 'aa'] WHERE info LIKE '%spans%'
----
  spans: -/"aa"

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM decimal_t WHERE a = 1.00] WHERE info LIKE '%spans%'
----
  spans: /1/0

# No tightening.

query T
SELECT info FROM [EXPLAIN (VERBOSE) SELECT * FROM decimal_t WHERE a < 2] WHERE info LIKE '%spans%'
----
  spans: -/2
