exec-ddl
CREATE TABLE abcde (
    a INT PRIMARY KEY,
    b INT,
    c INT,
    d INT,
    e INT DEFAULT(10),
    UNIQUE INDEX bc (b, c)
)
----

exec-ddl
CREATE TABLE xyz (
    x TEXT PRIMARY KEY,
    y INT8,
    z FLOAT8
)
----

# --------------------------------------------------
# SimplifyLimitOrdering
# --------------------------------------------------
# Remove constant column.
norm 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 e:5
 ├── internal-ordering: +4,+5
 ├── cardinality: [0 - 10]
 ├── ordering: +4,+5
 ├── sort
 │    ├── columns: d:4 e:5
 │    ├── ordering: +4,+5
 │    ├── limit hint: 10.00
 │    └── scan abcde
 │         └── columns: d:4 e:5
 └── 10

# Remove multiple constant columns.
norm 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 c:3  [hidden: a:1!null d:4!null e:5!null]
 ├── 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) [actual: +2,+3,+1]
 ├── sort
 │    ├── columns: a:1!null b:2 c:3 d:4!null e:5!null
 │    ├── key: (1)
 │    ├── fd: ()-->(4,5), (1)-->(2,3), (2,3)~~>(1)
 │    ├── ordering: +2,+3,+1 opt(4,5) [actual: +2,+3,+1]
 │    ├── limit hint: 10.00
 │    └── select
 │         ├── columns: a:1!null b:2 c:3 d:4!null e:5!null
 │         ├── key: (1)
 │         ├── fd: ()-->(4,5), (1)-->(2,3), (2,3)~~>(1)
 │         ├── scan abcde
 │         │    ├── columns: a:1!null b:2 c:3 d:4 e:5
 │         │    ├── key: (1)
 │         │    └── fd: (1)-->(2-5), (2,3)~~>(1,4,5)
 │         └── filters
 │              ├── d:4 = 1 [outer=(4), constraints=(/4: [/1 - /1]; tight), fd=()-->(4)]
 │              └── e:5 = 2 [outer=(5), constraints=(/5: [/2 - /2]; tight), fd=()-->(5)]
 └── 10

# Remove functionally dependent column that's only used in ordering.
norm expect=SimplifyLimitOrdering
SELECT c FROM abcde ORDER BY b, c, a, d LIMIT 10
----
limit
 ├── columns: c:3  [hidden: a:1!null b:2]
 ├── internal-ordering: +2,+3,+1
 ├── cardinality: [0 - 10]
 ├── key: (1)
 ├── fd: (1)-->(2,3), (2,3)~~>(1)
 ├── ordering: +2,+3,+1
 ├── sort
 │    ├── columns: a:1!null b:2 c:3
 │    ├── key: (1)
 │    ├── fd: (1)-->(2,3), (2,3)~~>(1)
 │    ├── ordering: +2,+3,+1
 │    ├── limit hint: 10.00
 │    └── scan abcde
 │         ├── columns: a:1!null b:2 c:3
 │         ├── key: (1)
 │         └── fd: (1)-->(2,3), (2,3)~~>(1)
 └── 10

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

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

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

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

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

# --------------------------------------------------
# SimplifyExplainOrdering
# --------------------------------------------------
# Remove functionally dependent synthesized column.
norm expect=SimplifyExplainOrdering
EXPLAIN SELECT b, b+1 AS plus, c FROM abcde ORDER BY b, plus, c
----
explain
 ├── columns: info:9
 ├── immutable
 └── project
      ├── columns: b:2 plus:8 c:3
      ├── immutable
      ├── lax-key: (2,3)
      ├── fd: (2)-->(8)
      ├── ordering: +2,+3
      ├── sort
      │    ├── columns: b:2 c:3
      │    ├── lax-key: (2,3)
      │    ├── ordering: +2,+3
      │    └── scan abcde
      │         ├── columns: b:2 c:3
      │         └── lax-key: (2,3)
      └── projections
           └── b:2 + 1 [as=plus:8, outer=(2), immutable]

# Regression: Explain a statement having constant column, but with no ordering.
norm
SELECT * FROM [EXPLAIN SELECT 123 AS k]
----
project
 ├── columns: info:3
 ├── explain
 │    ├── columns: info:2
 │    └── values
 │         ├── columns: k:1!null
 │         ├── cardinality: [1 - 1]
 │         ├── key: ()
 │         ├── fd: ()-->(1)
 │         └── (123,)
 └── projections
      └── info:2 [as=info:3, outer=(2)]

# --------------------------------------------------
# SimplifyWithBindingOrdering
# --------------------------------------------------
norm set=propagate_input_ordering=true expect=SimplifyWithBindingOrdering
WITH cte AS (SELECT a, b FROM abcde ORDER BY a, b, c)
SELECT * FROM cte, xyz
----
with &1 (cte)
 ├── columns: a:8!null b:9 x:10!null y:11 z:12
 ├── materialized
 ├── key: (8,10)
 ├── fd: (8)-->(9), (10)-->(11,12)
 ├── scan abcde
 │    ├── columns: abcde.a:1!null abcde.b:2 c:3
 │    ├── key: (1)
 │    ├── fd: (1)-->(2,3), (2,3)~~>(1)
 │    └── ordering: +1
 └── inner-join (cross)
      ├── columns: a:8!null b:9 x:10!null y:11 z:12
      ├── key: (8,10)
      ├── fd: (8)-->(9), (10)-->(11,12)
      ├── with-scan &1 (cte)
      │    ├── columns: a:8!null b:9
      │    ├── mapping:
      │    │    ├──  abcde.a:1 => a:8
      │    │    └──  abcde.b:2 => b:9
      │    ├── key: (8)
      │    └── fd: (8)-->(9)
      ├── scan xyz
      │    ├── columns: x:10!null y:11 z:12
      │    ├── key: (10)
      │    └── fd: (10)-->(11,12)
      └── filters (true)

norm set=propagate_input_ordering=true expect=SimplifyWithBindingOrdering
WITH cte AS (SELECT d, 1 AS one, e FROM abcde ORDER BY d, one, e)
SELECT * FROM cte
----
with &1 (cte)
 ├── columns: d:9 one:10!null e:11
 ├── materialized
 ├── fd: ()-->(10)
 ├── project
 │    ├── columns: one:8!null abcde.d:4 abcde.e:5
 │    ├── fd: ()-->(8)
 │    ├── ordering: +4,+5 opt(8) [actual: +4,+5]
 │    ├── sort
 │    │    ├── columns: abcde.d:4 abcde.e:5
 │    │    ├── ordering: +4,+5
 │    │    └── scan abcde
 │    │         └── columns: abcde.d:4 abcde.e:5
 │    └── projections
 │         └── 1 [as=one:8]
 └── with-scan &1 (cte)
      ├── columns: d:9 one:10!null e:11
      ├── mapping:
      │    ├──  abcde.d:4 => d:9
      │    ├──  one:8 => one:10
      │    └──  abcde.e:5 => e:11
      └── fd: ()-->(10)
