From 34385a3f4c8727ff9d6736e398ea58976a4466c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Nieto?= <jose.carlos@menteslibres.net> Date: Thu, 7 Aug 2014 11:53:25 -0500 Subject: [PATCH] QL: Adding support for db.Result.Group(). --- ql/_dumps/structs.sql | 8 +++++++ ql/database.go | 1 + ql/database_test.go | 56 +++++++++++++++++++++++++++++++++++++++++++ ql/layout.go | 8 +++++++ ql/result.go | 22 +++++++++++++++++ 5 files changed, 95 insertions(+) diff --git a/ql/_dumps/structs.sql b/ql/_dumps/structs.sql index 997b8165..21b48e86 100644 --- a/ql/_dumps/structs.sql +++ b/ql/_dumps/structs.sql @@ -43,4 +43,12 @@ CREATE TABLE data_types ( _time time ); +DROP TABLE IF EXISTS stats_test; + +CREATE TABLE stats_test ( + id uint, + numeric int64, + value int64 +); + COMMIT; diff --git a/ql/database.go b/ql/database.go index 13af8cf1..bb7af134 100644 --- a/ql/database.go +++ b/ql/database.go @@ -108,6 +108,7 @@ func init() { qlDropDatabaseLayout, qlDropTableLayout, qlSelectCountLayout, + qlGroupByLayout, } db.Register(Adapter, &source{}) diff --git a/ql/database_test.go b/ql/database_test.go index 9e73cc7a..24fcb689 100644 --- a/ql/database_test.go +++ b/ql/database_test.go @@ -34,6 +34,7 @@ import ( "menteslibres.net/gosexy/to" //"reflect" + "math/rand" "strings" "testing" "time" @@ -215,6 +216,61 @@ func TestAppend(t *testing.T) { } +func TestGroup(t *testing.T) { + + var err error + var sess db.Database + var stats db.Collection + + if sess, err = db.Open(Adapter, settings); err != nil { + t.Fatal(err) + } + + type stats_t struct { + Numeric int `db:"numeric"` + Value int `db:"value"` + } + + defer sess.Close() + + if stats, err = sess.Collection("stats_test"); err != nil { + t.Fatal(err) + } + + // Truncating table. + if err = stats.Truncate(); err != nil { + t.Fatal(err) + } + + // Adding row append. + for i := 0; i < 1000; i++ { + numeric, value := rand.Intn(10), rand.Intn(100) + if _, err = stats.Append(stats_t{numeric, value}); err != nil { + t.Fatal(err) + } + } + + // db.Func{"COUNT", 1}, + // db.Func{"SUM", `value`}, + + // Testing GROUP BY + res := stats.Find().Select( + `numeric`, + db.Raw{`count(1) AS counter`}, + db.Raw{`sum(value) AS total`}, + ).Group(`numeric`) + + var results []map[string]interface{} + + if err = res.All(&results); err != nil { + t.Fatal(err) + } + + if len(results) != 10 { + t.Fatalf(`Expecting exactly 10 results, this could fail, but it's very unlikely to happen.`) + } +} + // Attempts to count all rows in our newly defined set. func TestResultCount(t *testing.T) { var err error diff --git a/ql/layout.go b/ql/layout.go index 15f9a44f..d60f32e2 100644 --- a/ql/layout.go +++ b/ql/layout.go @@ -65,6 +65,8 @@ const ( {{.Where}} + {{.GroupBy}} + {{.OrderBy}} {{if .Limit}} @@ -121,4 +123,10 @@ const ( qlDropTableLayout = ` DROP TABLE {{.Table}} ` + + qlGroupByLayout = ` + {{if .GroupColumns}} + GROUP BY {{.GroupColumns}} + {{end}} + ` ) diff --git a/ql/result.go b/ql/result.go index 4c9dc638..164574ca 100644 --- a/ql/result.go +++ b/ql/result.go @@ -43,6 +43,7 @@ type result struct { columns sqlgen.Columns where sqlgen.Where orderBy sqlgen.OrderBy + groupBy sqlgen.GroupBy arguments []interface{} } @@ -59,6 +60,7 @@ func (self *result) setCursor() error { Offset: self.offset, Where: self.where, OrderBy: self.orderBy, + GroupBy: self.groupBy, }, self.arguments...) } return err @@ -83,6 +85,26 @@ func (self *result) Skip(n uint) db.Result { return self } +// Used to group results that have the same value in the same column or +// columns. +func (self *result) Group(fields ...interface{}) db.Result { + + groupByColumns := make(sqlgen.GroupBy, 0, len(fields)) + + l := len(fields) + for i := 0; i < l; i++ { + switch value := fields[i].(type) { + // Maybe other types? + default: + groupByColumns = append(groupByColumns, sqlgen.Column{value}) + } + } + + self.groupBy = groupByColumns + + return self +} + // Determines sorting of results according to the provided names. Fields may be // prefixed by - (minus) which means descending order, ascending order would be // used otherwise. -- GitLab