# Tests with a type that doesn't support Prev.
index-constraints vars=(a string) index=(a)
a > 'a' AND a < 'z'
----
[/e'a\x00' - /'z')

index-constraints vars=(a string, b int) index=(a, b)
a > 'a' AND a < 'z' AND b = 5
----
[/e'a\x00'/5 - /'z')
Remaining filter: b = 5

index-constraints vars=(a string) index=(a desc)
a > 'a' AND a < 'z'
----
(/'z' - /e'a\x00']

index-constraints vars=(a string, b int) index=(a desc, b)
a > 'a' AND a < 'z' AND b = 5
----
(/'z' - /e'a\x00'/5]
Remaining filter: b = 5

# Tests with a type that doesn't support Next or Prev.
index-constraints vars=(a decimal) index=(a)
a > 1.5
----
(/1.5 - ]

index-constraints vars=(a decimal) index=(a)
a > 1.5 AND a < 2
----
(/1.5 - /2)

index-constraints vars=(a decimal not null, b decimal not null) index=(a, b)
a <= 1.5 AND b < 2.5
----
[ - /1.5/2.5)
Remaining filter: b < 2.5

# Tests with a type that supports Next/Prev but we have a maximal/minimal value.
index-constraints vars=(a bool) index=(a)
a > true
----
(/true - ]

index-constraints vars=(a bool) index=(a)
a < false
----
(/NULL - /false)

# Note the difference here between decimal and int: we
# can't extend the exclusive start key.
index-constraints vars=(a decimal, b decimal) index=(a, b)
a > 1.5 AND b > 2
----
(/1.5 - ]
Remaining filter: b > 2

index-constraints vars=(a int) index=(a)
a IS NULL
----
[/NULL - /NULL]

index-constraints vars=(a int not null) index=(a)
a IS NOT DISTINCT FROM 1
----
[/1 - /1]

index-constraints vars=(a int, b int) index=(a, b)
b = a
----
(/NULL - ]
Remaining filter: b = a

index-constraints vars=(a int, b int) index=(a, b)
b < a
----
(/NULL - ]
Remaining filter: b < a

index-constraints vars=(a int not null, b int) index=(a, b)
a = b
----
[ - ]
Remaining filter: a = b

# Tests with top-level OR.
# TODO(radu): expression simplification is limited when dealing with ORs; some
# of the remaining filters below are not necessary (or could be simplified
# further).

index-constraints vars=(a int) index=(a)
a = 1 OR a = 2
----
[/1 - /2]

index-constraints vars=(a int) index=(a)
a IS NULL OR a = 1
----
[/NULL - /NULL]
[/1 - /1]

index-constraints vars=(a int) index=(a)
(a >= 1 AND a <= 5) OR (a >= 2 AND a <= 8)
----
[/1 - /8]

index-constraints vars=(a int) index=(a)
(a >= 1 AND a <= 3) OR (a >= 5 AND a <= 8)
----
[/1 - /3]
[/5 - /8]

index-constraints vars=(a int, b int) index=(a)
(a = 1 AND b = 5) OR (a = 2 and b = 6)
----
[/1 - /2]
Remaining filter: ((a = 1) AND (b = 5)) OR ((a = 2) AND (b = 6))

index-constraints vars=(a int, b int) index=(b)
(a = 1 AND b = 5) OR (a = 2 and b = 6)
----
[/5 - /6]
Remaining filter: ((a = 1) AND (b = 5)) OR ((a = 2) AND (b = 6))

index-constraints vars=(a int, b int) index=(b)
a = 1 OR b = 2
----
[ - ]
Remaining filter: (a = 1) OR (b = 2)

index-constraints vars=(a int, b int, c int) index=(a, b, c)
a = 1 OR (a, b, c) IN ((4, 5, 6), (7, 8, 9))
----
[/1 - /1]
[/4/5/6 - /4/5/6]
[/7/8/9 - /7/8/9]

index-constraints vars=(a int, b int, c int) index=(a, b, c)
a = 1 OR (a = 2 AND (b, c) IN ((4, 5), (6, 7))) OR (a = 3)
----
[/1 - /1]
[/2/4/5 - /2/4/5]
[/2/6/7 - /2/6/7]
[/3 - /3]

# Tests with inner OR.

index-constraints vars=(a int, b int) index=(a, b)
a = 1 AND (b = 2 OR b = 3)
----
[/1/2 - /1/3]

index-constraints vars=(a int, b int, c int) index=(a, b, c)
a = 1 AND (b = 2 OR (b = 3 AND c = 4))
----
[/1/2 - /1/2]
[/1/3/4 - /1/3/4]

index-constraints vars=(a int, b int) index=(a, b)
a >= 1 AND (b = 2 OR b = 3)
----
[/1/2 - ]
Remaining filter: (b = 2) OR (b = 3)

index-constraints vars=(a int, b int, c int) index=(a, b, c)
a = 1 AND (b = 2 OR b = 3) AND (c >= 4)
----
[/1/2/4 - /1/2]
[/1/3/4 - /1/3]

index-constraints vars=(a int, b int, c int) index=(a, b, c)
a = 1 AND b = CASE WHEN c = 2 THEN 1 ELSE 2 END
----
(/1/NULL - /1]
Remaining filter: b = CASE WHEN c = 2 THEN 1 ELSE 2 END

index-constraints vars=(a int, b int) index=(a, b)
a = 1 AND b IS OF (INT)
----
[/1 - /1]

# This testcase exposed an issue around extending spans. We don't normalize the
# expression so we have a hierarchy of ANDs (which requires a more complex path
# for calculating spans). As a side-effect of disabling normalization, an
# unnecessary filter remains.
index-constraints vars=(a int, b int, c int, d int) index=(a, b, c, d) nonormalize
a = 1 AND b = 2 AND c = 3 AND d IN (4,5,6)
----
[/1/2/3/4 - /1/2/3/6]

index-constraints vars=(a int, b int) index=(a, b)
(a = 1) AND (b > 5) AND (b < 1)
----

# Verify that we ignore mixed-type comparisons (they would result in incorrect
# encodings, see #4313). We don't have testcases for IN because those error
# out early (during type-checking).
index-constraints vars=(a int) index=(a)
a = 1.5
----
(/NULL - ]
Remaining filter: a = 1.5

index-constraints vars=(a int) index=(a)
a > 1.5
----
(/NULL - ]
Remaining filter: a > 1.5

index-constraints vars=(a int, b int) index=(a, b)
(a, b) = (1, 2.5)
----
(/1/NULL - /1]
Remaining filter: b = 2.5

index-constraints vars=(a int, b int) index=(a, b)
(a, b) >= (1, 2.5)
----
[/1 - ]
Remaining filter: (a, b) >= (1, 2.5)

# Verify that we ignore spans that become invalid after extension.
index-constraints vars=(a int, b int) index=(a, b)
a >= 1 AND (a, b) < (1, 2) AND b = 5
----

index-constraints vars=(a int, b int) index=(a, b)
(a >= 1 AND (a, b) < (1, 2) OR a > 3) AND b = 5
----
[/4/5 - ]
Remaining filter: b = 5

# Regression test for #3472.
index-constraints vars=(a int, b int) index=(a, b)
(a,b) IN ((1, 2)) AND a = 1
----
[/1/2 - /1/2]

# Function call.
index-constraints vars=(a string) index=(a)
a > 'a' AND length(a) = 2
----
[/e'a\x00' - ]
Remaining filter: length(a) = 2

index-constraints vars=(a bool) index=(a)
true
----
[ - ]

# Combinations with OR
index-constraints vars=(a int, b int, c int) index=(a, b)
((a = 3 OR a = 5) AND (a = 3 OR a = 8) AND (a = 3 OR a = 11)) OR ((a = 1 OR a = 5) AND (a = 2 OR a = 5) AND (a = 4 OR a = 5))
----
[/3 - /3]
[/5 - /5]

index-constraints vars=(a int, b int, c int) index=(a, b)
((a = 4) OR ((a = 3 AND b = 8) OR (a = 3 AND a = 11))) OR ((a = 4) OR ((a = 3 AND b = 8) OR (a = 3 AND a = 11)))
----
[/3 - /4]
Remaining filter: ((a = 4) OR ((a = 3) AND ((b = 8) OR (a = 11)))) OR ((a = 4) OR ((a = 3) AND ((b = 8) OR (a = 11))))

index-constraints vars=(a int, b int, c int) index=(a, b)
((a = 5) OR ((a = 3 AND b = 8) OR (a = 3 AND a = 11))) OR ((a = 4) OR ((a = 3 AND b = 8) OR (a = 3 AND a = 11)))
----
[/3 - /5]
Remaining filter: ((a = 5) OR ((a = 3) AND ((b = 8) OR (a = 11)))) OR ((a = 4) OR ((a = 3) AND ((b = 8) OR (a = 11))))

index-constraints vars=(a int, b int, c int) index=(a, b)
((a = 3 AND b = 8) OR (a = 2 AND b = 8) OR (a = 3 AND b = 11)) AND ((a = 3 AND b = 4) OR (a = 2 AND b = 3) OR (a = 3 AND b = 4))
----

index-constraints vars=(a int, b int, c int) index=(a, b)
((a = 3 AND b = 8) OR (a = 2 AND b = 8) OR (a = 3 AND b = 11)) OR ((a = 3 AND b = 4) OR (a = 2 AND b = 3) OR (a = 3 AND b = 4))
----
[/2/3 - /2/3]
[/2/8 - /2/8]
[/3/4 - /3/4]
[/3/8 - /3/8]
[/3/11 - /3/11]

index-constraints vars=(a int, b int, c int) index=(a, b)
(((a = 3 AND b = 8) OR (a = 2 AND b = 8) OR (a = 3 AND b = 11)) OR ((a = 3 AND b = 4) OR (a = 2 AND b = 3) OR (a = 3 AND b = 4))) AND
(((a = 1 AND b = 8) OR (a = 1 AND b = 8) OR (a = 1 AND b = 11)) OR ((a = 3 AND b = 4) OR (a = 2 AND b = 3) OR (a = 3 AND b = 8)))
----
[/2/3 - /2/3]
[/3/4 - /3/4]
[/3/8 - /3/8]

index-constraints vars=(a int, b int, c int) index=(a, b)
((((a = 3 AND b = 8) OR (a = 2 AND b = 8) OR (a = 3 AND b = 11)) OR ((a = 3 AND b = 4) OR (a = 2 AND b = 3) OR (a = 3 AND b = 4))) AND
(((a = 1 AND b = 8) OR (a = 1 AND b = 8) OR (a = 1 AND b = 11)) OR ((a = 3 AND b = 4) OR (a = 2 AND b = 3) OR (a = 3 AND b = 8)))) OR
((((a = 3 AND b = 9) OR (a = 2 AND a > 0) OR (a = 3 AND b = 11)) OR ((a = 3 AND b = 4) OR (a = 2 AND b = 3) OR (a = 3 AND b = 4))) AND
(((a = 1 AND b = 8) OR (a = 1 AND b = 8) OR (a = 1 AND b = 11)) OR ((a = 3 AND b = 4) OR (a = 2 AND b <= 3) OR (a = 3 AND b = 8))))
----
(/2/NULL - /2/3]
[/3/4 - /3/4]
[/3/8 - /3/8]

index-constraints vars=(a int, b int, c int) index=(a, b)
a IN (1,2,3,4,5,6,7,8) OR (a=10 OR a=11 OR a=12) AND a IN (9,10,12)
----
[/1 - /8]
[/10 - /10]
[/12 - /12]

index-constraints vars=(a int, b int, c int) index=(a, b)
a = 1 AND ((a = 1 AND b = 1) OR (a = 1 AND (a = 1 AND b = 1) AND (a = 1 OR a = 2 OR (a = 1 AND b = 6))))
----
[/1/1 - /1/1]
