exec-ddl
CREATE TABLE a (k INT PRIMARY KEY, i INT, s STRING, d DECIMAL NOT NULL)
----

exec-ddl
CREATE TABLE b (k INT PRIMARY KEY, a INT, b INT, c INT, INDEX (a, b), INDEX (a, b, c))
----

exec-ddl
CREATE TABLE c (a INT, b INT, c INT, d INT, INDEX (a), INDEX (b, c, d))
----

opt
SELECT max(k), min(k), i, s FROM a GROUP BY i, s
----
group-by (hash)
 ├── columns: max:7!null min:8!null i:2 s:3
 ├── grouping columns: i:2 s:3
 ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
 ├── cost: 1158.89625
 ├── key: (2,3)
 ├── fd: (2,3)-->(7,8)
 ├── scan a
 │    ├── columns: k:1!null i:2 s:3
 │    ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
 │    ├── cost: 1098.72
 │    ├── key: (1)
 │    └── fd: (1)-->(2,3)
 └── aggregations
      ├── max [as=max:7, outer=(1)]
      │    └── k:1
      └── min [as=min:8, outer=(1)]
           └── k:1

opt
SELECT a, count(*) FROM b GROUP BY a
----
group-by (streaming)
 ├── columns: a:2 count:7!null
 ├── grouping columns: a:2
 ├── internal-ordering: +2
 ├── stats: [rows=100, distinct(2)=100, null(2)=1]
 ├── cost: 1089.45
 ├── key: (2)
 ├── fd: (2)-->(7)
 ├── scan b@b_a_b_idx
 │    ├── columns: a:2
 │    ├── stats: [rows=1000, distinct(2)=100, null(2)=10]
 │    ├── cost: 1068.42
 │    └── ordering: +2
 └── aggregations
      └── count-rows [as=count_rows:7]

opt
SELECT a, b, count(*) FROM b GROUP BY a, b
----
group-by (streaming)
 ├── columns: a:2 b:3 count:7!null
 ├── grouping columns: a:2 b:3
 ├── internal-ordering: +2,+3
 ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
 ├── cost: 1118.55
 ├── key: (2,3)
 ├── fd: (2,3)-->(7)
 ├── scan b@b_a_b_idx
 │    ├── columns: a:2 b:3
 │    ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
 │    ├── cost: 1078.52
 │    └── ordering: +2,+3
 └── aggregations
      └── count-rows [as=count_rows:7]

# Consider a limit hint when costing streaming GroupBy expressions.
opt
SELECT a, count(*) FROM b GROUP BY a LIMIT 10
----
limit
 ├── columns: a:2 count:7!null
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10]
 ├── cost: 125.16
 ├── key: (2)
 ├── fd: (2)-->(7)
 ├── group-by (streaming)
 │    ├── columns: a:2 count_rows:7!null
 │    ├── grouping columns: a:2
 │    ├── internal-ordering: +2
 │    ├── stats: [rows=100, distinct(2)=100, null(2)=1]
 │    ├── cost: 125.05
 │    ├── key: (2)
 │    ├── fd: (2)-->(7)
 │    ├── limit hint: 10.00
 │    ├── scan b@b_a_b_idx
 │    │    ├── columns: a:2
 │    │    ├── stats: [rows=1000, distinct(2)=100, null(2)=10]
 │    │    ├── cost: 122.02
 │    │    ├── ordering: +2
 │    │    └── limit hint: 100.00
 │    └── aggregations
 │         └── count-rows [as=count_rows:7]
 └── 10

opt
SELECT a, b, count(*) FROM b GROUP BY a, b LIMIT 10
----
limit
 ├── columns: a:2 b:3 count:7!null
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10]
 ├── cost: 38.96
 ├── key: (2,3)
 ├── fd: (2,3)-->(7)
 ├── group-by (streaming)
 │    ├── columns: a:2 b:3 count_rows:7!null
 │    ├── grouping columns: a:2 b:3
 │    ├── internal-ordering: +2,+3
 │    ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
 │    ├── cost: 38.85
 │    ├── key: (2,3)
 │    ├── fd: (2,3)-->(7)
 │    ├── limit hint: 10.00
 │    ├── scan b@b_a_b_idx
 │    │    ├── columns: a:2 b:3
 │    │    ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
 │    │    ├── cost: 28.52
 │    │    ├── ordering: +2,+3
 │    │    └── limit hint: 10.00
 │    └── aggregations
 │         └── count-rows [as=count_rows:7]
 └── 10

opt
SELECT DISTINCT a FROM b
----
distinct-on
 ├── columns: a:2
 ├── grouping columns: a:2
 ├── internal-ordering: +2
 ├── stats: [rows=100, distinct(2)=100, null(2)=1]
 ├── cost: 1079.45
 ├── key: (2)
 └── scan b@b_a_b_idx
      ├── columns: a:2
      ├── stats: [rows=1000, distinct(2)=100, null(2)=10]
      ├── cost: 1068.42
      └── ordering: +2

opt
SELECT DISTINCT a FROM b LIMIT 10
----
limit
 ├── columns: a:2
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10]
 ├── cost: 32.5488337
 ├── key: (2)
 ├── distinct-on
 │    ├── columns: a:2
 │    ├── grouping columns: a:2
 │    ├── internal-ordering: +2
 │    ├── stats: [rows=100, distinct(2)=100, null(2)=1]
 │    ├── cost: 32.4388337
 │    ├── key: (2)
 │    ├── limit hint: 10.00
 │    └── scan b@b_a_b_idx
 │         ├── columns: a:2
 │         ├── stats: [rows=1000, distinct(2)=100, null(2)=10]
 │         ├── cost: 31.281321
 │         ├── ordering: +2
 │         └── limit hint: 12.75
 └── 10

opt set=(optimizer_use_improved_distinct_on_limit_hint_costing=false)
SELECT DISTINCT a FROM b LIMIT 10
----
limit
 ├── columns: a:2
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10]
 ├── cost: 42.421321
 ├── key: (2)
 ├── distinct-on
 │    ├── columns: a:2
 │    ├── grouping columns: a:2
 │    ├── internal-ordering: +2
 │    ├── stats: [rows=100, distinct(2)=100, null(2)=1]
 │    ├── cost: 42.311321
 │    ├── key: (2)
 │    ├── limit hint: 10.00
 │    └── scan b@b_a_b_idx
 │         ├── columns: a:2
 │         ├── stats: [rows=1000, distinct(2)=100, null(2)=10]
 │         ├── cost: 31.281321
 │         ├── ordering: +2
 │         └── limit hint: 12.75
 └── 10

opt
SELECT DISTINCT a, b FROM b
----
distinct-on
 ├── columns: a:2 b:3
 ├── grouping columns: a:2 b:3
 ├── internal-ordering: +2,+3
 ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
 ├── cost: 1108.55
 ├── key: (2,3)
 └── scan b@b_a_b_idx
      ├── columns: a:2 b:3
      ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
      ├── cost: 1078.52
      └── ordering: +2,+3

opt
SELECT DISTINCT a, b FROM b LIMIT 10
----
limit
 ├── columns: a:2 b:3
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10]
 ├── cost: 41.0744319
 ├── key: (2,3)
 ├── distinct-on
 │    ├── columns: a:2 b:3
 │    ├── grouping columns: a:2 b:3
 │    ├── internal-ordering: +2,+3
 │    ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
 │    ├── cost: 40.9644319
 │    ├── key: (2,3)
 │    ├── limit hint: 10.00
 │    └── scan b@b_a_b_idx
 │         ├── columns: a:2 b:3
 │         ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
 │         ├── cost: 30.6930407
 │         ├── ordering: +2,+3
 │         └── limit hint: 12.07
 └── 10

# Partially ordered group by with a limit hint.
opt
SELECT a, c, count(*) FROM c GROUP BY a, c LIMIT 10
----
limit
 ├── columns: a:1 c:3 count:8!null
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10]
 ├── cost: 645.98
 ├── key: (1,3)
 ├── fd: (1,3)-->(8)
 ├── group-by (partial streaming)
 │    ├── columns: a:1 c:3 count_rows:8!null
 │    ├── grouping columns: a:1 c:3
 │    ├── internal-ordering: +1
 │    ├── stats: [rows=1000, distinct(1,3)=1000, null(1,3)=0.1]
 │    ├── cost: 645.87
 │    ├── key: (1,3)
 │    ├── fd: (1,3)-->(8)
 │    ├── limit hint: 10.00
 │    ├── index-join c
 │    │    ├── columns: a:1 c:3
 │    │    ├── stats: [rows=1000, distinct(1,3)=1000, null(1,3)=0.1]
 │    │    ├── cost: 635.44
 │    │    ├── ordering: +1
 │    │    ├── limit hint: 10.00
 │    │    └── scan c@c_a_idx
 │    │         ├── columns: a:1 rowid:5!null
 │    │         ├── stats: [rows=1000, distinct(1)=100, null(1)=10]
 │    │         ├── cost: 28.42
 │    │         ├── key: (5)
 │    │         ├── fd: (5)-->(1)
 │    │         ├── ordering: +1
 │    │         └── limit hint: 10.00
 │    └── aggregations
 │         └── count-rows [as=count_rows:8]
 └── 10

opt
SELECT b, d, count(*) FROM c GROUP BY b, d LIMIT 10
----
limit
 ├── columns: b:2 d:4 count:8!null
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10]
 ├── cost: 39.16
 ├── key: (2,4)
 ├── fd: (2,4)-->(8)
 ├── group-by (partial streaming)
 │    ├── columns: b:2 d:4 count_rows:8!null
 │    ├── grouping columns: b:2 d:4
 │    ├── internal-ordering: +2
 │    ├── stats: [rows=1000, distinct(2,4)=1000, null(2,4)=0.1]
 │    ├── cost: 39.05
 │    ├── key: (2,4)
 │    ├── fd: (2,4)-->(8)
 │    ├── limit hint: 10.00
 │    ├── scan c@c_b_c_d_idx
 │    │    ├── columns: b:2 d:4
 │    │    ├── stats: [rows=1000, distinct(2,4)=1000, null(2,4)=0.1]
 │    │    ├── cost: 28.62
 │    │    ├── ordering: +2
 │    │    └── limit hint: 10.00
 │    └── aggregations
 │         └── count-rows [as=count_rows:8]
 └── 10

opt
SELECT b, a, count(*) FROM c GROUP BY b, a LIMIT 10
----
limit
 ├── columns: b:2 a:1 count:8!null
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10]
 ├── cost: 645.98
 ├── key: (1,2)
 ├── fd: (1,2)-->(8)
 ├── group-by (partial streaming)
 │    ├── columns: a:1 b:2 count_rows:8!null
 │    ├── grouping columns: a:1 b:2
 │    ├── internal-ordering: +1
 │    ├── stats: [rows=1000, distinct(1,2)=1000, null(1,2)=0.1]
 │    ├── cost: 645.87
 │    ├── key: (1,2)
 │    ├── fd: (1,2)-->(8)
 │    ├── limit hint: 10.00
 │    ├── index-join c
 │    │    ├── columns: a:1 b:2
 │    │    ├── stats: [rows=1000, distinct(1,2)=1000, null(1,2)=0.1]
 │    │    ├── cost: 635.44
 │    │    ├── ordering: +1
 │    │    ├── limit hint: 10.00
 │    │    └── scan c@c_a_idx
 │    │         ├── columns: a:1 rowid:5!null
 │    │         ├── stats: [rows=1000, distinct(1)=100, null(1)=10]
 │    │         ├── cost: 28.42
 │    │         ├── key: (5)
 │    │         ├── fd: (5)-->(1)
 │    │         ├── ordering: +1
 │    │         └── limit hint: 10.00
 │    └── aggregations
 │         └── count-rows [as=count_rows:8]
 └── 10

opt
SELECT b, c, a, count(*) FROM c GROUP BY b, c, a LIMIT 10
----
limit
 ├── columns: b:2 c:3 a:1 count:8!null
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10]
 ├── cost: 646.38
 ├── key: (1-3)
 ├── fd: (1-3)-->(8)
 ├── group-by (partial streaming)
 │    ├── columns: a:1 b:2 c:3 count_rows:8!null
 │    ├── grouping columns: a:1 b:2 c:3
 │    ├── internal-ordering: +2,+3
 │    ├── stats: [rows=1000, distinct(1-3)=1000, null(1-3)=0.001]
 │    ├── cost: 646.27
 │    ├── key: (1-3)
 │    ├── fd: (1-3)-->(8)
 │    ├── limit hint: 10.00
 │    ├── index-join c
 │    │    ├── columns: a:1 b:2 c:3
 │    │    ├── stats: [rows=1000, distinct(1-3)=1000, null(1-3)=0.001]
 │    │    ├── cost: 635.74
 │    │    ├── ordering: +2,+3
 │    │    ├── limit hint: 10.00
 │    │    └── scan c@c_b_c_d_idx
 │    │         ├── columns: b:2 c:3 rowid:5!null
 │    │         ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1]
 │    │         ├── cost: 28.72
 │    │         ├── key: (5)
 │    │         ├── fd: (5)-->(2,3)
 │    │         ├── ordering: +2,+3
 │    │         └── limit hint: 10.00
 │    └── aggregations
 │         └── count-rows [as=count_rows:8]
 └── 10

exec-ddl
CREATE TABLE f (
  filename
    STRING PRIMARY KEY,
  file_id
    UUID DEFAULT gen_random_uuid() NOT NULL UNIQUE,
  file_size
    INT8 NOT NULL,
  username
    STRING NOT NULL,
  upload_time
    TIMESTAMP DEFAULT now()
)
----

exec-ddl
CREATE TABLE p (file_id UUID, byte_offset INT8, payload BYTES, PRIMARY KEY (file_id, byte_offset))
----

# Non-scalar group-by with no grouping columns should be streaming: #71768
opt
SELECT f.file_id, sum_int(length(p.payload)) FROM f f LEFT OUTER JOIN p p ON p.file_id = f.file_id WHERE f.filename = 'abc' GROUP BY f.file_id
----
group-by (streaming)
 ├── columns: file_id:2!null sum_int:14
 ├── cardinality: [0 - 1]
 ├── immutable
 ├── stats: [rows=1]
 ├── cost: 54.15
 ├── key: ()
 ├── fd: ()-->(2,14)
 ├── project
 │    ├── columns: column13:13 f.file_id:2!null
 │    ├── immutable
 │    ├── stats: [rows=10]
 │    ├── cost: 53.92
 │    ├── fd: ()-->(2)
 │    ├── left-join (lookup p)
 │    │    ├── columns: filename:1!null f.file_id:2!null p.file_id:8 payload:10
 │    │    ├── key columns: [2] = [8]
 │    │    ├── stats: [rows=10, distinct(8)=1, null(8)=0]
 │    │    ├── cost: 53.7
 │    │    ├── fd: ()-->(1,2,8)
 │    │    ├── scan f
 │    │    │    ├── columns: filename:1!null f.file_id:2!null
 │    │    │    ├── constraint: /1: [/'abc' - /'abc']
 │    │    │    ├── cardinality: [0 - 1]
 │    │    │    ├── stats: [rows=1, distinct(1)=1, null(1)=0, distinct(2)=1, null(2)=0]
 │    │    │    ├── cost: 9.08
 │    │    │    ├── key: ()
 │    │    │    └── fd: ()-->(1,2)
 │    │    └── filters (true)
 │    └── projections
 │         └── length(payload:10) [as=column13:13, outer=(10), immutable]
 └── aggregations
      ├── sum-int [as=sum_int:14, outer=(13)]
      │    └── column13:13
      └── const-agg [as=f.file_id:2, outer=(2)]
           └── f.file_id:2
