Skip to content

Commit 34d0289

Browse files
committed
Rename to percentile.
1 parent dbf764a commit 34d0289

File tree

4 files changed

+38
-38
lines changed

4 files changed

+38
-38
lines changed

ext/stats/TODO.md

+2-6
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ https://sqlite.org/lang_aggfunc.html
4141
- [X] `RANK() OVER window`
4242
- [X] `DENSE_RANK() OVER window`
4343
- [X] `PERCENT_RANK() OVER window`
44-
- [ ] `PERCENTILE_CONT(percentile) OVER window`
45-
- [ ] `PERCENTILE_DISC(percentile) OVER window`
4644

4745
https://sqlite.org/windowfunctions.html#builtins
4846

@@ -54,7 +52,5 @@ https://sqlite.org/windowfunctions.html#builtins
5452
## Additional aggregates
5553

5654
- [X] `MEDIAN(expression)`
57-
- [X] `QUANTILE_CONT(expression, quantile)`
58-
- [X] `QUANTILE_DISC(expression, quantile)`
59-
60-
https://duckdb.org/docs/sql/aggregates.html
55+
- [X] `PERCENTILE_CONT(expression, fraction)`
56+
- [X] `PERCENTILE_DISC(expression, fraction)`

ext/stats/quantile.go renamed to ext/stats/percentile.go

+19-14
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@ import (
1313

1414
const (
1515
median = iota
16-
quant_cont
17-
quant_disc
16+
percentile_cont
17+
percentile_disc
1818
)
1919

20-
func newQuantile(kind int) func() sqlite3.AggregateFunction {
21-
return func() sqlite3.AggregateFunction { return &quantile{kind: kind} }
20+
func newPercentile(kind int) func() sqlite3.AggregateFunction {
21+
return func() sqlite3.AggregateFunction { return &percentile{kind: kind} }
2222
}
2323

24-
type quantile struct {
24+
type percentile struct {
2525
nums []float64
2626
arg1 []byte
2727
kind int
2828
}
2929

30-
func (q *quantile) Step(ctx sqlite3.Context, arg ...sqlite3.Value) {
30+
func (q *percentile) Step(ctx sqlite3.Context, arg ...sqlite3.Value) {
3131
if a := arg[0]; a.NumericType() != sqlite3.NULL {
3232
q.nums = append(q.nums, a.Float())
3333
}
@@ -36,7 +36,12 @@ func (q *quantile) Step(ctx sqlite3.Context, arg ...sqlite3.Value) {
3636
}
3737
}
3838

39-
func (q *quantile) Value(ctx sqlite3.Context) {
39+
func (q *percentile) Inverse(ctx sqlite3.Context, arg ...sqlite3.Value) {
40+
// Implementing inverse allows certain queries that don't really need it to succeed.
41+
ctx.ResultError(util.ErrorString("percentile: may not be used as a window function"))
42+
}
43+
44+
func (q *percentile) Value(ctx sqlite3.Context) {
4045
if len(q.nums) == 0 {
4146
return
4247
}
@@ -47,21 +52,21 @@ func (q *quantile) Value(ctx sqlite3.Context) {
4752
floats []float64
4853
)
4954
if q.kind == median {
50-
float, err = getQuantile(q.nums, 0.5, false)
55+
float, err = getPercentile(q.nums, 0.5, false)
5156
ctx.ResultFloat(float)
5257
} else if err = json.Unmarshal(q.arg1, &float); err == nil {
53-
float, err = getQuantile(q.nums, float, q.kind == quant_disc)
58+
float, err = getPercentile(q.nums, float, q.kind == percentile_disc)
5459
ctx.ResultFloat(float)
5560
} else if err = json.Unmarshal(q.arg1, &floats); err == nil {
56-
err = getQuantiles(q.nums, floats, q.kind == quant_disc)
61+
err = getPercentiles(q.nums, floats, q.kind == percentile_disc)
5762
ctx.ResultJSON(floats)
5863
}
5964
if err != nil {
60-
ctx.ResultError(fmt.Errorf("quantile: %w", err))
65+
ctx.ResultError(fmt.Errorf("percentile: %w", err))
6166
}
6267
}
6368

64-
func getQuantile(nums []float64, pos float64, disc bool) (float64, error) {
69+
func getPercentile(nums []float64, pos float64, disc bool) (float64, error) {
6570
if pos < 0 || pos > 1 {
6671
return 0, util.ErrorString("invalid pos")
6772
}
@@ -77,9 +82,9 @@ func getQuantile(nums []float64, pos float64, disc bool) (float64, error) {
7782
return math.FMA(f, m1, -math.FMA(f, m0, -m0)), nil
7883
}
7984

80-
func getQuantiles(nums []float64, pos []float64, disc bool) error {
85+
func getPercentiles(nums []float64, pos []float64, disc bool) error {
8186
for i := range pos {
82-
v, err := getQuantile(nums, pos[i], disc)
87+
v, err := getPercentile(nums, pos[i], disc)
8388
if err != nil {
8489
return err
8590
}

ext/stats/quantile_test.go renamed to ext/stats/percentile_test.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
_ "github.com/ncruces/go-sqlite3/internal/testcfg"
1111
)
1212

13-
func TestRegister_quantile(t *testing.T) {
13+
func TestRegister_percentile(t *testing.T) {
1414
t.Parallel()
1515

1616
db, err := sqlite3.Open(":memory:")
@@ -34,8 +34,8 @@ func TestRegister_quantile(t *testing.T) {
3434
stmt, _, err := db.Prepare(`
3535
SELECT
3636
median(x),
37-
quantile_disc(x, 0.5),
38-
quantile_cont(x, '[0.25, 0.5, 0.75]')
37+
percentile_disc(x, 0.5),
38+
percentile_cont(x, '[0.25, 0.5, 0.75]')
3939
FROM data`)
4040
if err != nil {
4141
t.Fatal(err)
@@ -60,8 +60,8 @@ func TestRegister_quantile(t *testing.T) {
6060
stmt, _, err = db.Prepare(`
6161
SELECT
6262
median(x),
63-
quantile_disc(x, 0.5),
64-
quantile_cont(x, '[0.25, 0.5, 0.75]')
63+
percentile_disc(x, 0.5),
64+
percentile_cont(x, '[0.25, 0.5, 0.75]')
6565
FROM data
6666
WHERE x < 5`)
6767
if err != nil {
@@ -87,8 +87,8 @@ func TestRegister_quantile(t *testing.T) {
8787
stmt, _, err = db.Prepare(`
8888
SELECT
8989
median(x),
90-
quantile_disc(x, 0.5),
91-
quantile_cont(x, '[0.25, 0.5, 0.75]')
90+
percentile_disc(x, 0.5),
91+
percentile_cont(x, '[0.25, 0.5, 0.75]')
9292
FROM data
9393
WHERE x < 0`)
9494
if err != nil {
@@ -109,10 +109,10 @@ func TestRegister_quantile(t *testing.T) {
109109

110110
stmt, _, err = db.Prepare(`
111111
SELECT
112-
quantile_disc(x, -2),
113-
quantile_cont(x, +2),
114-
quantile_cont(x, ''),
115-
quantile_cont(x, '[100]')
112+
percentile_disc(x, -2),
113+
percentile_cont(x, +2),
114+
percentile_cont(x, ''),
115+
percentile_cont(x, '[100]')
116116
FROM data`)
117117
if err != nil {
118118
t.Fatal(err)

ext/stats/stats.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
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-
// - quantile_disc: discrete quantile
22-
// - quantile_cont: continuous quantile
21+
// - percentile_disc: discrete percentile
22+
// - percentile_cont: continuous percentile
2323
// - median: median value
2424
// - every: boolean and
2525
// - some: boolean or
@@ -37,12 +37,11 @@
3737
// - percent_rank: relative rank of the row
3838
// - cume_dist: cumulative distribution
3939
//
40-
// See: [ANSI SQL Aggregate Functions], [DuckDB Aggregate Functions]
40+
// See: [ANSI SQL Aggregate Functions]
4141
//
4242
// [Built-in Aggregate Functions]: https://sqlite.org/lang_aggfunc.html
4343
// [Built-in Window Functions]: https://sqlite.org/windowfunctions.html#builtins
4444
// [ANSI SQL Aggregate Functions]: https://www.oreilly.com/library/view/sql-in-a/9780596155322/ch04s02.html
45-
// [DuckDB Aggregate Functions]: https://duckdb.org/docs/sql/aggregates.html
4645
package stats
4746

4847
import "github.com/ncruces/go-sqlite3"
@@ -67,9 +66,9 @@ func Register(db *sqlite3.Conn) {
6766
db.CreateWindowFunction("regr_intercept", 2, flags, newCovariance(regr_intercept))
6867
db.CreateWindowFunction("regr_count", 2, flags, newCovariance(regr_count))
6968
db.CreateWindowFunction("regr_json", 2, flags, newCovariance(regr_json))
70-
db.CreateWindowFunction("median", 1, flags, newQuantile(median))
71-
db.CreateWindowFunction("quantile_cont", 2, flags, newQuantile(quant_cont))
72-
db.CreateWindowFunction("quantile_disc", 2, flags, newQuantile(quant_disc))
69+
db.CreateWindowFunction("median", 1, flags, newPercentile(median))
70+
db.CreateWindowFunction("percentile_cont", 2, flags, newPercentile(percentile_cont))
71+
db.CreateWindowFunction("percentile_disc", 2, flags, newPercentile(percentile_disc))
7372
db.CreateWindowFunction("every", 1, flags, newBoolean(every))
7473
db.CreateWindowFunction("some", 1, flags, newBoolean(some))
7574
}

0 commit comments

Comments
 (0)