github.com/influxdata/influxdb/v2@v2.7.6/influxql/query/compile_test.go (about)

     1  package query_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/influxdata/influxdb/v2/influxql/query"
     8  	"github.com/influxdata/influxql"
     9  )
    10  
    11  func TestCompile_Success(t *testing.T) {
    12  	for _, tt := range []string{
    13  		`SELECT time, value FROM cpu`,
    14  		`SELECT value FROM cpu`,
    15  		`SELECT value, host FROM cpu`,
    16  		`SELECT * FROM cpu`,
    17  		`SELECT time, * FROM cpu`,
    18  		`SELECT value, * FROM cpu`,
    19  		`SELECT max(value) FROM cpu`,
    20  		`SELECT max(value), host FROM cpu`,
    21  		`SELECT max(value), * FROM cpu`,
    22  		`SELECT max(*) FROM cpu`,
    23  		`SELECT max(/val/) FROM cpu`,
    24  		`SELECT min(value) FROM cpu`,
    25  		`SELECT min(value), host FROM cpu`,
    26  		`SELECT min(value), * FROM cpu`,
    27  		`SELECT min(*) FROM cpu`,
    28  		`SELECT min(/val/) FROM cpu`,
    29  		`SELECT first(value) FROM cpu`,
    30  		`SELECT first(value), host FROM cpu`,
    31  		`SELECT first(value), * FROM cpu`,
    32  		`SELECT first(*) FROM cpu`,
    33  		`SELECT first(/val/) FROM cpu`,
    34  		`SELECT last(value) FROM cpu`,
    35  		`SELECT last(value), host FROM cpu`,
    36  		`SELECT last(value), * FROM cpu`,
    37  		`SELECT last(*) FROM cpu`,
    38  		`SELECT last(/val/) FROM cpu`,
    39  		`SELECT count(value) FROM cpu`,
    40  		`SELECT count(distinct(value)) FROM cpu`,
    41  		`SELECT count(distinct value) FROM cpu`,
    42  		`SELECT count(*) FROM cpu`,
    43  		`SELECT count(/val/) FROM cpu`,
    44  		`SELECT mean(value) FROM cpu`,
    45  		`SELECT mean(*) FROM cpu`,
    46  		`SELECT mean(/val/) FROM cpu`,
    47  		`SELECT min(value), max(value) FROM cpu`,
    48  		`SELECT min(*), max(*) FROM cpu`,
    49  		`SELECT min(/val/), max(/val/) FROM cpu`,
    50  		`SELECT first(value), last(value) FROM cpu`,
    51  		`SELECT first(*), last(*) FROM cpu`,
    52  		`SELECT first(/val/), last(/val/) FROM cpu`,
    53  		`SELECT count(value) FROM cpu WHERE time >= now() - 1h GROUP BY time(10m)`,
    54  		`SELECT distinct value FROM cpu`,
    55  		`SELECT distinct(value) FROM cpu`,
    56  		`SELECT value / total FROM cpu`,
    57  		`SELECT min(value) / total FROM cpu`,
    58  		`SELECT max(value) / total FROM cpu`,
    59  		`SELECT top(value, 1) FROM cpu`,
    60  		`SELECT top(value, host, 1) FROM cpu`,
    61  		`SELECT top(value, 1), host FROM cpu`,
    62  		`SELECT min(top) FROM (SELECT top(value, host, 1) FROM cpu) GROUP BY region`,
    63  		`SELECT bottom(value, 1) FROM cpu`,
    64  		`SELECT bottom(value, host, 1) FROM cpu`,
    65  		`SELECT bottom(value, 1), host FROM cpu`,
    66  		`SELECT max(bottom) FROM (SELECT bottom(value, host, 1) FROM cpu) GROUP BY region`,
    67  		`SELECT percentile(value, 75) FROM cpu`,
    68  		`SELECT percentile(value, 75.0) FROM cpu`,
    69  		`SELECT sample(value, 2) FROM cpu`,
    70  		`SELECT sample(*, 2) FROM cpu`,
    71  		`SELECT sample(/val/, 2) FROM cpu`,
    72  		`SELECT elapsed(value) FROM cpu`,
    73  		`SELECT elapsed(value, 10s) FROM cpu`,
    74  		`SELECT integral(value) FROM cpu`,
    75  		`SELECT integral(value, 10s) FROM cpu`,
    76  		`SELECT max(value) FROM cpu WHERE time >= now() - 1m GROUP BY time(10s, 5s)`,
    77  		`SELECT max(value) FROM cpu WHERE time >= now() - 1m GROUP BY time(10s, '2000-01-01T00:00:05Z')`,
    78  		`SELECT max(value) FROM cpu WHERE time >= now() - 1m GROUP BY time(10s, now())`,
    79  		`SELECT max(mean) FROM (SELECT mean(value) FROM cpu GROUP BY host)`,
    80  		`SELECT top(mean, 10), host FROM (SELECT mean(value) FROM cpu WHERE id =~ /^(server-1|server-2|server-3)$/ GROUP BY host)`,
    81  		`SELECT max(derivative) FROM (SELECT derivative(mean(value)) FROM cpu) WHERE time >= now() - 1m GROUP BY time(10s)`,
    82  		`SELECT max(value) FROM (SELECT value + total FROM cpu) WHERE time >= now() - 1m GROUP BY time(10s)`,
    83  		`SELECT value FROM cpu WHERE time >= '2000-01-01T00:00:00Z' AND time <= '2000-01-01T01:00:00Z'`,
    84  		`SELECT value FROM (SELECT value FROM cpu) ORDER BY time DESC`,
    85  		`SELECT count(distinct(value)), max(value) FROM cpu`,
    86  		`SELECT derivative(distinct(value)), difference(distinct(value)) FROM cpu WHERE time >= now() - 1m GROUP BY time(5s)`,
    87  		`SELECT moving_average(distinct(value), 3) FROM cpu WHERE time >= now() - 5m GROUP BY time(1m)`,
    88  		`SELECT elapsed(distinct(value)) FROM cpu WHERE time >= now() - 5m GROUP BY time(1m)`,
    89  		`SELECT cumulative_sum(distinct(value)) FROM cpu WHERE time >= now() - 5m GROUP BY time(1m)`,
    90  		`SELECT last(value) / (1 - 0) FROM cpu`,
    91  		`SELECT abs(value) FROM cpu`,
    92  		`SELECT sin(value) FROM cpu`,
    93  		`SELECT cos(value) FROM cpu`,
    94  		`SELECT tan(value) FROM cpu`,
    95  		`SELECT asin(value) FROM cpu`,
    96  		`SELECT acos(value) FROM cpu`,
    97  		`SELECT atan(value) FROM cpu`,
    98  		`SELECT sqrt(value) FROM cpu`,
    99  		`SELECT pow(value, 2) FROM cpu`,
   100  		`SELECT pow(value, 3.14) FROM cpu`,
   101  		`SELECT pow(2, value) FROM cpu`,
   102  		`SELECT pow(3.14, value) FROM cpu`,
   103  		`SELECT exp(value) FROM cpu`,
   104  		`SELECT atan2(value, 0.1) FROM cpu`,
   105  		`SELECT atan2(0.2, value) FROM cpu`,
   106  		`SELECT atan2(value, 1) FROM cpu`,
   107  		`SELECT atan2(2, value) FROM cpu`,
   108  		`SELECT ln(value) FROM cpu`,
   109  		`SELECT log(value, 2) FROM cpu`,
   110  		`SELECT log2(value) FROM cpu`,
   111  		`SELECT log10(value) FROM cpu`,
   112  		`SELECT sin(value) - sin(1.3) FROM cpu`,
   113  		`SELECT value FROM cpu WHERE sin(value) > 0.5`,
   114  		`SELECT sum("out")/sum("in") FROM (SELECT derivative("out") AS "out", derivative("in") AS "in" FROM "m0" WHERE time >= now() - 5m GROUP BY "index") GROUP BY time(1m) fill(none)`,
   115  	} {
   116  		t.Run(tt, func(t *testing.T) {
   117  			stmt, err := influxql.ParseStatement(tt)
   118  			if err != nil {
   119  				t.Fatalf("unexpected error: %s", err)
   120  			}
   121  			s := stmt.(*influxql.SelectStatement)
   122  
   123  			opt := query.CompileOptions{}
   124  			if _, err := query.Compile(s, opt); err != nil {
   125  				t.Errorf("unexpected error: %s", err)
   126  			}
   127  		})
   128  	}
   129  }
   130  
   131  func TestCompile_Failures(t *testing.T) {
   132  	for _, tt := range []struct {
   133  		s   string
   134  		err string
   135  	}{
   136  		{s: `SELECT time FROM cpu`, err: `at least 1 non-time field must be queried`},
   137  		{s: `SELECT value, mean(value) FROM cpu`, err: `mixing aggregate and non-aggregate queries is not supported`},
   138  		{s: `SELECT value, max(value), min(value) FROM cpu`, err: `mixing multiple selector functions with tags or fields is not supported`},
   139  		{s: `SELECT top(value, 10), max(value) FROM cpu`, err: `selector function top() cannot be combined with other functions`},
   140  		{s: `SELECT bottom(value, 10), max(value) FROM cpu`, err: `selector function bottom() cannot be combined with other functions`},
   141  		{s: `SELECT count() FROM cpu`, err: `invalid number of arguments for count, expected 1, got 0`},
   142  		{s: `SELECT count(value, host) FROM cpu`, err: `invalid number of arguments for count, expected 1, got 2`},
   143  		{s: `SELECT min() FROM cpu`, err: `invalid number of arguments for min, expected 1, got 0`},
   144  		{s: `SELECT min(value, host) FROM cpu`, err: `invalid number of arguments for min, expected 1, got 2`},
   145  		{s: `SELECT max() FROM cpu`, err: `invalid number of arguments for max, expected 1, got 0`},
   146  		{s: `SELECT max(value, host) FROM cpu`, err: `invalid number of arguments for max, expected 1, got 2`},
   147  		{s: `SELECT sum() FROM cpu`, err: `invalid number of arguments for sum, expected 1, got 0`},
   148  		{s: `SELECT sum(value, host) FROM cpu`, err: `invalid number of arguments for sum, expected 1, got 2`},
   149  		{s: `SELECT first() FROM cpu`, err: `invalid number of arguments for first, expected 1, got 0`},
   150  		{s: `SELECT first(value, host) FROM cpu`, err: `invalid number of arguments for first, expected 1, got 2`},
   151  		{s: `SELECT last() FROM cpu`, err: `invalid number of arguments for last, expected 1, got 0`},
   152  		{s: `SELECT last(value, host) FROM cpu`, err: `invalid number of arguments for last, expected 1, got 2`},
   153  		{s: `SELECT mean() FROM cpu`, err: `invalid number of arguments for mean, expected 1, got 0`},
   154  		{s: `SELECT mean(value, host) FROM cpu`, err: `invalid number of arguments for mean, expected 1, got 2`},
   155  		{s: `SELECT distinct(value), max(value) FROM cpu`, err: `aggregate function distinct() cannot be combined with other functions or fields`},
   156  		{s: `SELECT count(distinct()) FROM cpu`, err: `distinct function requires at least one argument`},
   157  		{s: `SELECT count(distinct(value, host)) FROM cpu`, err: `distinct function can only have one argument`},
   158  		{s: `SELECT count(distinct(2)) FROM cpu`, err: `expected field argument in distinct()`},
   159  		{s: `SELECT value FROM cpu GROUP BY now()`, err: `only time() calls allowed in dimensions`},
   160  		{s: `SELECT value FROM cpu GROUP BY time()`, err: `time dimension expected 1 or 2 arguments`},
   161  		{s: `SELECT value FROM cpu GROUP BY time(5m, 30s, 1ms)`, err: `time dimension expected 1 or 2 arguments`},
   162  		{s: `SELECT value FROM cpu GROUP BY time('unexpected')`, err: `time dimension must have duration argument`},
   163  		{s: `SELECT value FROM cpu GROUP BY time(5m), time(1m)`, err: `multiple time dimensions not allowed`},
   164  		{s: `SELECT value FROM cpu GROUP BY time(5m, unexpected())`, err: `time dimension offset function must be now()`},
   165  		{s: `SELECT value FROM cpu GROUP BY time(5m, now(1m))`, err: `time dimension offset now() function requires no arguments`},
   166  		{s: `SELECT value FROM cpu GROUP BY time(5m, 'unexpected')`, err: `time dimension offset must be duration or now()`},
   167  		{s: `SELECT value FROM cpu GROUP BY 'unexpected'`, err: `only time and tag dimensions allowed`},
   168  		{s: `SELECT top(value) FROM cpu`, err: `invalid number of arguments for top, expected at least 2, got 1`},
   169  		{s: `SELECT top('unexpected', 5) FROM cpu`, err: `expected first argument to be a field in top(), found 'unexpected'`},
   170  		{s: `SELECT top(value, 'unexpected', 5) FROM cpu`, err: `only fields or tags are allowed in top(), found 'unexpected'`},
   171  		{s: `SELECT top(value, 2.5) FROM cpu`, err: `expected integer as last argument in top(), found 2.500`},
   172  		{s: `SELECT top(value, -1) FROM cpu`, err: `limit (-1) in top function must be at least 1`},
   173  		{s: `SELECT top(value, 3) FROM cpu LIMIT 2`, err: `limit (3) in top function can not be larger than the LIMIT (2) in the select statement`},
   174  		{s: `SELECT bottom(value) FROM cpu`, err: `invalid number of arguments for bottom, expected at least 2, got 1`},
   175  		{s: `SELECT bottom('unexpected', 5) FROM cpu`, err: `expected first argument to be a field in bottom(), found 'unexpected'`},
   176  		{s: `SELECT bottom(value, 'unexpected', 5) FROM cpu`, err: `only fields or tags are allowed in bottom(), found 'unexpected'`},
   177  		{s: `SELECT bottom(value, 2.5) FROM cpu`, err: `expected integer as last argument in bottom(), found 2.500`},
   178  		{s: `SELECT bottom(value, -1) FROM cpu`, err: `limit (-1) in bottom function must be at least 1`},
   179  		{s: `SELECT bottom(value, 3) FROM cpu LIMIT 2`, err: `limit (3) in bottom function can not be larger than the LIMIT (2) in the select statement`},
   180  		// TODO(jsternberg): This query is wrong, but we cannot enforce this because of previous behavior: https://github.com/influxdata/influxdb/pull/8771
   181  		//{s: `SELECT value FROM cpu WHERE time >= now() - 10m OR time < now() - 5m`, err: `cannot use OR with time conditions`},
   182  		{s: `SELECT value FROM cpu WHERE value`, err: `invalid condition expression: value`},
   183  		{s: `SELECT count(value), * FROM cpu`, err: `mixing aggregate and non-aggregate queries is not supported`},
   184  		{s: `SELECT max(*), host FROM cpu`, err: `mixing aggregate and non-aggregate queries is not supported`},
   185  		{s: `SELECT count(value), /ho/ FROM cpu`, err: `mixing aggregate and non-aggregate queries is not supported`},
   186  		{s: `SELECT max(/val/), * FROM cpu`, err: `mixing aggregate and non-aggregate queries is not supported`},
   187  		{s: `SELECT a(value) FROM cpu`, err: `undefined function a()`},
   188  		{s: `SELECT count(max(value)) FROM myseries`, err: `expected field argument in count()`},
   189  		{s: `SELECT count(distinct('value')) FROM myseries`, err: `expected field argument in distinct()`},
   190  		{s: `SELECT distinct('value') FROM myseries`, err: `expected field argument in distinct()`},
   191  		{s: `SELECT min(max(value)) FROM myseries`, err: `expected field argument in min()`},
   192  		{s: `SELECT min(distinct(value)) FROM myseries`, err: `expected field argument in min()`},
   193  		{s: `SELECT max(max(value)) FROM myseries`, err: `expected field argument in max()`},
   194  		{s: `SELECT sum(max(value)) FROM myseries`, err: `expected field argument in sum()`},
   195  		{s: `SELECT first(max(value)) FROM myseries`, err: `expected field argument in first()`},
   196  		{s: `SELECT last(max(value)) FROM myseries`, err: `expected field argument in last()`},
   197  		{s: `SELECT mean(max(value)) FROM myseries`, err: `expected field argument in mean()`},
   198  		{s: `SELECT median(max(value)) FROM myseries`, err: `expected field argument in median()`},
   199  		{s: `SELECT mode(max(value)) FROM myseries`, err: `expected field argument in mode()`},
   200  		{s: `SELECT stddev(max(value)) FROM myseries`, err: `expected field argument in stddev()`},
   201  		{s: `SELECT spread(max(value)) FROM myseries`, err: `expected field argument in spread()`},
   202  		{s: `SELECT top() FROM myseries`, err: `invalid number of arguments for top, expected at least 2, got 0`},
   203  		{s: `SELECT top(field1) FROM myseries`, err: `invalid number of arguments for top, expected at least 2, got 1`},
   204  		{s: `SELECT top(field1,foo) FROM myseries`, err: `expected integer as last argument in top(), found foo`},
   205  		{s: `SELECT top(field1,host,'server',foo) FROM myseries`, err: `expected integer as last argument in top(), found foo`},
   206  		{s: `SELECT top(field1,5,'server',2) FROM myseries`, err: `only fields or tags are allowed in top(), found 5`},
   207  		{s: `SELECT top(field1,max(foo),'server',2) FROM myseries`, err: `only fields or tags are allowed in top(), found max(foo)`},
   208  		{s: `SELECT top(value, 10) + count(value) FROM myseries`, err: `selector function top() cannot be combined with other functions`},
   209  		{s: `SELECT top(max(value), 10) FROM myseries`, err: `expected first argument to be a field in top(), found max(value)`},
   210  		{s: `SELECT bottom() FROM myseries`, err: `invalid number of arguments for bottom, expected at least 2, got 0`},
   211  		{s: `SELECT bottom(field1) FROM myseries`, err: `invalid number of arguments for bottom, expected at least 2, got 1`},
   212  		{s: `SELECT bottom(field1,foo) FROM myseries`, err: `expected integer as last argument in bottom(), found foo`},
   213  		{s: `SELECT bottom(field1,host,'server',foo) FROM myseries`, err: `expected integer as last argument in bottom(), found foo`},
   214  		{s: `SELECT bottom(field1,5,'server',2) FROM myseries`, err: `only fields or tags are allowed in bottom(), found 5`},
   215  		{s: `SELECT bottom(field1,max(foo),'server',2) FROM myseries`, err: `only fields or tags are allowed in bottom(), found max(foo)`},
   216  		{s: `SELECT bottom(value, 10) + count(value) FROM myseries`, err: `selector function bottom() cannot be combined with other functions`},
   217  		{s: `SELECT bottom(max(value), 10) FROM myseries`, err: `expected first argument to be a field in bottom(), found max(value)`},
   218  		{s: `SELECT top(value, 10), bottom(value, 10) FROM cpu`, err: `selector function top() cannot be combined with other functions`},
   219  		{s: `SELECT bottom(value, 10), top(value, 10) FROM cpu`, err: `selector function bottom() cannot be combined with other functions`},
   220  		{s: `SELECT sample(value) FROM myseries`, err: `invalid number of arguments for sample, expected 2, got 1`},
   221  		{s: `SELECT sample(value, 2, 3) FROM myseries`, err: `invalid number of arguments for sample, expected 2, got 3`},
   222  		{s: `SELECT sample(value, 0) FROM myseries`, err: `sample window must be greater than 1, got 0`},
   223  		{s: `SELECT sample(value, 2.5) FROM myseries`, err: `expected integer argument in sample()`},
   224  		{s: `SELECT percentile() FROM myseries`, err: `invalid number of arguments for percentile, expected 2, got 0`},
   225  		{s: `SELECT percentile(field1) FROM myseries`, err: `invalid number of arguments for percentile, expected 2, got 1`},
   226  		{s: `SELECT percentile(field1, foo) FROM myseries`, err: `expected float argument in percentile()`},
   227  		{s: `SELECT percentile(max(field1), 75) FROM myseries`, err: `expected field argument in percentile()`},
   228  		{s: `SELECT field1 FROM foo group by time(1s)`, err: `GROUP BY requires at least one aggregate function`},
   229  		{s: `SELECT field1 FROM foo fill(none)`, err: `fill(none) must be used with a function`},
   230  		{s: `SELECT field1 FROM foo fill(linear)`, err: `fill(linear) must be used with a function`},
   231  		{s: `SELECT count(value), value FROM foo`, err: `mixing aggregate and non-aggregate queries is not supported`},
   232  		{s: `SELECT count(value) FROM foo group by time`, err: `time() is a function and expects at least one argument`},
   233  		{s: `SELECT count(value) FROM foo group by 'time'`, err: `only time and tag dimensions allowed`},
   234  		{s: `SELECT count(value) FROM foo where time > now() and time < now() group by time()`, err: `time dimension expected 1 or 2 arguments`},
   235  		{s: `SELECT count(value) FROM foo where time > now() and time < now() group by time(b)`, err: `time dimension must have duration argument`},
   236  		{s: `SELECT count(value) FROM foo where time > now() and time < now() group by time(1s), time(2s)`, err: `multiple time dimensions not allowed`},
   237  		{s: `SELECT count(value) FROM foo where time > now() and time < now() group by time(1s, b)`, err: `time dimension offset must be duration or now()`},
   238  		{s: `SELECT count(value) FROM foo where time > now() and time < now() group by time(1s, '5s')`, err: `time dimension offset must be duration or now()`},
   239  		{s: `SELECT distinct(field1), sum(field1) FROM myseries`, err: `aggregate function distinct() cannot be combined with other functions or fields`},
   240  		{s: `SELECT distinct(field1), field2 FROM myseries`, err: `aggregate function distinct() cannot be combined with other functions or fields`},
   241  		{s: `SELECT distinct(field1, field2) FROM myseries`, err: `distinct function can only have one argument`},
   242  		{s: `SELECT distinct() FROM myseries`, err: `distinct function requires at least one argument`},
   243  		{s: `SELECT distinct field1, field2 FROM myseries`, err: `aggregate function distinct() cannot be combined with other functions or fields`},
   244  		{s: `SELECT count(distinct field1, field2) FROM myseries`, err: `invalid number of arguments for count, expected 1, got 2`},
   245  		{s: `select count(distinct(too, many, arguments)) from myseries`, err: `distinct function can only have one argument`},
   246  		{s: `select count() from myseries`, err: `invalid number of arguments for count, expected 1, got 0`},
   247  		{s: `SELECT derivative(field1), field1 FROM myseries`, err: `mixing aggregate and non-aggregate queries is not supported`},
   248  		{s: `select derivative() from myseries`, err: `invalid number of arguments for derivative, expected at least 1 but no more than 2, got 0`},
   249  		{s: `select derivative(mean(value), 1h, 3) from myseries`, err: `invalid number of arguments for derivative, expected at least 1 but no more than 2, got 3`},
   250  		{s: `SELECT derivative(value) FROM myseries group by time(1h)`, err: `aggregate function required inside the call to derivative`},
   251  		{s: `SELECT derivative(top(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for top, expected at least 2, got 1`},
   252  		{s: `SELECT derivative(bottom(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for bottom, expected at least 2, got 1`},
   253  		{s: `SELECT derivative(max()) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for max, expected 1, got 0`},
   254  		{s: `SELECT derivative(percentile(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for percentile, expected 2, got 1`},
   255  		{s: `SELECT derivative(mean(value), 1h) FROM myseries where time < now() and time > now() - 1d`, err: `derivative aggregate requires a GROUP BY interval`},
   256  		{s: `SELECT derivative(value, -2h) FROM myseries`, err: `duration argument must be positive, got -2h`},
   257  		{s: `SELECT derivative(value, 10) FROM myseries`, err: `second argument to derivative must be a duration, got *influxql.IntegerLiteral`},
   258  		{s: `SELECT derivative(f, true) FROM myseries`, err: `second argument to derivative must be a duration, got *influxql.BooleanLiteral`},
   259  		{s: `SELECT non_negative_derivative(field1), field1 FROM myseries`, err: `mixing aggregate and non-aggregate queries is not supported`},
   260  		{s: `select non_negative_derivative() from myseries`, err: `invalid number of arguments for non_negative_derivative, expected at least 1 but no more than 2, got 0`},
   261  		{s: `select non_negative_derivative(mean(value), 1h, 3) from myseries`, err: `invalid number of arguments for non_negative_derivative, expected at least 1 but no more than 2, got 3`},
   262  		{s: `SELECT non_negative_derivative(value) FROM myseries group by time(1h)`, err: `aggregate function required inside the call to non_negative_derivative`},
   263  		{s: `SELECT non_negative_derivative(top(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for top, expected at least 2, got 1`},
   264  		{s: `SELECT non_negative_derivative(bottom(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for bottom, expected at least 2, got 1`},
   265  		{s: `SELECT non_negative_derivative(max()) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for max, expected 1, got 0`},
   266  		{s: `SELECT non_negative_derivative(mean(value), 1h) FROM myseries where time < now() and time > now() - 1d`, err: `non_negative_derivative aggregate requires a GROUP BY interval`},
   267  		{s: `SELECT non_negative_derivative(percentile(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for percentile, expected 2, got 1`},
   268  		{s: `SELECT non_negative_derivative(value, -2h) FROM myseries`, err: `duration argument must be positive, got -2h`},
   269  		{s: `SELECT non_negative_derivative(value, 10) FROM myseries`, err: `second argument to non_negative_derivative must be a duration, got *influxql.IntegerLiteral`},
   270  		{s: `SELECT difference(field1), field1 FROM myseries`, err: `mixing aggregate and non-aggregate queries is not supported`},
   271  		{s: `SELECT difference() from myseries`, err: `invalid number of arguments for difference, expected 1, got 0`},
   272  		{s: `SELECT difference(value) FROM myseries group by time(1h)`, err: `aggregate function required inside the call to difference`},
   273  		{s: `SELECT difference(top(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for top, expected at least 2, got 1`},
   274  		{s: `SELECT difference(bottom(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for bottom, expected at least 2, got 1`},
   275  		{s: `SELECT difference(max()) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for max, expected 1, got 0`},
   276  		{s: `SELECT difference(percentile(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for percentile, expected 2, got 1`},
   277  		{s: `SELECT difference(mean(value)) FROM myseries where time < now() and time > now() - 1d`, err: `difference aggregate requires a GROUP BY interval`},
   278  		{s: `SELECT non_negative_difference(field1), field1 FROM myseries`, err: `mixing aggregate and non-aggregate queries is not supported`},
   279  		{s: `SELECT non_negative_difference() from myseries`, err: `invalid number of arguments for non_negative_difference, expected 1, got 0`},
   280  		{s: `SELECT non_negative_difference(value) FROM myseries group by time(1h)`, err: `aggregate function required inside the call to non_negative_difference`},
   281  		{s: `SELECT non_negative_difference(top(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for top, expected at least 2, got 1`},
   282  		{s: `SELECT non_negative_difference(bottom(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for bottom, expected at least 2, got 1`},
   283  		{s: `SELECT non_negative_difference(max()) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for max, expected 1, got 0`},
   284  		{s: `SELECT non_negative_difference(percentile(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for percentile, expected 2, got 1`},
   285  		{s: `SELECT non_negative_difference(mean(value)) FROM myseries where time < now() and time > now() - 1d`, err: `non_negative_difference aggregate requires a GROUP BY interval`},
   286  		{s: `SELECT elapsed() FROM myseries`, err: `invalid number of arguments for elapsed, expected at least 1 but no more than 2, got 0`},
   287  		{s: `SELECT elapsed(value) FROM myseries group by time(1h)`, err: `aggregate function required inside the call to elapsed`},
   288  		{s: `SELECT elapsed(value, 1s, host) FROM myseries`, err: `invalid number of arguments for elapsed, expected at least 1 but no more than 2, got 3`},
   289  		{s: `SELECT elapsed(value, 0s) FROM myseries`, err: `duration argument must be positive, got 0s`},
   290  		{s: `SELECT elapsed(value, -10s) FROM myseries`, err: `duration argument must be positive, got -10s`},
   291  		{s: `SELECT elapsed(value, 10) FROM myseries`, err: `second argument to elapsed must be a duration, got *influxql.IntegerLiteral`},
   292  		{s: `SELECT elapsed(top(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for top, expected at least 2, got 1`},
   293  		{s: `SELECT elapsed(bottom(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for bottom, expected at least 2, got 1`},
   294  		{s: `SELECT elapsed(max()) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for max, expected 1, got 0`},
   295  		{s: `SELECT elapsed(percentile(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for percentile, expected 2, got 1`},
   296  		{s: `SELECT elapsed(mean(value)) FROM myseries where time < now() and time > now() - 1d`, err: `elapsed aggregate requires a GROUP BY interval`},
   297  		{s: `SELECT moving_average(field1, 2), field1 FROM myseries`, err: `mixing aggregate and non-aggregate queries is not supported`},
   298  		{s: `SELECT moving_average(field1, 1), field1 FROM myseries`, err: `moving_average window must be greater than 1, got 1`},
   299  		{s: `SELECT moving_average(field1, 0), field1 FROM myseries`, err: `moving_average window must be greater than 1, got 0`},
   300  		{s: `SELECT moving_average(field1, -1), field1 FROM myseries`, err: `moving_average window must be greater than 1, got -1`},
   301  		{s: `SELECT moving_average(field1, 2.0), field1 FROM myseries`, err: `second argument for moving_average must be an integer, got *influxql.NumberLiteral`},
   302  		{s: `SELECT moving_average() from myseries`, err: `invalid number of arguments for moving_average, expected 2, got 0`},
   303  		{s: `SELECT moving_average(value) FROM myseries`, err: `invalid number of arguments for moving_average, expected 2, got 1`},
   304  		{s: `SELECT moving_average(value, 2) FROM myseries group by time(1h)`, err: `aggregate function required inside the call to moving_average`},
   305  		{s: `SELECT moving_average(top(value), 2) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for top, expected at least 2, got 1`},
   306  		{s: `SELECT moving_average(bottom(value), 2) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for bottom, expected at least 2, got 1`},
   307  		{s: `SELECT moving_average(max(), 2) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for max, expected 1, got 0`},
   308  		{s: `SELECT moving_average(percentile(value), 2) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for percentile, expected 2, got 1`},
   309  		{s: `SELECT moving_average(mean(value), 2) FROM myseries where time < now() and time > now() - 1d`, err: `moving_average aggregate requires a GROUP BY interval`},
   310  		{s: `SELECT cumulative_sum(field1), field1 FROM myseries`, err: `mixing aggregate and non-aggregate queries is not supported`},
   311  		{s: `SELECT cumulative_sum() from myseries`, err: `invalid number of arguments for cumulative_sum, expected 1, got 0`},
   312  		{s: `SELECT cumulative_sum(value) FROM myseries group by time(1h)`, err: `aggregate function required inside the call to cumulative_sum`},
   313  		{s: `SELECT cumulative_sum(top(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for top, expected at least 2, got 1`},
   314  		{s: `SELECT cumulative_sum(bottom(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for bottom, expected at least 2, got 1`},
   315  		{s: `SELECT cumulative_sum(max()) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for max, expected 1, got 0`},
   316  		{s: `SELECT cumulative_sum(percentile(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for percentile, expected 2, got 1`},
   317  		{s: `SELECT cumulative_sum(mean(value)) FROM myseries where time < now() and time > now() - 1d`, err: `cumulative_sum aggregate requires a GROUP BY interval`},
   318  		{s: `SELECT integral() FROM myseries`, err: `invalid number of arguments for integral, expected at least 1 but no more than 2, got 0`},
   319  		{s: `SELECT integral(value, 10s, host) FROM myseries`, err: `invalid number of arguments for integral, expected at least 1 but no more than 2, got 3`},
   320  		{s: `SELECT integral(value, -10s) FROM myseries`, err: `duration argument must be positive, got -10s`},
   321  		{s: `SELECT integral(value, 10) FROM myseries`, err: `second argument must be a duration`},
   322  		{s: `SELECT holt_winters(value) FROM myseries where time < now() and time > now() - 1d`, err: `invalid number of arguments for holt_winters, expected 3, got 1`},
   323  		{s: `SELECT holt_winters(value, 10, 2) FROM myseries where time < now() and time > now() - 1d`, err: `must use aggregate function with holt_winters`},
   324  		{s: `SELECT holt_winters(min(value), 10, 2) FROM myseries where time < now() and time > now() - 1d`, err: `holt_winters aggregate requires a GROUP BY interval`},
   325  		{s: `SELECT holt_winters(min(value), 0, 2) FROM myseries where time < now() and time > now() - 1d GROUP BY time(1d)`, err: `second arg to holt_winters must be greater than 0, got 0`},
   326  		{s: `SELECT holt_winters(min(value), false, 2) FROM myseries where time < now() and time > now() - 1d GROUP BY time(1d)`, err: `expected integer argument as second arg in holt_winters`},
   327  		{s: `SELECT holt_winters(min(value), 10, 'string') FROM myseries where time < now() and time > now() - 1d GROUP BY time(1d)`, err: `expected integer argument as third arg in holt_winters`},
   328  		{s: `SELECT holt_winters(min(value), 10, -1) FROM myseries where time < now() and time > now() - 1d GROUP BY time(1d)`, err: `third arg to holt_winters cannot be negative, got -1`},
   329  		{s: `SELECT holt_winters_with_fit(value) FROM myseries where time < now() and time > now() - 1d`, err: `invalid number of arguments for holt_winters_with_fit, expected 3, got 1`},
   330  		{s: `SELECT holt_winters_with_fit(value, 10, 2) FROM myseries where time < now() and time > now() - 1d`, err: `must use aggregate function with holt_winters_with_fit`},
   331  		{s: `SELECT holt_winters_with_fit(min(value), 10, 2) FROM myseries where time < now() and time > now() - 1d`, err: `holt_winters_with_fit aggregate requires a GROUP BY interval`},
   332  		{s: `SELECT holt_winters_with_fit(min(value), 0, 2) FROM myseries where time < now() and time > now() - 1d GROUP BY time(1d)`, err: `second arg to holt_winters_with_fit must be greater than 0, got 0`},
   333  		{s: `SELECT holt_winters_with_fit(min(value), false, 2) FROM myseries where time < now() and time > now() - 1d GROUP BY time(1d)`, err: `expected integer argument as second arg in holt_winters_with_fit`},
   334  		{s: `SELECT holt_winters_with_fit(min(value), 10, 'string') FROM myseries where time < now() and time > now() - 1d GROUP BY time(1d)`, err: `expected integer argument as third arg in holt_winters_with_fit`},
   335  		{s: `SELECT holt_winters_with_fit(min(value), 10, -1) FROM myseries where time < now() and time > now() - 1d GROUP BY time(1d)`, err: `third arg to holt_winters_with_fit cannot be negative, got -1`},
   336  		{s: `SELECT mean(value) + value FROM cpu WHERE time < now() and time > now() - 1h GROUP BY time(10m)`, err: `mixing aggregate and non-aggregate queries is not supported`},
   337  		// TODO: Remove this restriction in the future: https://github.com/influxdata/influxdb/issues/5968
   338  		{s: `SELECT mean(cpu_total - cpu_idle) FROM cpu`, err: `expected field argument in mean()`},
   339  		{s: `SELECT derivative(mean(cpu_total - cpu_idle), 1s) FROM cpu WHERE time < now() AND time > now() - 1d GROUP BY time(1h)`, err: `expected field argument in mean()`},
   340  		// TODO: The error message will change when math is allowed inside an aggregate: https://github.com/influxdata/influxdb/pull/5990#issuecomment-195565870
   341  		{s: `SELECT count(foo + sum(bar)) FROM cpu`, err: `expected field argument in count()`},
   342  		{s: `SELECT (count(foo + sum(bar))) FROM cpu`, err: `expected field argument in count()`},
   343  		{s: `SELECT sum(value) + count(foo + sum(bar)) FROM cpu`, err: `expected field argument in count()`},
   344  		{s: `SELECT top(value, 2), max(value) FROM cpu`, err: `selector function top() cannot be combined with other functions`},
   345  		{s: `SELECT bottom(value, 2), max(value) FROM cpu`, err: `selector function bottom() cannot be combined with other functions`},
   346  		{s: `SELECT min(derivative) FROM (SELECT derivative(mean(value), 1h) FROM myseries) where time < now() and time > now() - 1d`, err: `derivative aggregate requires a GROUP BY interval`},
   347  		{s: `SELECT min(mean) FROM (SELECT mean(value) FROM myseries GROUP BY time)`, err: `time() is a function and expects at least one argument`},
   348  		{s: `SELECT value FROM myseries WHERE value OR time >= now() - 1m`, err: `invalid condition expression: value`},
   349  		{s: `SELECT value FROM myseries WHERE time >= now() - 1m OR value`, err: `invalid condition expression: value`},
   350  		{s: `SELECT value FROM (SELECT value FROM cpu ORDER BY time DESC) ORDER BY time ASC`, err: `subqueries must be ordered in the same direction as the query itself`},
   351  		{s: `SELECT sin(value, 3) FROM cpu`, err: `invalid number of arguments for sin, expected 1, got 2`},
   352  		{s: `SELECT cos(2.3, value, 3) FROM cpu`, err: `invalid number of arguments for cos, expected 1, got 3`},
   353  		{s: `SELECT tan(value, 3) FROM cpu`, err: `invalid number of arguments for tan, expected 1, got 2`},
   354  		{s: `SELECT asin(value, 3) FROM cpu`, err: `invalid number of arguments for asin, expected 1, got 2`},
   355  		{s: `SELECT acos(value, 3.2) FROM cpu`, err: `invalid number of arguments for acos, expected 1, got 2`},
   356  		{s: `SELECT atan() FROM cpu`, err: `invalid number of arguments for atan, expected 1, got 0`},
   357  		{s: `SELECT sqrt(42, 3, 4) FROM cpu`, err: `invalid number of arguments for sqrt, expected 1, got 3`},
   358  		{s: `SELECT abs(value, 3) FROM cpu`, err: `invalid number of arguments for abs, expected 1, got 2`},
   359  		{s: `SELECT ln(value, 3) FROM cpu`, err: `invalid number of arguments for ln, expected 1, got 2`},
   360  		{s: `SELECT log2(value, 3) FROM cpu`, err: `invalid number of arguments for log2, expected 1, got 2`},
   361  		{s: `SELECT log10(value, 3) FROM cpu`, err: `invalid number of arguments for log10, expected 1, got 2`},
   362  		{s: `SELECT pow(value, 3, 3) FROM cpu`, err: `invalid number of arguments for pow, expected 2, got 3`},
   363  		{s: `SELECT atan2(value, 3, 3) FROM cpu`, err: `invalid number of arguments for atan2, expected 2, got 3`},
   364  		{s: `SELECT sin(1.3) FROM cpu`, err: `field must contain at least one variable`},
   365  		{s: `SELECT nofunc(1.3) FROM cpu`, err: `undefined function nofunc()`},
   366  		{s: `SELECT * FROM cpu WHERE ( host =~ /foo/ ^ other AND env =~ /bar/ ) and time >= now()-15m`, err: `likely malformed statement, unable to rewrite: interface conversion: influxql.Expr is *influxql.BinaryExpr, not *influxql.RegexLiteral`},
   367  	} {
   368  		t.Run(tt.s, func(t *testing.T) {
   369  			stmt, err := influxql.ParseStatement(tt.s)
   370  			if err != nil {
   371  				t.Fatalf("unexpected error: %s", err)
   372  			}
   373  			s := stmt.(*influxql.SelectStatement)
   374  
   375  			opt := query.CompileOptions{}
   376  			if _, err := query.Compile(s, opt); err == nil {
   377  				t.Error("expected error")
   378  			} else if have, want := err.Error(), tt.err; have != want {
   379  				t.Errorf("unexpected error: %s != %s", have, want)
   380  			}
   381  		})
   382  	}
   383  }
   384  
   385  func TestPrepare_MapShardsTimeRange(t *testing.T) {
   386  	for _, tt := range []struct {
   387  		s          string
   388  		start, end string
   389  	}{
   390  		{
   391  			s:     `SELECT max(value) FROM cpu WHERE time >= '2018-09-03T15:00:00Z' AND time <= '2018-09-03T16:00:00Z' GROUP BY time(10m)`,
   392  			start: "2018-09-03T15:00:00Z",
   393  			end:   "2018-09-03T16:00:00Z",
   394  		},
   395  		{
   396  			s:     `SELECT derivative(mean(value)) FROM cpu WHERE time >= '2018-09-03T15:00:00Z' AND time <= '2018-09-03T16:00:00Z' GROUP BY time(10m)`,
   397  			start: "2018-09-03T14:50:00Z",
   398  			end:   "2018-09-03T16:00:00Z",
   399  		},
   400  		{
   401  			s:     `SELECT moving_average(mean(value), 3) FROM cpu WHERE time >= '2018-09-03T15:00:00Z' AND time <= '2018-09-03T16:00:00Z' GROUP BY time(10m)`,
   402  			start: "2018-09-03T14:30:00Z",
   403  			end:   "2018-09-03T16:00:00Z",
   404  		},
   405  		{
   406  			s:     `SELECT moving_average(mean(value), 3) FROM cpu WHERE time <= '2018-09-03T16:00:00Z' GROUP BY time(10m)`,
   407  			start: "1677-09-21T00:12:43.145224194Z",
   408  			end:   "2018-09-03T16:00:00Z",
   409  		},
   410  	} {
   411  		t.Run(tt.s, func(t *testing.T) {
   412  			stmt, err := influxql.ParseStatement(tt.s)
   413  			if err != nil {
   414  				t.Fatalf("unexpected error: %s", err)
   415  			}
   416  			s := stmt.(*influxql.SelectStatement)
   417  
   418  			opt := query.CompileOptions{}
   419  			c, err := query.Compile(s, opt)
   420  			if err != nil {
   421  				t.Fatalf("unexpected error: %s", err)
   422  			}
   423  
   424  			shardMapper := ShardMapper{
   425  				MapShardsFn: func(_ context.Context, _ influxql.Sources, tr influxql.TimeRange) query.ShardGroup {
   426  					if got, want := tr.Min, mustParseTime(tt.start); !got.Equal(want) {
   427  						t.Errorf("unexpected start time: got=%s want=%s", got, want)
   428  					}
   429  					if got, want := tr.Max, mustParseTime(tt.end); !got.Equal(want) {
   430  						t.Errorf("unexpected end time: got=%s want=%s", got, want)
   431  					}
   432  					return &ShardGroup{}
   433  				},
   434  			}
   435  
   436  			if _, err := c.Prepare(context.Background(), &shardMapper, query.SelectOptions{}); err != nil {
   437  				t.Fatalf("unexpected error: %s", err)
   438  			}
   439  		})
   440  	}
   441  }