Add RDBMS DAL aggregation functions (avg, sum and count)
This commit is contained in:
parent
8d2718bef7
commit
fbf4410335
@ -7,6 +7,7 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"github.com/cortezaproject/corteza-server/store/adapters/rdbms"
|
||||
"os"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
_ "github.com/cortezaproject/corteza-server/store/adapters/rdbms/drivers/mysql"
|
||||
@ -34,8 +35,8 @@ func TestMain(m *testing.M) {
|
||||
if len(dsn) == 0 {
|
||||
// a temporary solution to make sure all tests are ran inside sqlite
|
||||
dsn = "sqlite3+debug://file::memory:?cache=shared&mode=memory"
|
||||
fmt.Fprintln(os.Stderr, "can not run store/adapters/rdbms/dal tests without DB_DSN, skip")
|
||||
return
|
||||
//fmt.Fprintln(os.Stderr, "can not run store/adapters/rdbms/dal tests without DB_DSN, skip")
|
||||
//return
|
||||
}
|
||||
|
||||
// ctx = logger.ContextWithValue(context.Background(), log)
|
||||
@ -68,3 +69,22 @@ func (r kv) SetValue(k string, place uint, v any) error {
|
||||
r[k] = v
|
||||
return nil
|
||||
}
|
||||
|
||||
// String function returns string representation of the kv with sorted keys
|
||||
func (r kv) String() string {
|
||||
// sort keys from map
|
||||
keys := make([]string, 0, len(r))
|
||||
for k := range r {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
sort.Strings(keys)
|
||||
|
||||
// build string by iterating over sorted keys and appending values
|
||||
var out string
|
||||
for _, k := range keys {
|
||||
out += fmt.Sprintf("%s=%v ", k, r[k])
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
@ -7,12 +7,15 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza-server/pkg/logger"
|
||||
. "github.com/cortezaproject/corteza-server/store/adapters/rdbms/dal"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestModel_Aggregate(t *testing.T) {
|
||||
_ = logger.Default()
|
||||
|
||||
var (
|
||||
req = require.New(t)
|
||||
|
||||
@ -33,10 +36,10 @@ func TestModel_Aggregate(t *testing.T) {
|
||||
i dal.Iterator
|
||||
|
||||
table, err = s.DataDefiner.ConvertModel(baseModel)
|
||||
row *kv
|
||||
row kv
|
||||
)
|
||||
|
||||
ctx = logger.ContextWithValue(context.Background(), logger.MakeDebugLogger())
|
||||
//ctx = logger.ContextWithValue(context.Background(), logger.MakeDebugLogger())
|
||||
|
||||
table.Temporary = true
|
||||
req.NoError(s.DataDefiner.TableCreate(ctx, table))
|
||||
@ -71,8 +74,11 @@ func TestModel_Aggregate(t *testing.T) {
|
||||
},
|
||||
// aggregation expressions
|
||||
[]*dal.AggregateAttr{
|
||||
{Identifier: "count", RawExpr: "COUNT(*)", Type: &dal.TypeNumber{}},
|
||||
{Identifier: "max", RawExpr: "MAX(price)", Type: &dal.TypeNumber{}},
|
||||
{Identifier: "min", RawExpr: "MIN(price)", Type: &dal.TypeNumber{}},
|
||||
{Identifier: "avg", RawExpr: "AVG(price)", Type: &dal.TypeNumber{}},
|
||||
{Identifier: "sum", RawExpr: "SUM(price)", Type: &dal.TypeNumber{}},
|
||||
},
|
||||
"", // <== here be having condition
|
||||
)
|
||||
@ -81,20 +87,25 @@ func TestModel_Aggregate(t *testing.T) {
|
||||
|
||||
defer req.NoError(i.Close())
|
||||
|
||||
// ctx = logger.ContextWithValue(context.Background(), logger.MakeDebugLogger())
|
||||
ctx = logger.ContextWithValue(context.Background(), logger.MakeDebugLogger())
|
||||
|
||||
t.Log("Iterating over results")
|
||||
rows := make([]*kv, 0, 5)
|
||||
rows := make([]kv, 0, 5)
|
||||
for i.Next(ctx) {
|
||||
row = &kv{}
|
||||
row = kv{}
|
||||
req.NoError(i.Scan(row))
|
||||
|
||||
// due to difference of number of decimal digits in different DBs, we need to do this
|
||||
// to make sure we get the same result
|
||||
row["avg"] = fmt.Sprintf("%.2f", cast.ToFloat64(row["avg"]))
|
||||
|
||||
rows = append(rows, row)
|
||||
}
|
||||
|
||||
req.Len(rows, 5)
|
||||
req.Equal(&kv{"group": "g5", "max": "501000", "min": "500001"}, rows[0])
|
||||
req.Equal(&kv{"group": "g4", "max": "401000", "min": "400001"}, rows[1])
|
||||
req.Equal(&kv{"group": "g3", "max": "301000", "min": "300001"}, rows[2])
|
||||
req.Equal(&kv{"group": "g2", "max": "201000", "min": "200001"}, rows[3])
|
||||
req.Equal(&kv{"group": "g1", "max": "101000", "min": "100001"}, rows[4])
|
||||
req.Equal("avg=500500.50 count=1000 group=g5 max=501000 min=500001 sum=500500500 ", rows[0].String())
|
||||
req.Equal("avg=400500.50 count=1000 group=g4 max=401000 min=400001 sum=400500500 ", rows[1].String())
|
||||
req.Equal("avg=300500.50 count=1000 group=g3 max=301000 min=300001 sum=300500500 ", rows[2].String())
|
||||
req.Equal("avg=200500.50 count=1000 group=g2 max=201000 min=200001 sum=200500500 ", rows[3].String())
|
||||
req.Equal("avg=100500.50 count=1000 group=g1 max=101000 min=100001 sum=100500500 ", rows[4].String())
|
||||
}
|
||||
|
||||
@ -97,6 +97,15 @@ var (
|
||||
},
|
||||
"mult": {
|
||||
Handler: func(args ...exp.Expression) exp.Expression {
|
||||
// Handling COUNT(*) scenario:
|
||||
// ql parser interprets * as a multiplier
|
||||
//
|
||||
// in situations where there are 0 arguments we'll just
|
||||
// return star
|
||||
if len(args) == 0 {
|
||||
return exp.Star()
|
||||
}
|
||||
|
||||
return exp.NewLiteralExpression("? * ?", args[0], args[1])
|
||||
},
|
||||
},
|
||||
@ -216,9 +225,19 @@ var (
|
||||
return exp.NewSQLFunctionExpression("DATE", args[0])
|
||||
},
|
||||
},
|
||||
"max": {
|
||||
"count": {
|
||||
Handler: func(args ...exp.Expression) exp.Expression {
|
||||
return exp.NewSQLFunctionExpression("MAX", args[0])
|
||||
return exp.NewSQLFunctionExpression("COUNT", args[0])
|
||||
},
|
||||
},
|
||||
"sum": {
|
||||
Handler: func(args ...exp.Expression) exp.Expression {
|
||||
return exp.NewSQLFunctionExpression("SUM", args[0])
|
||||
},
|
||||
},
|
||||
"avg": {
|
||||
Handler: func(args ...exp.Expression) exp.Expression {
|
||||
return exp.NewSQLFunctionExpression("AVG", args[0])
|
||||
},
|
||||
},
|
||||
"min": {
|
||||
@ -226,6 +245,11 @@ var (
|
||||
return exp.NewSQLFunctionExpression("MIN", args[0])
|
||||
},
|
||||
},
|
||||
"max": {
|
||||
Handler: func(args ...exp.Expression) exp.Expression {
|
||||
return exp.NewSQLFunctionExpression("MAX", args[0])
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user