Skip to content

Commit 8a3d454

Browse files
committed
More tests.
1 parent fa7516c commit 8a3d454

File tree

4 files changed

+77
-12
lines changed

4 files changed

+77
-12
lines changed

ext/stats/TODO.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,12 @@ https://sqlite.org/lang_aggfunc.html
4444
- [ ] `PERCENTILE_CONT(percentile) OVER window`
4545
- [ ] `PERCENTILE_DISC(percentile) OVER window`
4646

47-
https://sqlite.org/windowfunctions.html#builtins
47+
https://sqlite.org/windowfunctions.html#builtins
48+
49+
## Additional aggregates
50+
51+
- [X] `MEDIAN(expression)`
52+
- [X] `QUANTILE_CONT(expression, quantile)`
53+
- [X] `QUANTILE_DISC(expression, quantile)`
54+
55+
https://duckdb.org/docs/sql/aggregates.html

ext/stats/quantile.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (q *quantile) Step(ctx sqlite3.Context, arg ...sqlite3.Value) {
3535
}
3636

3737
func (q *quantile) Value(ctx sqlite3.Context) {
38-
if q.list == nil {
38+
if len(q.list) == 0 {
3939
return
4040
}
4141
if q.kind == median {
@@ -49,7 +49,7 @@ func (q *quantile) Value(ctx sqlite3.Context) {
4949
i, f := math.Modf(q.pos * float64(len(q.list)-1))
5050
m0 := quick.Select(q.list, int(i))
5151

52-
if q.kind == quant_disc {
52+
if f == 0 || q.kind == quant_disc {
5353
ctx.ResultFloat(m0)
5454
return
5555
}

ext/stats/quantile_test.go

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,80 @@ func TestRegister_quantile(t *testing.T) {
3434
SELECT
3535
median(x),
3636
quantile_disc(x, 0.5),
37-
quantile_cont(x, 0.3)
37+
quantile_cont(x, 0.25)
3838
FROM data`)
3939
if err != nil {
4040
t.Fatal(err)
4141
}
42-
defer stmt.Close()
43-
4442
if stmt.Step() {
4543
if got := stmt.ColumnFloat(0); got != 10 {
4644
t.Errorf("got %v, want 10", got)
4745
}
4846
if got := stmt.ColumnFloat(1); got != 7 {
4947
t.Errorf("got %v, want 7", got)
5048
}
51-
if got := stmt.ColumnFloat(2); got != 6.699999999999999 {
52-
t.Errorf("got %v, want 6.7", got)
49+
if got := stmt.ColumnFloat(2); got != 6.25 {
50+
t.Errorf("got %v, want 6.25", got)
5351
}
5452
}
53+
stmt.Close()
54+
55+
stmt, _, err = db.Prepare(`
56+
SELECT
57+
median(x),
58+
quantile_disc(x, 0.5),
59+
quantile_cont(x, 0.25)
60+
FROM data
61+
WHERE x < 5`)
62+
if err != nil {
63+
t.Fatal(err)
64+
}
65+
if stmt.Step() {
66+
if got := stmt.ColumnFloat(0); got != 4 {
67+
t.Errorf("got %v, want 4", got)
68+
}
69+
if got := stmt.ColumnFloat(1); got != 4 {
70+
t.Errorf("got %v, want 4", got)
71+
}
72+
if got := stmt.ColumnFloat(2); got != 4 {
73+
t.Errorf("got %v, want 4", got)
74+
}
75+
}
76+
stmt.Close()
77+
78+
stmt, _, err = db.Prepare(`
79+
SELECT
80+
median(x),
81+
quantile_disc(x, 0.5),
82+
quantile_cont(x, 0.25)
83+
FROM data
84+
WHERE x < 0`)
85+
if err != nil {
86+
t.Fatal(err)
87+
}
88+
if stmt.Step() {
89+
if got := stmt.ColumnType(0); got != sqlite3.NULL {
90+
t.Error("want NULL")
91+
}
92+
if got := stmt.ColumnType(1); got != sqlite3.NULL {
93+
t.Error("want NULL")
94+
}
95+
if got := stmt.ColumnType(2); got != sqlite3.NULL {
96+
t.Error("want NULL")
97+
}
98+
}
99+
stmt.Close()
100+
101+
stmt, _, err = db.Prepare(`
102+
SELECT
103+
quantile_disc(x, -2),
104+
quantile_cont(x, +2)
105+
FROM data`)
106+
if err != nil {
107+
t.Fatal(err)
108+
}
109+
if stmt.Step() {
110+
t.Fatal("want error")
111+
}
112+
stmt.Close()
55113
}

ext/stats/stats.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
// - regr_slope: slope of the least-squares-fit linear equation
1919
// - regr_intercept: y-intercept of the least-squares-fit linear equation
2020
// - regr_json: all regr stats in a JSON object
21-
// - median: median value
22-
// - quantile_cont: continuous quantile
2321
// - quantile_disc: discrete quantile
22+
// - quantile_cont: continuous quantile
23+
// - median: median value
2424
//
2525
// These join the [Built-in Aggregate Functions]:
2626
// - count: count rows/values
@@ -29,8 +29,7 @@
2929
// - min: minimum value
3030
// - max: maximum value
3131
//
32-
// See: [ANSI SQL Aggregate Functions]
33-
// See: [DuckDB Aggregate Functions]
32+
// See: [ANSI SQL Aggregate Functions], [DuckDB Aggregate Functions]
3433
//
3534
// [Built-in Aggregate Functions]: https://sqlite.org/lang_aggfunc.html
3635
// [ANSI SQL Aggregate Functions]: https://www.oreilly.com/library/view/sql-in-a/9780596155322/ch04s02.html

0 commit comments

Comments
 (0)