Files
sqlite3/ext/stats/percentile_test.go

174 lines
3.5 KiB
Go
Raw Permalink Normal View History

2024-05-31 17:36:16 +01:00
package stats_test
import (
2024-06-02 13:37:29 +01:00
"slices"
2024-05-31 17:36:16 +01:00
"testing"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
2024-06-02 10:33:20 +01:00
_ "github.com/ncruces/go-sqlite3/internal/testcfg"
2024-05-31 17:36:16 +01:00
)
2024-06-06 19:52:49 +01:00
func TestRegister_percentile(t *testing.T) {
2024-05-31 17:36:16 +01:00
t.Parallel()
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
err = db.Exec(`CREATE TABLE data (x)`)
if err != nil {
t.Fatal(err)
}
err = db.Exec(`INSERT INTO data (x) VALUES (4), (7.0), ('13'), (NULL), (16)`)
if err != nil {
t.Fatal(err)
}
stmt, _, err := db.Prepare(`
SELECT
median(x),
2024-10-16 14:00:22 +01:00
percentile(x, 50),
2024-06-06 19:52:49 +01:00
percentile_disc(x, 0.5),
percentile_cont(x, '[0.25, 0.5, 0.75]')
2024-05-31 17:36:16 +01:00
FROM data`)
if err != nil {
t.Fatal(err)
}
2025-07-17 01:11:16 +01:00
if !stmt.Step() {
t.Fatal(stmt.Err())
} else {
2024-05-31 17:36:16 +01:00
if got := stmt.ColumnFloat(0); got != 10 {
t.Errorf("got %v, want 10", got)
}
2024-10-16 14:00:22 +01:00
if got := stmt.ColumnFloat(1); got != 10 {
t.Errorf("got %v, want 10", got)
}
if got := stmt.ColumnFloat(2); got != 7 {
2024-05-31 17:36:16 +01:00
t.Errorf("got %v, want 7", got)
}
2024-06-02 13:37:29 +01:00
var got []float64
2024-10-16 14:00:22 +01:00
if err := stmt.ColumnJSON(3, &got); err != nil {
2024-06-02 13:37:29 +01:00
t.Error(err)
}
if !slices.Equal(got, []float64{6.25, 10, 13.75}) {
t.Errorf("got %v, want [6.25 10 13.75]", got)
2024-05-31 17:36:16 +01:00
}
}
2024-06-02 10:33:06 +01:00
stmt.Close()
2024-10-17 08:15:44 +01:00
stmt, _, err = db.Prepare(`
SELECT
median(x) OVER (ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
FROM data`)
if err != nil {
t.Fatal(err)
}
2025-07-17 01:11:16 +01:00
if !stmt.Step() {
t.Fatal(stmt.Err())
} else if got := stmt.ColumnFloat(0); got != 5.5 {
t.Errorf("got %v, want 5.5", got)
2024-10-17 08:15:44 +01:00
}
2025-07-17 01:11:16 +01:00
if !stmt.Step() {
t.Fatal(stmt.Err())
} else if got := stmt.ColumnFloat(0); got != 7 {
t.Errorf("got %v, want 7", got)
2024-10-17 08:15:44 +01:00
}
2025-07-17 01:11:16 +01:00
if !stmt.Step() {
t.Fatal(stmt.Err())
} else if got := stmt.ColumnFloat(0); got != 10 {
t.Errorf("got %v, want 10", got)
2024-10-17 08:15:44 +01:00
}
2025-07-17 01:11:16 +01:00
if !stmt.Step() {
t.Fatal(stmt.Err())
} else if got := stmt.ColumnFloat(0); got != 14.5 {
t.Errorf("got %v, want 14.5", got)
2024-10-17 08:15:44 +01:00
}
2025-07-17 01:11:16 +01:00
if !stmt.Step() {
t.Fatal(stmt.Err())
} else if got := stmt.ColumnFloat(0); got != 16 {
t.Errorf("got %v, want 16", got)
2024-10-17 08:15:44 +01:00
}
stmt.Close()
2024-06-02 10:33:06 +01:00
stmt, _, err = db.Prepare(`
SELECT
median(x),
2024-10-16 14:00:22 +01:00
percentile(x, 50),
2024-06-06 19:52:49 +01:00
percentile_disc(x, 0.5),
percentile_cont(x, '[0.25, 0.5, 0.75]')
2024-06-02 10:33:06 +01:00
FROM data
WHERE x < 5`)
if err != nil {
t.Fatal(err)
}
2025-07-17 01:11:16 +01:00
if !stmt.Step() {
t.Fatal(stmt.Err())
} else {
2024-06-02 10:33:06 +01:00
if got := stmt.ColumnFloat(0); got != 4 {
t.Errorf("got %v, want 4", got)
}
if got := stmt.ColumnFloat(1); got != 4 {
t.Errorf("got %v, want 4", got)
}
2024-10-16 14:00:22 +01:00
if got := stmt.ColumnFloat(2); got != 4 {
t.Errorf("got %v, want 4", got)
}
2024-06-02 13:37:29 +01:00
var got []float64
2024-10-16 14:00:22 +01:00
if err := stmt.ColumnJSON(3, &got); err != nil {
2024-06-02 13:37:29 +01:00
t.Error(err)
}
if !slices.Equal(got, []float64{4, 4, 4}) {
t.Errorf("got %v, want [4 4 4]", got)
2024-06-02 10:33:06 +01:00
}
}
stmt.Close()
stmt, _, err = db.Prepare(`
SELECT
median(x),
2024-10-16 14:00:22 +01:00
percentile(x, 50),
2024-06-06 19:52:49 +01:00
percentile_disc(x, 0.5),
percentile_cont(x, '[0.25, 0.5, 0.75]')
2024-06-02 10:33:06 +01:00
FROM data
WHERE x < 0`)
if err != nil {
t.Fatal(err)
}
2025-07-17 01:11:16 +01:00
if !stmt.Step() {
t.Fatal(stmt.Err())
} else {
2024-06-02 10:33:06 +01:00
if got := stmt.ColumnType(0); got != sqlite3.NULL {
t.Error("want NULL")
}
if got := stmt.ColumnType(1); got != sqlite3.NULL {
t.Error("want NULL")
}
if got := stmt.ColumnType(2); got != sqlite3.NULL {
t.Error("want NULL")
}
2024-10-16 14:00:22 +01:00
if got := stmt.ColumnType(3); got != sqlite3.NULL {
t.Error("want NULL")
}
2024-06-02 10:33:06 +01:00
}
stmt.Close()
stmt, _, err = db.Prepare(`
SELECT
2024-06-06 19:52:49 +01:00
percentile_disc(x, -2),
percentile_cont(x, +2),
percentile_cont(x, ''),
percentile_cont(x, '[100]')
2024-06-02 10:33:06 +01:00
FROM data`)
if err != nil {
t.Fatal(err)
}
if stmt.Step() {
2024-06-02 13:37:29 +01:00
t.Error("want error")
2024-06-02 10:33:06 +01:00
}
stmt.Close()
2024-05-31 17:36:16 +01:00
}