From 2602dd241fc58d40a81d716f3e746457d0d6197b Mon Sep 17 00:00:00 2001 From: mengjingleli Date: Fri, 4 Dec 2015 15:17:31 +0800 Subject: [PATCH] fix raw math query panic --- influxql/ast.go | 8 +++--- influxql/ast_test.go | 54 +++++++++++++++++++++++++++++++++++++ influxql/result.go | 3 +++ tsdb/query_executor_test.go | 18 +++++++++++++ tsdb/raw.go | 6 ++++- 5 files changed, 84 insertions(+), 5 deletions(-) diff --git a/influxql/ast.go b/influxql/ast.go index ef7eeab841..239296f498 100644 --- a/influxql/ast.go +++ b/influxql/ast.go @@ -2365,14 +2365,14 @@ func (a Fields) AliasNames() []string { func (a Fields) Names() []string { names := []string{} for _, f := range a { - var name string switch expr := f.Expr.(type) { case *Call: - name = expr.Name + names = append(names, expr.Name) case *VarRef: - name = expr.Val + names = append(names, expr.Val) + case *BinaryExpr: + names = append(names, walkNames(expr)...) } - names = append(names, name) } return names } diff --git a/influxql/ast_test.go b/influxql/ast_test.go index e532fff53b..c0ee09d2ed 100644 --- a/influxql/ast_test.go +++ b/influxql/ast_test.go @@ -807,6 +807,60 @@ func TestReduce(t *testing.T) { } } +func Test_fieldsNames(t *testing.T) { + for _, test := range []struct { + in []string + out []string + alias []string + }{ + { //case: binary expr(valRef) + in: []string{"value+value"}, + out: []string{"value", "value"}, + alias: []string{""}, + }, + { //case: binary expr + valRef + in: []string{"value+value", "temperature"}, + out: []string{"value", "value", "temperature"}, + alias: []string{"", "temperature"}, + }, + { //case: aggregate expr + in: []string{"mean(value)"}, + out: []string{"mean"}, + alias: []string{"mean"}, + }, + { //case: binary expr(aggregate expr) + in: []string{"mean(value) + max(value)"}, + out: []string{"value", "value"}, + alias: []string{""}, + }, + { //case: binary expr(aggregate expr) + valRef + in: []string{"mean(value) + max(value)", "temperature"}, + out: []string{"value", "value", "temperature"}, + alias: []string{"", "temperature"}, + }, + { //case: mixed aggregate and varRef + in: []string{"mean(value) + temperature"}, + out: []string{"value", "temperature"}, + alias: []string{""}, + }, + } { + fields := influxql.Fields{} + for _, s := range test.in { + expr := MustParseExpr(s) + fields = append(fields, &influxql.Field{Expr: expr}) + } + got := fields.Names() + if !reflect.DeepEqual(got, test.out) { + t.Errorf("get fileds name:\nexp=%v\ngot=%v\n", test.out, got) + } + alias := fields.AliasNames() + if !reflect.DeepEqual(alias, test.alias) { + t.Errorf("get fileds alias name:\nexp=%v\ngot=%v\n", test.alias, alias) + } + } + +} + // Valuer represents a simple wrapper around a map to implement the influxql.Valuer interface. type Valuer map[string]interface{} diff --git a/influxql/result.go b/influxql/result.go index b6a749ccf5..555f1bbfb2 100644 --- a/influxql/result.go +++ b/influxql/result.go @@ -95,6 +95,9 @@ type Processor func(values []interface{}) interface{} func newEchoProcessor(index int) Processor { return func(values []interface{}) interface{} { + if index > len(values)-1 { + return nil + } return values[index] } } diff --git a/tsdb/query_executor_test.go b/tsdb/query_executor_test.go index ca41b5cdfd..82c1eb59cf 100644 --- a/tsdb/query_executor_test.go +++ b/tsdb/query_executor_test.go @@ -48,6 +48,24 @@ func TestWritePointsAndExecuteQuery(t *testing.T) { t.Fatalf("\nexp: %s\ngot: %s", exepected, got) } + got = executeAndGetJSON("SELECT mean(value) + mean(value) as value FROM cpu", executor) + exepected = `[{"series":[{"name":"cpu","columns":["time","value"],"values":[["1970-01-01T00:00:00Z",2]]}]}]` + if exepected != got { + t.Fatalf("\nexp: %s\ngot: %s", exepected, got) + } + + got = executeAndGetJSON("SELECT value + value FROM cpu", executor) + exepected = `[{"series":[{"name":"cpu","columns":["time",""],"values":[["1970-01-01T00:00:01.000000002Z",2],["1970-01-01T00:00:02.000000003Z",2]]}]}]` + if exepected != got { + t.Fatalf("\nexp: %s\ngot: %s", exepected, got) + } + + got = executeAndGetJSON("SELECT value + value as sum FROM cpu", executor) + exepected = `[{"series":[{"name":"cpu","columns":["time","sum"],"values":[["1970-01-01T00:00:01.000000002Z",2],["1970-01-01T00:00:02.000000003Z",2]]}]}]` + if exepected != got { + t.Fatalf("\nexp: %s\ngot: %s", exepected, got) + } + got = executeAndGetJSON("SELECT * FROM cpu GROUP BY *", executor) exepected = `[{"series":[{"name":"cpu","tags":{"host":"server"},"columns":["time","value"],"values":[["1970-01-01T00:00:01.000000002Z",1],["1970-01-01T00:00:02.000000003Z",1]]}]}]` if exepected != got { diff --git a/tsdb/raw.go b/tsdb/raw.go index 69b791afb2..514818079d 100644 --- a/tsdb/raw.go +++ b/tsdb/raw.go @@ -483,9 +483,13 @@ func (r *limitedRowWriter) processValues(values []*MapperValue) *models.Row { selectFields := make([]string, 0, len(selectNames)) aliasFields := make([]string, 0, len(selectNames)) - for i, n := range selectNames { + for _, n := range selectNames { if _, found := r.tags[n]; !found { selectFields = append(selectFields, n) + } + } + for i, n := range aliasNames { + if _, found := r.tags[n]; !found { aliasFields = append(aliasFields, aliasNames[i]) } }