# LogicTest: local

statement ok
CREATE TABLE kv (
  k INT PRIMARY KEY,
  v INT,
  w INT,
  s STRING
)

# Selecting and grouping on a more complex expression works.
query TTTTT
EXPLAIN (VERBOSE) SELECT count(*), k+v AS r FROM kv GROUP BY k+v
----
group           ·            ·                                    (count, r)                      weak-key(r)
 │              aggregate 0  count_rows()                         ·                               ·
 │              aggregate 1  ?column?                             ·                               ·
 │              group by     @1                                   ·                               ·
 └── render     ·            ·                                    ("?column?")                    ·
      │         render 0     test.public.kv.k + test.public.kv.v  ·                               ·
      └── scan  ·            ·                                    (k, v, w[omitted], s[omitted])  k!=NULL; key(k)
·               table        kv@primary                           ·                               ·
·               spans        ALL                                  ·                               ·

# Selecting a more complex expression, made up of things which are each grouped, works.
query TTTTT
EXPLAIN (VERBOSE) SELECT count(*), k+v AS r FROM kv GROUP BY k, v
----
render               ·            ·                 (count, r)                      ·
 │                   render 0     agg0              ·                               ·
 │                   render 1     agg1 + agg2       ·                               ·
 └── group           ·            ·                 (agg0, agg1, agg2)              agg1!=NULL; key(agg1)
      │              aggregate 0  count_rows()      ·                               ·
      │              aggregate 1  k                 ·                               ·
      │              aggregate 2  v                 ·                               ·
      │              group by     @1-@2             ·                               ·
      │              ordered      @1                ·                               ·
      └── render     ·            ·                 (k, v)                          k!=NULL; key(k); +k
           │         render 0     test.public.kv.k  ·                               ·
           │         render 1     test.public.kv.v  ·                               ·
           └── scan  ·            ·                 (k, v, w[omitted], s[omitted])  k!=NULL; key(k); +k
·                    table        kv@primary        ·                               ·
·                    spans        ALL               ·                               ·

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT count(k) FROM kv
]
----
group           ·            ·
 │              aggregate 0  count(k)
 │              scalar       ·
 └── render     ·            ·
      │         render 0     test.public.kv.k
      └── scan  ·            ·
·               table        kv@primary
·               spans        ALL

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT count(k), sum(k), max(k) FROM kv
]
----
group           ·            ·
 │              aggregate 0  count(k)
 │              aggregate 1  sum(k)
 │              aggregate 2  max(k)
 │              scalar       ·
 └── render     ·            ·
      │         render 0     test.public.kv.k
      └── scan  ·            ·
·               table        kv@primary
·               spans        ALL

query TTTTT
EXPLAIN (VERBOSE) SELECT count(DISTINCT a.*) FROM kv a, kv b
----
group                ·            ·                                             (count)                                                       ·
 │                   aggregate 0  count(DISTINCT ((k, v, w, s) AS k, v, w, s))  ·                                                             ·
 │                   scalar       ·                                             ·                                                             ·
 └── render          ·            ·                                             ("((k, v, w, s) AS k, v, w, s)")                              ·
      │              render 0     ((a.k, a.v, a.w, a.s) AS k, v, w, s)          ·                                                             ·
      └── hash-join  ·            ·                                             (k, v, w, s, k[omitted], v[omitted], w[omitted], s[omitted])  ·
           │         type         cross                                         ·                                                             ·
           ├── scan  ·            ·                                             (k, v, w, s)                                                  k!=NULL; key(k)
           │         table        kv@primary                                    ·                                                             ·
           │         spans        ALL                                           ·                                                             ·
           └── scan  ·            ·                                             (k[omitted], v[omitted], w[omitted], s[omitted])              k!=NULL; key(k)
·                    table        kv@primary                                    ·                                                             ·
·                    spans        ALL                                           ·                                                             ·

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT min(b.k) FROM kv a, kv b GROUP BY a.*
]
----
group                ·            ·
 │                   aggregate 0  min(k)
 │                   group by     @1-@4
 └── render          ·            ·
      │              render 0     a.k
      │              render 1     a.v
      │              render 2     a.w
      │              render 3     a.s
      │              render 4     b.k
      └── hash-join  ·            ·
           │         type         cross
           ├── scan  ·            ·
           │         table        kv@primary
           │         spans        ALL
           └── scan  ·            ·
·                    table        kv@primary
·                    spans        ALL

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT min(b.k) FROM kv a, kv b GROUP BY (1, (a.*))
]
----
group                ·            ·
 │                   aggregate 0  min(k)
 │                   group by     @1-@5
 └── render          ·            ·
      │              render 0     1
      │              render 1     a.k
      │              render 2     a.v
      │              render 3     a.w
      │              render 4     a.s
      │              render 5     b.k
      └── hash-join  ·            ·
           │         type         cross
           ├── scan  ·            ·
           │         table        kv@primary
           │         spans        ALL
           └── scan  ·            ·
·                    table        kv@primary
·                    spans        ALL

# A useful optimization: naked tuple expansion in GROUP BY clause.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT min(b.k) FROM kv a, kv b GROUP BY (a.*)
]
----
group                ·            ·
 │                   aggregate 0  min(k)
 │                   group by     @1-@4
 └── render          ·            ·
      │              render 0     a.k
      │              render 1     a.v
      │              render 2     a.w
      │              render 3     a.s
      │              render 4     b.k
      └── hash-join  ·            ·
           │         type         cross
           ├── scan  ·            ·
           │         table        kv@primary
           │         spans        ALL
           └── scan  ·            ·
·                    table        kv@primary
·                    spans        ALL

# Show reuse of renders expression inside an expansion.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT a.k FROM kv a, kv b GROUP BY a.*
]
----
group                ·            ·
 │                   aggregate 0  k
 │                   group by     @1-@4
 └── render          ·            ·
      │              render 0     a.k
      │              render 1     a.v
      │              render 2     a.w
      │              render 3     a.s
      └── hash-join  ·            ·
           │         type         cross
           ├── scan  ·            ·
           │         table        kv@primary
           │         spans        ALL
           └── scan  ·            ·
·                    table        kv@primary
·                    spans        ALL

statement ok
CREATE TABLE abc (
  a CHAR PRIMARY KEY,
  b FLOAT,
  c BOOLEAN,
  d DECIMAL
)

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT min(a) FROM abc
]
----
group           ·            ·
 │              aggregate 0  min(a)
 │              scalar       ·
 └── render     ·            ·
      │         render 0     test.public.abc.a
      └── scan  ·            ·
·               table        abc@primary
·               spans        ALL
·               limit        1

# Verify summing of intervals
statement ok
CREATE TABLE intervals (
  a INTERVAL PRIMARY KEY
)

statement ok
CREATE TABLE xyz (
  x INT PRIMARY KEY,
  y INT,
  z FLOAT,
  INDEX xy (x, y),
  INDEX zyx (z, y, x),
  FAMILY (x),
  FAMILY (y),
  FAMILY (z)
)

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT min(x) FROM xyz
]
----
group           ·            ·
 │              aggregate 0  min(x)
 │              scalar       ·
 └── render     ·            ·
      │         render 0     test.public.xyz.x
      └── scan  ·            ·
·               table        xyz@xy
·               spans        ALL
·               limit        1

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT min(x) FROM xyz WHERE x in (0, 4, 7)
]
----
group           ·            ·
 │              aggregate 0  min(x)
 │              scalar       ·
 └── render     ·            ·
      │         render 0     test.public.xyz.x
      └── scan  ·            ·
·               table        xyz@xy
·               spans        /0-/1 /4-/5 /7-/8
·               limit        1

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT max(x) FROM xyz
]
----
group              ·            ·
 │                 aggregate 0  max(x)
 │                 scalar       ·
 └── render        ·            ·
      │            render 0     test.public.xyz.x
      └── revscan  ·            ·
·                  table        xyz@xy
·                  spans        ALL
·                  limit        1

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT min(y) FROM xyz WHERE x = 1
]
----
group           ·            ·
 │              aggregate 0  min(y)
 │              scalar       ·
 └── render     ·            ·
      │         render 0     test.public.xyz.y
      └── scan  ·            ·
·               table        xyz@xy
·               spans        /1/!NULL-/2
·               limit        1

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT max(y) FROM xyz WHERE x = 1
]
----
group              ·            ·
 │                 aggregate 0  max(y)
 │                 scalar       ·
 └── render        ·            ·
      │            render 0     test.public.xyz.y
      └── revscan  ·            ·
·                  table        xyz@xy
·                  spans        /1/!NULL-/2
·                  limit        1

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT min(y) FROM xyz WHERE x = 7
]
----
group           ·            ·
 │              aggregate 0  min(y)
 │              scalar       ·
 └── render     ·            ·
      │         render 0     test.public.xyz.y
      └── scan  ·            ·
·               table        xyz@xy
·               spans        /7/!NULL-/8
·               limit        1

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT max(y) FROM xyz WHERE x = 7
]
----
group              ·            ·
 │                 aggregate 0  max(y)
 │                 scalar       ·
 └── render        ·            ·
      │            render 0     test.public.xyz.y
      └── revscan  ·            ·
·                  table        xyz@xy
·                  spans        /7/!NULL-/8
·                  limit        1

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT min(x) FROM xyz WHERE (y, z) = (2, 3.0)
]
----
group           ·            ·
 │              aggregate 0  min(x)
 │              scalar       ·
 └── render     ·            ·
      │         render 0     test.public.xyz.x
      └── scan  ·            ·
·               table        xyz@zyx
·               spans        /3/2-/3/3
·               limit        1

statement okSE
INSERT INTO xyz VALUES (1, 2, 3.0), (4, 5, 6.0), (7, NULL, 8.0)

statement ok
SET tracing = on,kv,results; SELECT min(x) FROM xyz WHERE (y, z) = (2, 3.0); SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /xyz/zyx/3.0/2/1 -> NULL
output row: [1]

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT max(x) FROM xyz WHERE (z, y) = (3.0, 2)
]
----
group              ·            ·
 │                 aggregate 0  max(x)
 │                 scalar       ·
 └── render        ·            ·
      │            render 0     test.public.xyz.x
      └── revscan  ·            ·
·                  table        xyz@zyx
·                  spans        /3/2-/3/3
·                  limit        1

# VARIANCE/STDDEV

statement ok
SET tracing = on,kv,results; SELECT variance(x), variance(y::decimal), round(variance(z), 14) FROM xyz; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /xyz/primary/1 -> NULL
fetched: /xyz/primary/1/y -> 2
fetched: /xyz/primary/1/z -> 3.0
fetched: /xyz/primary/4 -> NULL
fetched: /xyz/primary/4/y -> 5
fetched: /xyz/primary/4/z -> 6.0
fetched: /xyz/primary/7 -> NULL
fetched: /xyz/primary/7/z -> 8.0
output row: [9 4.5 6.33333333333333]

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT variance(x) FROM xyz WHERE x = 1
]
----
group           ·            ·
 │              aggregate 0  variance(x)
 │              scalar       ·
 └── render     ·            ·
      │         render 0     test.public.xyz.x
      └── scan  ·            ·
·               table        xyz@xy
·               spans        /1-/2

# Verify we only look at one row for MIN when we have an index on that column.
statement ok
SET tracing = on,kv,results; SELECT min(z) FROM xyz; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /xyz/zyx/3.0/2/1 -> NULL
output row: [3.0]

# Tests for the single-row optimization.
statement OK
CREATE TABLE ab (
  a INT PRIMARY KEY,
  b INT,
  FAMILY (a),
  FAMILY (b)
)

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT min(a) FROM abc
]
----
group           ·            ·
 │              aggregate 0  min(a)
 │              scalar       ·
 └── render     ·            ·
      │         render 0     test.public.abc.a
      └── scan  ·            ·
·               table        abc@primary
·               spans        ALL
·               limit        1

statement OK
INSERT INTO ab VALUES
  (1, 10),
  (2, 20),
  (3, 30),
  (4, 40),
  (5, 50)

# Verify we only buffer one row.
statement ok
SET tracing = on,kv,results; SELECT min(a) FROM ab; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /ab/primary/1 -> NULL
fetched: /ab/primary/1/b -> 10
output row: [1]

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT max(a) FROM abc
]
----
group              ·            ·
 │                 aggregate 0  max(a)
 │                 scalar       ·
 └── render        ·            ·
      │            render 0     test.public.abc.a
      └── revscan  ·            ·
·                  table        abc@primary
·                  spans        ALL
·                  limit        1

# Verify we only buffer one row.
statement ok
SET tracing = on,kv,results; SELECT max(a) FROM ab; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /ab/primary/5/b -> 50
fetched: /ab/primary/5 -> NULL
output row: [5]

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT v, count(k) FROM kv GROUP BY v ORDER BY count(k)
]
----
sort                 ·            ·
 │                   order        +count
 └── group           ·            ·
      │              aggregate 0  v
      │              aggregate 1  count(k)
      │              group by     @1
      └── render     ·            ·
           │         render 0     test.public.kv.v
           │         render 1     test.public.kv.k
           └── scan  ·            ·
·                    table        kv@primary
·                    spans        ALL

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT v, count(*) FROM kv GROUP BY v ORDER BY count(*)
]
----
sort                 ·            ·
 │                   order        +count
 └── group           ·            ·
      │              aggregate 0  v
      │              aggregate 1  count_rows()
      │              group by     @1
      └── render     ·            ·
           │         render 0     test.public.kv.v
           └── scan  ·            ·
·                    table        kv@primary
·                    spans        ALL

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT v, count(1) FROM kv GROUP BY v ORDER BY count(1)
]
----
sort                 ·            ·
 │                   order        +count
 └── group           ·            ·
      │              aggregate 0  v
      │              aggregate 1  count(1)
      │              group by     @1
      └── render     ·            ·
           │         render 0     test.public.kv.v
           │         render 1     1
           └── scan  ·            ·
·                    table        kv@primary
·                    spans        ALL

# Check that filters propagate through no-op aggregation.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM (SELECT v, count(1) FROM kv GROUP BY v) WHERE v > 10
]
----
group           ·            ·
 │              aggregate 0  v
 │              aggregate 1  count(1)
 │              group by     @1
 └── render     ·            ·
      │         render 0     test.public.kv.v
      │         render 1     1
      └── scan  ·            ·
·               table        kv@primary
·               spans        ALL
·               filter       v > 10

# Verify that FILTER works.

statement ok
CREATE TABLE filter_test (
  k INT,
  v INT,
  mark BOOL
)

# Check that filter expressions are only rendered once.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT count(*) FILTER (WHERE k>5), max(k>5) FILTER(WHERE k>5) FROM filter_test GROUP BY v
]
----
group           ·            ·
 │              aggregate 0  count_rows() FILTER (WHERE ?column?)
 │              aggregate 1  max(?column?) FILTER (WHERE ?column?)
 │              group by     @1
 └── render     ·            ·
      │         render 0     test.public.filter_test.v
      │         render 1     test.public.filter_test.k > 5
      └── scan  ·            ·
·               table        filter_test@primary
·               spans        ALL

query TTTTT
EXPLAIN (TYPES) SELECT count(*) FILTER (WHERE k > 5) FROM filter_test GROUP BY v
----
group           ·            ·                                     (count int)                                                    ·
 │              aggregate 0  count_rows() FILTER (WHERE ?column?)  ·                                                              ·
 │              group by     @1                                    ·                                                              ·
 └── render     ·            ·                                     (v int, "?column?" bool)                                       ·
      │         render 0     (v)[int]                              ·                                                              ·
      │         render 1     ((k)[int] > (5)[int])[bool]           ·                                                              ·
      └── scan  ·            ·                                     (k int, v int, mark[omitted] bool, rowid[hidden,omitted] int)  rowid!=NULL; key(rowid)
·               table        filter_test@primary                   ·                                                              ·
·               spans        ALL                                   ·                                                              ·

# Tests with * inside GROUP BY.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT 1 FROM kv GROUP BY kv.*
]
----
render          ·         ·
 │              render 0  1
 └── group      ·         ·
      │         group by  @1-@4
      │         ordered   @1
      └── scan  ·         ·
·               table     kv@primary
·               spans     ALL

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT sum(abc.d) FROM kv JOIN abc ON kv.k >= abc.d GROUP BY kv.*
]
----
group                ·            ·
 │                   aggregate 0  sum(d)
 │                   group by     @1-@4
 └── render          ·            ·
      │              render 0     test.public.kv.k
      │              render 1     test.public.kv.v
      │              render 2     test.public.kv.w
      │              render 3     test.public.kv.s
      │              render 4     test.public.abc.d
      └── hash-join  ·            ·
           │         type         inner
           │         pred         test.public.kv.k >= test.public.abc.d
           ├── scan  ·            ·
           │         table        kv@primary
           │         spans        ALL
           └── scan  ·            ·
·                    table        abc@primary
·                    spans        ALL

# opt_test is used for tests around the single-row optimization for MIN/MAX.
statement ok
CREATE TABLE opt_test (k INT PRIMARY KEY, v INT, INDEX v(v))

# Verify that we correctly add the v IS NOT NULL constraint (which restricts the span).
query TTTTT
EXPLAIN (VERBOSE) SELECT min(v) FROM opt_test
----
group           ·            ·                       (min)            ·
 │              aggregate 0  min(v)                  ·                ·
 │              scalar       ·                       ·                ·
 └── render     ·            ·                       (v)              v!=NULL; +v
      │         render 0     test.public.opt_test.v  ·                ·
      └── scan  ·            ·                       (k[omitted], v)  k!=NULL; v!=NULL; key(k,v); +v
·               table        opt_test@v              ·                ·
·               spans        /!NULL-                 ·                ·
·               limit        1                       ·                ·

# Repeat test when there is an existing filter.
query TTTTT
EXPLAIN (VERBOSE) SELECT min(v) FROM opt_test WHERE k <> 4
----
group           ·            ·                       (min)   ·
 │              aggregate 0  min(v)                  ·       ·
 │              scalar       ·                       ·       ·
 └── render     ·            ·                       (v)     v!=NULL; +v
      │         render 0     test.public.opt_test.v  ·       ·
      └── scan  ·            ·                       (k, v)  k!=NULL; v!=NULL; key(k,v); +v
·               table        opt_test@v              ·       ·
·               spans        /!NULL-                 ·       ·
·               filter       k != 4                  ·       ·

# Check the optimization when the argument is non-trivial. The renderNode can't
# present an ordering on v+1 so the optimization is not applied, but the IS NOT
# NULL filter should be added.
query TTTTT
EXPLAIN (VERBOSE) SELECT min(v+1) FROM opt_test WHERE k <> 4
----
group           ·            ·                           (min)            ·
 │              aggregate 0  min(v + 1)                  ·                ·
 │              scalar       ·                           ·                ·
 └── render     ·            ·                           ("v + 1")        ·
      │         render 0     test.public.opt_test.v + 1  ·                ·
      └── scan  ·            ·                           (k[omitted], v)  k!=NULL; v!=NULL; key(k)
·               table        opt_test@primary            ·                ·
·               spans        -/3/# /5-                   ·                ·
·               filter       (v + 1) IS NOT NULL         ·                ·

# Verify that we don't use the optimization if there is a GROUP BY.
query TTTTT
EXPLAIN (VERBOSE) SELECT min(v) FROM opt_test GROUP BY k
----
group      ·            ·                 (min)   ·
 │         aggregate 0  min(v)            ·       ·
 │         group by     @1                ·       ·
 │         ordered      @1                ·       ·
 └── scan  ·            ·                 (k, v)  k!=NULL; key(k)
·          table        opt_test@primary  ·       ·
·          spans        ALL               ·       ·

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT (b, a) FROM ab GROUP BY (b, a)
]
----
render               ·            ·
 │                   render 0     (agg0, agg1)
 └── group           ·            ·
      │              aggregate 0  b
      │              aggregate 1  a
      │              group by     @1-@2
      │              ordered      @2
      └── render     ·            ·
           │         render 0     test.public.ab.b
           │         render 1     test.public.ab.a
           └── scan  ·            ·
·                    table        ab@primary
·                    spans        ALL

statement ok
CREATE TABLE xy(x STRING, y STRING);

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE)
   SELECT min(y), (b, a)
     FROM ab, xy GROUP BY (x, (a, b))
]
----
render                    ·            ·
 │                        render 0     agg0
 │                        render 1     (agg1, agg2)
 └── group                ·            ·
      │                   aggregate 0  min(y)
      │                   aggregate 1  b
      │                   aggregate 2  a
      │                   group by     @1-@3
      └── render          ·            ·
           │              render 0     test.public.xy.x
           │              render 1     test.public.ab.a
           │              render 2     test.public.ab.b
           │              render 3     test.public.xy.y
           └── hash-join  ·            ·
                │         type         cross
                ├── scan  ·            ·
                │         table        ab@primary
                │         spans        ALL
                └── scan  ·            ·
·                         table        xy@primary
·                         spans        ALL

# Test that ordering on GROUP BY columns is maintained.
statement ok
CREATE TABLE group_ord (
  x INT PRIMARY KEY,
  y INT,
  z INT,
  INDEX foo(z)
)

# The ordering is on all the GROUP BY columns, and isn't preserved after the
# aggregation.
query TTTTT
EXPLAIN (VERBOSE) SELECT x, max(y) FROM group_ord GROUP BY x
----
group           ·            ·                        (x, max)            x!=NULL; key(x)
 │              aggregate 0  x                        ·                   ·
 │              aggregate 1  max(y)                   ·                   ·
 │              group by     @1                       ·                   ·
 │              ordered      @1                       ·                   ·
 └── render     ·            ·                        (x, y)              x!=NULL; key(x); +x
      │         render 0     test.public.group_ord.x  ·                   ·
      │         render 1     test.public.group_ord.y  ·                   ·
      └── scan  ·            ·                        (x, y, z[omitted])  x!=NULL; key(x); +x
·               table        group_ord@primary        ·                   ·
·               spans        ALL                      ·                   ·

# The ordering is on all the GROUP BY columns, and is preserved after the
# aggregation.
query TTTTT
EXPLAIN (VERBOSE) SELECT x, max(y) FROM group_ord GROUP BY x ORDER BY x
----
group           ·            ·                        (x, max)            x!=NULL; key(x); +x
 │              aggregate 0  x                        ·                   ·
 │              aggregate 1  max(y)                   ·                   ·
 │              group by     @1                       ·                   ·
 │              ordered      @1                       ·                   ·
 └── render     ·            ·                        (x, y)              x!=NULL; key(x); +x
      │         render 0     test.public.group_ord.x  ·                   ·
      │         render 1     test.public.group_ord.y  ·                   ·
      └── scan  ·            ·                        (x, y, z[omitted])  x!=NULL; key(x); +x
·               table        group_ord@primary        ·                   ·
·               spans        ALL                      ·                   ·

# The ordering is on some of the GROUP BY columns, and isn't preserved after
# the aggregation.
query TTTTT
EXPLAIN (VERBOSE) SELECT z, x, max(y) FROM group_ord GROUP BY x, z
----
group           ·            ·                        (z, x, max)  x!=NULL; key(x)
 │              aggregate 0  z                        ·            ·
 │              aggregate 1  x                        ·            ·
 │              aggregate 2  max(y)                   ·            ·
 │              group by     @1-@2                    ·            ·
 │              ordered      @1                       ·            ·
 └── render     ·            ·                        (x, z, y)    x!=NULL; key(x); +x
      │         render 0     test.public.group_ord.x  ·            ·
      │         render 1     test.public.group_ord.z  ·            ·
      │         render 2     test.public.group_ord.y  ·            ·
      └── scan  ·            ·                        (x, y, z)    x!=NULL; key(x); +x
·               table        group_ord@primary        ·            ·
·               spans        ALL                      ·            ·

# The ordering is on some of the GROUP BY columns, and is preserved after
# the aggregation.
query TTTTT
EXPLAIN (VERBOSE) SELECT z, x, max(y) FROM group_ord GROUP BY x, z ORDER BY x
----
group           ·            ·                        (z, x, max)  x!=NULL; key(x); +x
 │              aggregate 0  z                        ·            ·
 │              aggregate 1  x                        ·            ·
 │              aggregate 2  max(y)                   ·            ·
 │              group by     @1-@2                    ·            ·
 │              ordered      @1                       ·            ·
 └── render     ·            ·                        (x, z, y)    x!=NULL; key(x); +x
      │         render 0     test.public.group_ord.x  ·            ·
      │         render 1     test.public.group_ord.z  ·            ·
      │         render 2     test.public.group_ord.y  ·            ·
      └── scan  ·            ·                        (x, y, z)    x!=NULL; key(x); +x
·               table        group_ord@primary        ·            ·
·               spans        ALL                      ·            ·

# If the underlying ordering isn't from the primary index, it needs to be hinted
# for now.
query TTTTT
EXPLAIN (VERBOSE) SELECT z, max(y) FROM group_ord@foo GROUP BY z
----
group                 ·            ·                        (z, max)                     weak-key(z)
 │                    aggregate 0  z                        ·                            ·
 │                    aggregate 1  max(y)                   ·                            ·
 │                    group by     @1                       ·                            ·
 │                    ordered      @1                       ·                            ·
 └── render           ·            ·                        (z, y)                       +z
      │               render 0     test.public.group_ord.z  ·                            ·
      │               render 1     test.public.group_ord.y  ·                            ·
      └── index-join  ·            ·                        (x[omitted], y, z)           x!=NULL; weak-key(x,z); +z
           │          table        group_ord@primary        ·                            ·
           └── scan   ·            ·                        (x, y[omitted], z[omitted])  x!=NULL; weak-key(x,z); +z
·                     table        group_ord@foo            ·                            ·
·                     spans        ALL                      ·                            ·

# Test that a merge join is used on two aggregate subqueries with orderings on
# the GROUP BY columns. Note that an ORDER BY is not necessary on the
# subqueries.
query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM (SELECT x, max(y) FROM group_ord GROUP BY x) JOIN (SELECT z, min(y) FROM group_ord@foo GROUP BY z) ON x = z
----
merge-join                 ·               ·                        (x, max, z, min)             x=z; x!=NULL
 │                         type            inner                    ·                            ·
 │                         equality        (x) = (z)                ·                            ·
 │                         mergeJoinOrder  +"(x=z)"                 ·                            ·
 ├── group                 ·               ·                        (x, max)                     x!=NULL; key(x); +x
 │    │                    aggregate 0     x                        ·                            ·
 │    │                    aggregate 1     max(y)                   ·                            ·
 │    │                    group by        @1                       ·                            ·
 │    │                    ordered         @1                       ·                            ·
 │    └── render           ·               ·                        (x, y)                       x!=NULL; key(x); +x
 │         │               render 0        test.public.group_ord.x  ·                            ·
 │         │               render 1        test.public.group_ord.y  ·                            ·
 │         └── scan        ·               ·                        (x, y, z[omitted])           x!=NULL; key(x); +x
 │                         table           group_ord@primary        ·                            ·
 │                         spans           ALL                      ·                            ·
 └── group                 ·               ·                        (z, min)                     weak-key(z); +z
      │                    aggregate 0     z                        ·                            ·
      │                    aggregate 1     min(y)                   ·                            ·
      │                    group by        @1                       ·                            ·
      │                    ordered         @1                       ·                            ·
      └── render           ·               ·                        (z, y)                       +z
           │               render 0        test.public.group_ord.z  ·                            ·
           │               render 1        test.public.group_ord.y  ·                            ·
           └── index-join  ·               ·                        (x[omitted], y, z)           x!=NULL; weak-key(x,z); +z
                │          table           group_ord@primary        ·                            ·
                └── scan   ·               ·                        (x, y[omitted], z[omitted])  x!=NULL; weak-key(x,z); +z
·                          table           group_ord@foo            ·                            ·
·                          spans           ALL                      ·                            ·

# Regression test for #25533 (crash when propagating filter through GROUP BY).
query TTTTT
EXPLAIN (VERBOSE) SELECT 1 a FROM kv GROUP BY v, w::DECIMAL HAVING w::DECIMAL > 1;
----
render                    ·            ·                          (a)                             a=CONST
 │                        render 0     1                          ·                               ·
 └── group                ·            ·                          (agg0)                          weak-key(agg0)
      │                   aggregate 0  w                          ·                               ·
      │                   group by     @1-@2                      ·                               ·
      └── filter          ·            ·                          (v, w)                          w!=NULL
           │              filter       w > 1                      ·                               ·
           └── render     ·            ·                          (v, w)                          ·
                │         render 0     test.public.kv.v           ·                               ·
                │         render 1     test.public.kv.w::DECIMAL  ·                               ·
                └── scan  ·            ·                          (k[omitted], v, w, s[omitted])  k!=NULL; key(k)
·                         table        kv@primary                 ·                               ·
·                         spans        ALL                        ·                               ·

# Regression test for #26419
query TTTTT
EXPLAIN (VERBOSE) SELECT 123 a FROM kv ORDER BY max(v)
----
sort                      ·            ·                 (a)                                      a=CONST
 │                        order        +max              ·                                        ·
 └── render               ·            ·                 (a, max)                                 a=CONST
      │                   render 0     123               ·                                        ·
      │                   render 1     agg0              ·                                        ·
      └── group           ·            ·                 (agg0)                                   ·
           │              aggregate 0  max(v)            ·                                        ·
           │              scalar       ·                 ·                                        ·
           └── render     ·            ·                 (v)                                      v!=NULL
                │         render 0     test.public.kv.v  ·                                        ·
                └── scan  ·            ·                 (k[omitted], v, w[omitted], s[omitted])  k!=NULL; v!=NULL; key(k)
·                         table        kv@primary        ·                                        ·
·                         spans        ALL               ·                                        ·
·                         filter       v IS NOT NULL     ·                                        ·

# Limitation test for #26349
statement error HAVING clause without FROM
SELECT 1 HAVING false
