# --------------------------------------------------
# FoldArray
# --------------------------------------------------

exec-ddl
CREATE TABLE t (
  x INT PRIMARY KEY
)
----
TABLE t
 ├── x int not null
 └── INDEX primary
      └── x int not null

opt expect=FoldArray
SELECT ARRAY[1, 2, 3] FROM t
----
project
 ├── columns: array:2(int[]!null)
 ├── fd: ()-->(2)
 ├── scan t
 └── projections
      └── const: ARRAY[1,2,3] [type=int[]]

# Do not fold if there is a non-constant element.
opt expect-not=FoldArray
SELECT ARRAY[1, 2, 3, x] FROM t
----
project
 ├── columns: array:2(int[])
 ├── scan t
 │    ├── columns: x:1(int!null)
 │    └── key: (1)
 └── projections [outer=(1)]
      └── ARRAY[1, 2, 3, x] [type=int[], outer=(1)]

opt expect=FoldArray
SELECT ARRAY['foo', 'bar']
----
project
 ├── columns: array:1(string[]!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: ARRAY['foo','bar'] [type=string[]]

# --------------------------------------------------
# FoldBinary
# --------------------------------------------------

# Fold constant.
opt expect=FoldBinary
SELECT 1::INT + 2::DECIMAL
----
project
 ├── columns: "?column?":1(decimal!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: 3 [type=decimal]

# Don't fold: out of range error.
opt expect-not=FoldBinary
SELECT 9223372036854775800::INT + 9223372036854775800::INT
----
project
 ├── columns: "?column?":1(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── 9223372036854775800 + 9223372036854775800 [type=int]

# Fold constant.
opt expect=FoldBinary
SELECT 1::INT - 2::INT
----
project
 ├── columns: "?column?":1(int!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: -1 [type=int]

# Don't fold: out of range error.
opt expect-not=FoldBinary
SELECT (-9223372036854775800)::INT - 9223372036854775800::INT
----
project
 ├── columns: "?column?":1(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── -9223372036854775800 - 9223372036854775800 [type=int]

# Fold constant.
opt expect=FoldBinary
SELECT 4::INT * 2::INT
----
project
 ├── columns: "?column?":1(int!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: 8 [type=int]

# Don't fold: out of range error.
opt expect-not=FoldBinary
SELECT 9223372036854775800::INT * 9223372036854775800::INT
----
project
 ├── columns: "?column?":1(int)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── 9223372036854775800 * 9223372036854775800 [type=int]

# Fold constant.
opt expect=FoldBinary
SELECT 1::FLOAT / 2::FLOAT
----
project
 ├── columns: "?column?":1(float!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: 0.5 [type=float]

# Don't fold: divide by zero error.
opt expect-not=FoldBinary
SELECT 1::INT / 0::INT
----
project
 ├── columns: "?column?":1(decimal)
 ├── cardinality: [1 - 1]
 ├── side-effects
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections [side-effects]
      └── 1 / 0 [type=decimal, side-effects]

# Fold constant.
opt expect=FoldBinary
SELECT '2000-05-05 10:00:00+03':::TIMESTAMP - '2000-05-06 10:00:00+03':::TIMESTAMP
----
project
 ├── columns: "?column?":1(interval!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: '-24h' [type=interval]

# Fold constant.
opt expect=FoldBinary
SELECT '2000-05-05 10:00:00+03':::TIMESTAMP - '2000-05-06 10:00:00+03':::TIMESTAMPTZ
----
project
 ├── columns: "?column?":1(interval!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: '-21h' [type=interval]

# Fold constant.
opt expect=FoldBinary
SELECT ARRAY['a','b','c'] || 'd'
----
project
 ├── columns: "?column?":1(string[]!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: ARRAY['a','b','c','d'] [type=string[]]

# Fold constant.
opt expect=FoldBinary
SELECT ARRAY['a','b','c'] || ARRAY['d','e','f']
----
project
 ├── columns: "?column?":1(string[]!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: ARRAY['a','b','c','d','e','f'] [type=string[]]

# NULL should not be added to the array.
opt expect=FoldBinary
SELECT ARRAY[1,2,3] || NULL
----
project
 ├── columns: "?column?":1(int[]!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: ARRAY[1,2,3] [type=int[]]

# --------------------------------------------------
# FoldUnary
# --------------------------------------------------
opt expect=FoldUnary
SELECT -(1:::int)
----
project
 ├── columns: "?column?":1(int!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: -1 [type=int]

opt expect=FoldUnary
SELECT -(1:::float)
----
project
 ├── columns: "?column?":1(float!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: -1.0 [type=float]

# TODO(justin): it would be better if this produced an error in the optimizer
# rather than falling back to execution to error.
opt expect-not=FoldUnary format=show-all
SELECT -((-9223372036854775808)::int)
----
project
 ├── columns: "?column?":1(int)
 ├── cardinality: [1 - 1]
 ├── stats: [rows=1]
 ├── cost: 0.03
 ├── key: ()
 ├── fd: ()-->(1)
 ├── prune: (1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── stats: [rows=1]
 │    ├── cost: 0.01
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── unary-minus [type=int]
           └── const: -9223372036854775808 [type=int]

opt expect=FoldUnary format=show-all
SELECT -(1:::decimal)
----
project
 ├── columns: "?column?":1(decimal!null)
 ├── cardinality: [1 - 1]
 ├── stats: [rows=1]
 ├── cost: 0.03
 ├── key: ()
 ├── fd: ()-->(1)
 ├── prune: (1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── stats: [rows=1]
 │    ├── cost: 0.01
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: -1 [type=decimal]

opt expect=FoldUnary format=show-all
SELECT -('-1d'::interval);
----
project
 ├── columns: "?column?":1(interval!null)
 ├── cardinality: [1 - 1]
 ├── stats: [rows=1]
 ├── cost: 0.03
 ├── key: ()
 ├── fd: ()-->(1)
 ├── prune: (1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── stats: [rows=1]
 │    ├── cost: 0.01
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: '1d' [type=interval]

# TODO(justin): this seems incorrect but it's consistent with the existing
# planner. Revisit this: #26932.
opt expect=FoldUnary
SELECT -('-9223372036854775808d'::interval);
----
project
 ├── columns: "?column?":1(interval!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: '-9223372036854775808d' [type=interval]

# Fold constant.
opt expect=FoldUnary
SELECT ~(500::INT)
----
project
 ├── columns: "?column?":1(int!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: -501 [type=int]

# Fold constant.
opt expect=FoldUnary
SELECT ~('35.231.178.195'::INET)
----
project
 ├── columns: "?column?":1(inet!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── const: '220.24.77.60' [type=inet]

# --------------------------------------------------
# FoldComparison
# --------------------------------------------------

# Fold constant.
opt expect=FoldComparison
SELECT 1::INT < 2::INT
----
project
 ├── columns: "?column?":1(bool!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── true [type=bool]

# Fold constant.
opt expect=FoldComparison
SELECT 2.0::DECIMAL = 2::INT
----
project
 ├── columns: "?column?":1(bool!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── true [type=bool]

# Fold constant.
opt expect=FoldComparison
SELECT 100 IS NOT DISTINCT FROM 200
----
project
 ├── columns: "?column?":1(bool!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── false [type=bool]

# Fold constant.
opt expect=FoldComparison
SELECT 'foo' IN ('a', 'b', 'c')
----
project
 ├── columns: "?column?":1(bool!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── false [type=bool]

# Fold constant.
opt expect=FoldComparison
SELECT '[1, 2]'::JSONB <@ '[1, 2, 3]'::JSONB
----
project
 ├── columns: "?column?":1(bool!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── true [type=bool]

# Fold constant.
opt expect=FoldComparison
SELECT ('a', 'b', 'c') = ('d', 'e', 'f')
----
project
 ├── columns: "?column?":1(bool!null)
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(1)
 ├── values
 │    ├── cardinality: [1 - 1]
 │    ├── key: ()
 │    └── tuple [type=tuple]
 └── projections
      └── false [type=bool]
