Commit 4387d202 by bergquist

feat(influxdb): render select and groupby

parent 9968fa5b
......@@ -12,13 +12,15 @@ import (
type InfluxDBExecutor struct {
*tsdb.DataSourceInfo
QueryParser *InfluxdbQueryParser
QueryParser *InfluxdbQueryParser
QueryBuilder *QueryBuild
}
func NewInfluxDBExecutor(dsInfo *tsdb.DataSourceInfo) tsdb.Executor {
return &InfluxDBExecutor{
DataSourceInfo: dsInfo,
QueryParser: &InfluxdbQueryParser{},
QueryBuilder: &QueryBuild{},
}
}
......@@ -46,12 +48,16 @@ func (e *InfluxDBExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice,
for _, v := range queries {
query, err := e.QueryParser.Parse(v.Model)
if err != nil {
result.Error = err
return result
}
glog.Info("Influxdb executor", "query", query)
rawQuery, err := e.QueryBuilder.Build(query)
glog.Info("Influxdb", "error", err, "rawQuery", rawQuery)
}
return result
......
package influxdb
import "fmt"
import (
"fmt"
"strings"
)
type QueryBuild struct{}
func renderTags(query *Query) []string {
var res []string
for i, tag := range query.Tags {
str := ""
if i > 0 {
if tag.Condition == "" {
str += "AND"
} else {
str += tag.Condition
}
str += " "
}
res = append(res, fmt.Sprintf(`%s"%s" %s '%s'`, str, tag.Key, tag.Operator, tag.Value))
}
return res
}
func (*QueryBuild) Build(query *Query) (string, error) {
res := "SELECT "
var selectors []string
for _, sel := range query.Selects {
stk := ""
for _, s := range *sel {
stk = s.Render(stk)
}
selectors = append(selectors, stk)
}
res += strings.Join(selectors, ", ")
res += fmt.Sprintf(` FROM "%s"`, query.Measurement)
res += " WHERE "
conditions := renderTags(query)
res += strings.Join(conditions, " ")
if len(conditions) > 0 {
res += " AND "
}
res += "$timeFilter"
var groupBy []string
for _, group := range query.GroupBy {
groupBy = append(groupBy, group.Render(""))
}
if len(groupBy) > 0 {
res += " GROUP BY " + strings.Join(groupBy, " ")
}
return "", fmt.Errorf("query is not valid")
return res, nil
}
......@@ -8,50 +8,40 @@ import (
func TestInfluxdbQueryBuilder(t *testing.T) {
Convey("Influxdb query builder", t, func() {
builder := QueryBuild{}
builder := &QueryBuild{}
qp1, _ := NewQueryPart("field", []string{"value"})
qp2, _ := NewQueryPart("mean", []string{})
groupBy1, _ := NewQueryPart("time", []string{"$interval"})
groupBy2, _ := NewQueryPart("fill", []string{"null"})
tag1 := &Tag{Key: "hostname", Value: "server1", Operator: "="}
tag2 := &Tag{Key: "hostname", Value: "server2", Operator: "=", Condition: "OR"}
Convey("can build query", func() {
//query := &Query{}
//res, err := builder.Build(query)
//So(err, ShouldBeNil)
query := &Query{
Selects: []*Select{{*qp1, *qp2}},
Measurement: "cpu",
GroupBy: []*QueryPart{groupBy1, groupBy2},
}
rawQuery, err := builder.Build(query)
So(err, ShouldBeNil)
So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "cpu" WHERE $timeFilter GROUP BY time($interval) fill(null)`)
})
Convey("empty queries should return error", func() {
query := &Query{}
res, err := builder.Build(query)
So(err, ShouldNotBeNil)
So(res, ShouldEqual, "")
Convey("can asd query", func() {
query := &Query{
Selects: []*Select{{*qp1, *qp2}},
Measurement: "cpu",
GroupBy: []*QueryPart{groupBy1},
Tags: []*Tag{tag1, tag2},
}
rawQuery, err := builder.Build(query)
So(err, ShouldBeNil)
So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "cpu" WHERE "hostname" = 'server1' OR "hostname" = 'server2' AND $timeFilter GROUP BY time($interval)`)
})
})
}
/*
describe('render series with mesurement only', function() {
it('should generate correct query', function() {
var query = new InfluxQuery({
measurement: 'cpu',
}, templateSrv, {});
var queryText = query.render();
expect(queryText).to.be('SELECT mean("value") FROM "cpu" WHERE $timeFilter GROUP BY time($interval) fill(null)');
});
});
*/
/*
describe('series with tags OR condition', function() {
it('should generate correct query', function() {
var query = new InfluxQuery({
measurement: 'cpu',
groupBy: [{type: 'time', params: ['auto']}],
tags: [{key: 'hostname', value: 'server1'}, {key: 'hostname', value: 'server2', condition: "OR"}]
}, templateSrv, {});
var queryText = query.render();
expect(queryText).to.be('SELECT mean("value") FROM "cpu" WHERE "hostname" = \'server1\' OR "hostname" = \'server2\' AND ' +
'$timeFilter GROUP BY time($interval)');
});
});
*/
......@@ -91,13 +91,13 @@ func fieldRenderer(part *QueryPart, innerExpr string) string {
}
func functionRenderer(part *QueryPart, innerExpr string) string {
params := strings.Join(part.Params, ", ")
if len(part.Params) > 0 {
return fmt.Sprintf("%s(%s, %s)", part.Type, innerExpr, params)
if innerExpr != "" {
part.Params = append([]string{innerExpr}, part.Params...)
}
return fmt.Sprintf("%s(%s)", part.Type, innerExpr)
params := strings.Join(part.Params, ", ")
return fmt.Sprintf("%s(%s)", part.Type, params)
}
func suffixRenderer(part *QueryPart, innerExpr string) string {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment