exec-ddl
CREATE TABLE abcde (
    a INT PRIMARY KEY,
    b INT,
    c INT,
    d INT,
    e INT,
    UNIQUE INDEX bc (b, c)
)
----
TABLE abcde
 ├── a int not null
 ├── b int
 ├── c int
 ├── d int
 ├── e int
 ├── INDEX primary
 │    └── a int not null
 └── INDEX bc
      ├── b int
      ├── c int
      └── a int not null (storing)

# --------------------------------------------------
# SimplifyLimitOrdering
# --------------------------------------------------
# Remove constant column.
opt expect=SimplifyLimitOrdering
SELECT d, e FROM (SELECT d, 1 AS one, e FROM abcde) ORDER BY d, one, e LIMIT 10
----
limit
 ├── columns: d:4(int) e:5(int)
 ├── internal-ordering: +4,+5
 ├── cardinality: [0 - 10]
 ├── ordering: +4,+5 opt(6)
 ├── sort
 │    ├── columns: d:4(int) e:5(int)
 │    ├── ordering: +4,+5
 │    └── scan abcde
 │         └── columns: d:4(int) e:5(int)
 └── const: 10 [type=int]

# Remove multiple constant columns.
opt expect=SimplifyLimitOrdering
SELECT b, c FROM abcde WHERE d=1 AND e=2 ORDER BY b, c, d, e, a LIMIT 10
----
limit
 ├── columns: b:2(int) c:3(int)
 ├── internal-ordering: +2,+3,+1 opt(4,5)
 ├── cardinality: [0 - 10]
 ├── key: (1)
 ├── fd: ()-->(4,5), (1)-->(2,3), (2,3)~~>(1)
 ├── ordering: +2,+3,+1 opt(4,5)
 ├── sort
 │    ├── columns: a:1(int!null) b:2(int) c:3(int) d:4(int!null) e:5(int!null)
 │    ├── key: (1)
 │    ├── fd: ()-->(4,5), (1)-->(2,3), (2,3)~~>(1)
 │    ├── ordering: +2,+3,+1 opt(4,5)
 │    └── select
 │         ├── columns: a:1(int!null) b:2(int) c:3(int) d:4(int!null) e:5(int!null)
 │         ├── key: (1)
 │         ├── fd: ()-->(4,5), (1)-->(2,3), (2,3)~~>(1)
 │         ├── scan abcde
 │         │    ├── columns: a:1(int!null) b:2(int) c:3(int) d:4(int) e:5(int)
 │         │    ├── key: (1)
 │         │    └── fd: (1)-->(2-5), (2,3)~~>(1,4,5)
 │         └── filters [type=bool, outer=(4,5), constraints=(/4: [/1 - /1]; /5: [/2 - /2]; tight), fd=()-->(4,5)]
 │              ├── d = 1 [type=bool, outer=(4), constraints=(/4: [/1 - /1]; tight)]
 │              └── e = 2 [type=bool, outer=(5), constraints=(/5: [/2 - /2]; tight)]
 └── const: 10 [type=int]

# Remove functionally dependent column that's only used in ordering.
opt expect=SimplifyLimitOrdering
SELECT c FROM abcde ORDER BY b, c, a, d LIMIT 10
----
scan abcde@bc
 ├── columns: c:3(int)
 ├── limit: 10
 ├── key: (1)
 ├── fd: (1)-->(2,3), (2,3)~~>(1)
 └── ordering: +2,+3,+1

# --------------------------------------------------
# SimplifyOffsetOrdering
# --------------------------------------------------
# Remove all order by columns, because all are constant.
opt expect=SimplifyOffsetOrdering
SELECT d, e FROM (SELECT d, 1 AS one, e FROM abcde) ORDER BY one OFFSET 10
----
offset
 ├── columns: d:4(int) e:5(int)
 ├── scan abcde
 │    └── columns: d:4(int) e:5(int)
 └── const: 10 [type=int]

# --------------------------------------------------
# SimplifyGroupByOrdering
# --------------------------------------------------
# Remove columns functionally dependent on key.
# TODO(justin): figure out why this doesn't trigger SimplifyGroupByOrdering (it
# triggers SimplifyRootOrdering).
opt
SELECT array_agg(b), a, c FROM abcde GROUP BY b, a, c ORDER BY a, b, c
----
group-by
 ├── columns: array_agg:6(int[]) a:1(int!null) c:3(int)
 ├── grouping columns: a:1(int!null)
 ├── key: (1)
 ├── fd: (1)-->(3,6)
 ├── ordering: +1
 ├── scan abcde
 │    ├── columns: a:1(int!null) b:2(int) c:3(int)
 │    ├── key: (1)
 │    ├── fd: (1)-->(2,3), (2,3)~~>(1)
 │    └── ordering: +1
 └── aggregations [outer=(2,3)]
      ├── array-agg [type=int[], outer=(2)]
      │    └── variable: b [type=int, outer=(2)]
      └── const-agg [type=int, outer=(3)]
           └── variable: c [type=int, outer=(3)]

# ScalarGroupBy case.
opt expect=SimplifyGroupByOrdering
SELECT array_agg(b) FROM (SELECT * FROM abcde ORDER BY a, b, c)
----
scalar-group-by
 ├── columns: array_agg:6(int[])
 ├── internal-ordering: +1
 ├── cardinality: [1 - 1]
 ├── key: ()
 ├── fd: ()-->(6)
 ├── scan abcde
 │    ├── columns: a:1(int!null) b:2(int) c:3(int)
 │    ├── key: (1)
 │    ├── fd: (1)-->(2,3), (2,3)~~>(1)
 │    └── ordering: +1
 └── aggregations [outer=(2)]
      └── array-agg [type=int[], outer=(2)]
           └── variable: b [type=int, outer=(2)]

# DistinctOn case.
opt expect=SimplifyGroupByOrdering
SELECT DISTINCT ON (b, c) a, b, c FROM abcde ORDER BY b, c, a, d, e
----
distinct-on
 ├── columns: a:1(int) b:2(int) c:3(int)
 ├── grouping columns: b:2(int) c:3(int)
 ├── internal-ordering: +2,+3,+1
 ├── key: (1)
 ├── fd: (1)-->(2,3), (2,3)-->(1)
 ├── ordering: +2,+3
 ├── scan abcde@bc
 │    ├── columns: a:1(int!null) b:2(int) c:3(int)
 │    ├── key: (1)
 │    ├── fd: (1)-->(2,3), (2,3)~~>(1)
 │    └── ordering: +2,+3,+1
 └── aggregations [outer=(1)]
      └── first-agg [type=int, outer=(1)]
           └── variable: a [type=int, outer=(1)]

# --------------------------------------------------
# SimplifyRowNumberOrdering
# --------------------------------------------------
# Remove column functionally dependent on multi-column key.
opt expect=SimplifyRowNumberOrdering
SELECT * FROM (SELECT * FROM abcde WHERE b IS NOT NULL AND c IS NOT NULL ORDER BY c, d, b, e) WITH ORDINALITY
----
row-number
 ├── columns: a:1(int!null) b:2(int!null) c:3(int!null) d:4(int) e:5(int) ordinality:6(int!null)
 ├── key: (1)
 ├── fd: (1)-->(2-6), (2,3)-->(1,4,5), (6)-->(1-5)
 └── sort
      ├── columns: a:1(int!null) b:2(int!null) c:3(int!null) d:4(int) e:5(int)
      ├── key: (1)
      ├── fd: (1)-->(2-5), (2,3)-->(1,4,5)
      ├── ordering: +3,+4,+2
      └── select
           ├── columns: a:1(int!null) b:2(int!null) c:3(int!null) d:4(int) e:5(int)
           ├── key: (1)
           ├── fd: (1)-->(2-5), (2,3)-->(1,4,5)
           ├── scan abcde
           │    ├── columns: a:1(int!null) b:2(int) c:3(int) d:4(int) e:5(int)
           │    ├── key: (1)
           │    └── fd: (1)-->(2-5), (2,3)~~>(1,4,5)
           └── filters [type=bool, outer=(2,3), constraints=(/2: (/NULL - ]; /3: (/NULL - ]; tight)]
                ├── b IS NOT NULL [type=bool, outer=(2), constraints=(/2: (/NULL - ]; tight)]
                └── c IS NOT NULL [type=bool, outer=(3), constraints=(/3: (/NULL - ]; tight)]

# --------------------------------------------------
# SimplifyExplainOrdering
# --------------------------------------------------
# Remove functionally dependent synthesized column.
opt expect=SimplifyExplainOrdering
EXPLAIN SELECT b, b+1 AS plus, c FROM abcde ORDER BY b, plus, c
----
explain
 ├── columns: tree:7(string) field:8(string) description:9(string)
 └── project
      ├── columns: b:2(int) plus:6(int) c:3(int)
      ├── lax-key: (2,3)
      ├── fd: (2)-->(6)
      ├── ordering: +2,+3
      ├── scan abcde@bc
      │    ├── columns: b:2(int) c:3(int)
      │    ├── lax-key: (2,3)
      │    └── ordering: +2,+3
      └── projections [outer=(2,3)]
           └── b + 1 [type=int, outer=(2)]

# Regression: Explain a statement having constant column, but with no ordering.
opt
SELECT field FROM [EXPLAIN SELECT 123 AS k]
----
project
 ├── columns: field:3(string)
 └── explain
      ├── columns: tree:2(string) field:3(string) description:4(string)
      └── project
           ├── columns: k:1(int!null)
           ├── cardinality: [1 - 1]
           ├── key: ()
           ├── fd: ()-->(1)
           ├── values
           │    ├── cardinality: [1 - 1]
           │    ├── key: ()
           │    └── tuple [type=tuple]
           └── projections
                └── const: 123 [type=int]
