Skip to content

Commit 4387d20

Browse files
committed
feat(influxdb): render select and groupby
1 parent 9968fa5 commit 4387d20

File tree

4 files changed

+99
-48
lines changed

4 files changed

+99
-48
lines changed

pkg/tsdb/influxdb/influxdb.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ import (
1212

1313
type InfluxDBExecutor struct {
1414
*tsdb.DataSourceInfo
15-
QueryParser *InfluxdbQueryParser
15+
QueryParser *InfluxdbQueryParser
16+
QueryBuilder *QueryBuild
1617
}
1718

1819
func NewInfluxDBExecutor(dsInfo *tsdb.DataSourceInfo) tsdb.Executor {
1920
return &InfluxDBExecutor{
2021
DataSourceInfo: dsInfo,
2122
QueryParser: &InfluxdbQueryParser{},
23+
QueryBuilder: &QueryBuild{},
2224
}
2325
}
2426

@@ -46,12 +48,16 @@ func (e *InfluxDBExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice,
4648
for _, v := range queries {
4749

4850
query, err := e.QueryParser.Parse(v.Model)
49-
5051
if err != nil {
5152
result.Error = err
5253
return result
5354
}
55+
5456
glog.Info("Influxdb executor", "query", query)
57+
58+
rawQuery, err := e.QueryBuilder.Build(query)
59+
60+
glog.Info("Influxdb", "error", err, "rawQuery", rawQuery)
5561
}
5662

5763
return result

pkg/tsdb/influxdb/query_builder.go

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,65 @@
11
package influxdb
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
"strings"
6+
)
47

58
type QueryBuild struct{}
69

10+
func renderTags(query *Query) []string {
11+
var res []string
12+
for i, tag := range query.Tags {
13+
str := ""
14+
15+
if i > 0 {
16+
if tag.Condition == "" {
17+
str += "AND"
18+
} else {
19+
str += tag.Condition
20+
}
21+
str += " "
22+
}
23+
24+
res = append(res, fmt.Sprintf(`%s"%s" %s '%s'`, str, tag.Key, tag.Operator, tag.Value))
25+
}
26+
27+
return res
28+
}
29+
730
func (*QueryBuild) Build(query *Query) (string, error) {
31+
res := "SELECT "
32+
33+
var selectors []string
34+
for _, sel := range query.Selects {
35+
36+
stk := ""
37+
for _, s := range *sel {
38+
stk = s.Render(stk)
39+
}
40+
selectors = append(selectors, stk)
41+
}
42+
res += strings.Join(selectors, ", ")
43+
44+
res += fmt.Sprintf(` FROM "%s"`, query.Measurement)
45+
46+
res += " WHERE "
47+
conditions := renderTags(query)
48+
res += strings.Join(conditions, " ")
49+
if len(conditions) > 0 {
50+
res += " AND "
51+
}
52+
53+
res += "$timeFilter"
54+
55+
var groupBy []string
56+
for _, group := range query.GroupBy {
57+
groupBy = append(groupBy, group.Render(""))
58+
}
59+
60+
if len(groupBy) > 0 {
61+
res += " GROUP BY " + strings.Join(groupBy, " ")
62+
}
863

9-
return "", fmt.Errorf("query is not valid")
64+
return res, nil
1065
}

pkg/tsdb/influxdb/query_builder_test.go

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,50 +8,40 @@ import (
88

99
func TestInfluxdbQueryBuilder(t *testing.T) {
1010
Convey("Influxdb query builder", t, func() {
11+
builder := QueryBuild{}
1112

12-
builder := &QueryBuild{}
13+
qp1, _ := NewQueryPart("field", []string{"value"})
14+
qp2, _ := NewQueryPart("mean", []string{})
15+
16+
groupBy1, _ := NewQueryPart("time", []string{"$interval"})
17+
groupBy2, _ := NewQueryPart("fill", []string{"null"})
18+
19+
tag1 := &Tag{Key: "hostname", Value: "server1", Operator: "="}
20+
tag2 := &Tag{Key: "hostname", Value: "server2", Operator: "=", Condition: "OR"}
1321

1422
Convey("can build query", func() {
15-
//query := &Query{}
16-
//res, err := builder.Build(query)
17-
//So(err, ShouldBeNil)
23+
query := &Query{
24+
Selects: []*Select{{*qp1, *qp2}},
25+
Measurement: "cpu",
26+
GroupBy: []*QueryPart{groupBy1, groupBy2},
27+
}
28+
29+
rawQuery, err := builder.Build(query)
30+
So(err, ShouldBeNil)
31+
So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "cpu" WHERE $timeFilter GROUP BY time($interval) fill(null)`)
1832
})
1933

20-
Convey("empty queries should return error", func() {
21-
query := &Query{}
22-
23-
res, err := builder.Build(query)
24-
So(err, ShouldNotBeNil)
25-
So(res, ShouldEqual, "")
34+
Convey("can asd query", func() {
35+
query := &Query{
36+
Selects: []*Select{{*qp1, *qp2}},
37+
Measurement: "cpu",
38+
GroupBy: []*QueryPart{groupBy1},
39+
Tags: []*Tag{tag1, tag2},
40+
}
41+
42+
rawQuery, err := builder.Build(query)
43+
So(err, ShouldBeNil)
44+
So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "cpu" WHERE "hostname" = 'server1' OR "hostname" = 'server2' AND $timeFilter GROUP BY time($interval)`)
2645
})
2746
})
2847
}
29-
30-
/*
31-
describe('render series with mesurement only', function() {
32-
it('should generate correct query', function() {
33-
var query = new InfluxQuery({
34-
measurement: 'cpu',
35-
}, templateSrv, {});
36-
37-
var queryText = query.render();
38-
expect(queryText).to.be('SELECT mean("value") FROM "cpu" WHERE $timeFilter GROUP BY time($interval) fill(null)');
39-
});
40-
});
41-
*/
42-
43-
/*
44-
describe('series with tags OR condition', function() {
45-
it('should generate correct query', function() {
46-
var query = new InfluxQuery({
47-
measurement: 'cpu',
48-
groupBy: [{type: 'time', params: ['auto']}],
49-
tags: [{key: 'hostname', value: 'server1'}, {key: 'hostname', value: 'server2', condition: "OR"}]
50-
}, templateSrv, {});
51-
52-
var queryText = query.render();
53-
expect(queryText).to.be('SELECT mean("value") FROM "cpu" WHERE "hostname" = \'server1\' OR "hostname" = \'server2\' AND ' +
54-
'$timeFilter GROUP BY time($interval)');
55-
});
56-
});
57-
*/

pkg/tsdb/influxdb/query_part.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,13 @@ func fieldRenderer(part *QueryPart, innerExpr string) string {
9191
}
9292

9393
func functionRenderer(part *QueryPart, innerExpr string) string {
94-
params := strings.Join(part.Params, ", ")
95-
96-
if len(part.Params) > 0 {
97-
return fmt.Sprintf("%s(%s, %s)", part.Type, innerExpr, params)
94+
if innerExpr != "" {
95+
part.Params = append([]string{innerExpr}, part.Params...)
9896
}
9997

100-
return fmt.Sprintf("%s(%s)", part.Type, innerExpr)
98+
params := strings.Join(part.Params, ", ")
99+
100+
return fmt.Sprintf("%s(%s)", part.Type, params)
101101
}
102102

103103
func suffixRenderer(part *QueryPart, innerExpr string) string {

0 commit comments

Comments
 (0)