diff --git a/CHANGELOG.md b/CHANGELOG.md index e1edeb0d3b..60cc7e18c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - [#9058](https://github.com/influxdata/influxdb/issues/9058): Fix space required after regex operator. Thanks @stop-start! - [#9109](https://github.com/influxdata/influxdb/issues/9109): Fix: panic: sync: WaitGroup is reused before previous Wait has returned - [#9163](https://github.com/influxdata/influxdb/pull/9163): Fix race condition in the merge iterator close method. +- [#9144](https://github.com/influxdata/influxdb/issues/9144): Fix query compilation so multiple nested distinct calls is allowable ## v1.4.2 [2017-11-15] diff --git a/query/compile.go b/query/compile.go index 41de4d4809..137d5829f5 100644 --- a/query/compile.go +++ b/query/compile.go @@ -250,7 +250,7 @@ func (c *compiledField) compileExpr(expr influxql.Expr) error { case "sample": return c.compileSample(expr.Args) case "distinct": - return c.compileDistinct(expr.Args) + return c.compileDistinct(expr.Args, false) case "top", "bottom": return c.compileTopBottom(expr) case "derivative", "non_negative_derivative": @@ -276,7 +276,7 @@ func (c *compiledField) compileExpr(expr influxql.Expr) error { case *influxql.Distinct: call := expr.NewCall() c.global.FunctionCalls = append(c.global.FunctionCalls, call) - return c.compileDistinct(call.Args) + return c.compileDistinct(call.Args, false) case *influxql.BinaryExpr: // Disallow wildcards in binary expressions. RewriteFields, which expands // wildcards, is too complicated if we allow wildcards inside of expressions. @@ -349,10 +349,10 @@ func (c *compiledField) compileFunction(expr *influxql.Call) error { if expr.Name == "count" { // If we have count(), the argument may be a distinct() call. if arg0, ok := expr.Args[0].(*influxql.Call); ok && arg0.Name == "distinct" { - return c.compileDistinct(arg0.Args) + return c.compileDistinct(arg0.Args, true) } else if arg0, ok := expr.Args[0].(*influxql.Distinct); ok { call := arg0.NewCall() - return c.compileDistinct(call.Args) + return c.compileDistinct(call.Args, true) } } return c.compileSymbol(expr.Name, expr.Args[0]) @@ -591,7 +591,7 @@ func (c *compiledField) compileHoltWinters(args []influxql.Expr, withFit bool) e return c.compileExpr(call) } -func (c *compiledField) compileDistinct(args []influxql.Expr) error { +func (c *compiledField) compileDistinct(args []influxql.Expr, nested bool) error { if len(args) == 0 { return errors.New("distinct function requires at least one argument") } else if len(args) != 1 { @@ -601,7 +601,9 @@ func (c *compiledField) compileDistinct(args []influxql.Expr) error { if _, ok := args[0].(*influxql.VarRef); !ok { return errors.New("expected field argument in distinct()") } - c.global.HasDistinct = true + if !nested { + c.global.HasDistinct = true + } c.global.OnlySelectors = false return nil } diff --git a/query/compile_test.go b/query/compile_test.go index 4eab7ef9d1..fa4de43517 100644 --- a/query/compile_test.go +++ b/query/compile_test.go @@ -80,6 +80,7 @@ func TestCompile_Success(t *testing.T) { `SELECT max(value) FROM (SELECT value + total FROM cpu) WHERE time >= now() - 1m GROUP BY time(10s)`, `SELECT value FROM cpu WHERE time >= '2000-01-01T00:00:00Z' AND time <= '2000-01-01T01:00:00Z'`, `SELECT value FROM (SELECT value FROM cpu) ORDER BY time DESC`, + `SELECT count(distinct(value)), max(value) FROM cpu`, } { t.Run(tt, func(t *testing.T) { stmt, err := influxql.ParseStatement(tt) @@ -121,7 +122,6 @@ func TestCompile_Failures(t *testing.T) { {s: `SELECT mean() FROM cpu`, err: `invalid number of arguments for mean, expected 1, got 0`}, {s: `SELECT mean(value, host) FROM cpu`, err: `invalid number of arguments for mean, expected 1, got 2`}, {s: `SELECT distinct(value), max(value) FROM cpu`, err: `aggregate function distinct() cannot be combined with other functions or fields`}, - {s: `SELECT count(distinct(value)), max(value) FROM cpu`, err: `aggregate function distinct() cannot be combined with other functions or fields`}, {s: `SELECT count(distinct()) FROM cpu`, err: `distinct function requires at least one argument`}, {s: `SELECT count(distinct(value, host)) FROM cpu`, err: `distinct function can only have one argument`}, {s: `SELECT count(distinct(2)) FROM cpu`, err: `expected field argument in distinct()`},