Fix query compilation so multiple nested distinct calls is allowable

When refactoring the query engine, I thought calling
`count(distinct(value))` multiple times was disallowed and so the
refactor made it so that wasn't possible.

It turns out that this pattern is allowed because since the distinct is
nested, it is aggregated anyway and can be combined with other
aggregates.

This removes the erroneously placed restriction.
pull/9145/head
Jonathan A. Sternberg 2017-11-21 11:46:29 -06:00
parent 0b18a6faf4
commit db60a83d5a
3 changed files with 10 additions and 7 deletions

View File

@ -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]

View File

@ -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
}

View File

@ -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()`},