github.com/influxdata/influxql@v1.1.0/parser_test.go (about)

     1  package influxql_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"reflect"
     7  	"regexp"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/influxdata/influxql"
    13  )
    14  
    15  // Ensure the parser can parse a multi-statement query.
    16  func TestParser_ParseQuery(t *testing.T) {
    17  	s := `SELECT a FROM b; SELECT c FROM d`
    18  	q, err := influxql.NewParser(strings.NewReader(s)).ParseQuery()
    19  	if err != nil {
    20  		t.Fatalf("unexpected error: %s", err)
    21  	} else if len(q.Statements) != 2 {
    22  		t.Fatalf("unexpected statement count: %d", len(q.Statements))
    23  	}
    24  }
    25  
    26  func TestParser_ParseQuery_TrailingSemicolon(t *testing.T) {
    27  	s := `SELECT value FROM cpu;`
    28  	q, err := influxql.NewParser(strings.NewReader(s)).ParseQuery()
    29  	if err != nil {
    30  		t.Fatalf("unexpected error: %s", err)
    31  	} else if len(q.Statements) != 1 {
    32  		t.Fatalf("unexpected statement count: %d", len(q.Statements))
    33  	}
    34  }
    35  
    36  // Ensure the parser can parse an empty query.
    37  func TestParser_ParseQuery_Empty(t *testing.T) {
    38  	q, err := influxql.NewParser(strings.NewReader(``)).ParseQuery()
    39  	if err != nil {
    40  		t.Fatalf("unexpected error: %s", err)
    41  	} else if len(q.Statements) != 0 {
    42  		t.Fatalf("unexpected statement count: %d", len(q.Statements))
    43  	}
    44  }
    45  
    46  // Ensure the parser will skip comments.
    47  func TestParser_ParseQuery_SkipComments(t *testing.T) {
    48  	q, err := influxql.ParseQuery(`SELECT * FROM cpu; -- read from cpu database
    49  
    50  /* create continuous query */
    51  CREATE CONTINUOUS QUERY cq0 ON db0 BEGIN
    52  	SELECT mean(*) INTO db1..:MEASUREMENT FROM cpu GROUP BY time(5m)
    53  END;
    54  
    55  /* just a multline comment
    56  what is this doing here?
    57  **/
    58  
    59  -- should ignore the trailing multiline comment /*
    60  SELECT mean(value) FROM gpu;
    61  -- trailing comment at the end`)
    62  	if err != nil {
    63  		t.Fatalf("unexpected error: %s", err)
    64  	} else if len(q.Statements) != 3 {
    65  		t.Fatalf("unexpected statement count: %d", len(q.Statements))
    66  	}
    67  }
    68  
    69  // Ensure the parser can return an error from an malformed statement.
    70  func TestParser_ParseQuery_ParseError(t *testing.T) {
    71  	_, err := influxql.NewParser(strings.NewReader(`SELECT`)).ParseQuery()
    72  	if err == nil || err.Error() != `found EOF, expected identifier, string, number, bool at line 1, char 8` {
    73  		t.Fatalf("unexpected error: %s", err)
    74  	}
    75  }
    76  
    77  func TestParser_ParseQuery_NoSemicolon(t *testing.T) {
    78  	_, err := influxql.NewParser(strings.NewReader(`CREATE DATABASE foo CREATE DATABASE bar`)).ParseQuery()
    79  	if err == nil || err.Error() != `found CREATE, expected ; at line 1, char 21` {
    80  		t.Fatalf("unexpected error: %s", err)
    81  	}
    82  }
    83  
    84  // Ensure the parser can parse strings into Statement ASTs.
    85  func TestParser_ParseStatement(t *testing.T) {
    86  	// For use in various tests.
    87  	now := time.Now()
    88  
    89  	var tests = []struct {
    90  		skip   bool
    91  		s      string
    92  		params map[string]interface{}
    93  		stmt   influxql.Statement
    94  		err    string
    95  	}{
    96  		// SELECT * statement
    97  		{
    98  			s: `SELECT * FROM myseries`,
    99  			stmt: &influxql.SelectStatement{
   100  				IsRawQuery: true,
   101  				Fields: []*influxql.Field{
   102  					{Expr: &influxql.Wildcard{}},
   103  				},
   104  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   105  			},
   106  		},
   107  		{
   108  			s: `SELECT * FROM myseries GROUP BY *`,
   109  			stmt: &influxql.SelectStatement{
   110  				IsRawQuery: true,
   111  				Fields: []*influxql.Field{
   112  					{Expr: &influxql.Wildcard{}},
   113  				},
   114  				Sources:    []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   115  				Dimensions: []*influxql.Dimension{{Expr: &influxql.Wildcard{}}},
   116  			},
   117  		},
   118  		{
   119  			s: `SELECT field1, * FROM myseries GROUP BY *`,
   120  			stmt: &influxql.SelectStatement{
   121  				IsRawQuery: true,
   122  				Fields: []*influxql.Field{
   123  					{Expr: &influxql.VarRef{Val: "field1"}},
   124  					{Expr: &influxql.Wildcard{}},
   125  				},
   126  				Sources:    []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   127  				Dimensions: []*influxql.Dimension{{Expr: &influxql.Wildcard{}}},
   128  			},
   129  		},
   130  		{
   131  			s: `SELECT *, field1 FROM myseries GROUP BY *`,
   132  			stmt: &influxql.SelectStatement{
   133  				IsRawQuery: true,
   134  				Fields: []*influxql.Field{
   135  					{Expr: &influxql.Wildcard{}},
   136  					{Expr: &influxql.VarRef{Val: "field1"}},
   137  				},
   138  				Sources:    []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   139  				Dimensions: []*influxql.Dimension{{Expr: &influxql.Wildcard{}}},
   140  			},
   141  		},
   142  
   143  		// SELECT statement
   144  		{
   145  			s: fmt.Sprintf(`SELECT mean(field1), sum(field2), count(field3) AS field_x FROM myseries WHERE host = 'hosta.influxdb.org' and time > '%s' GROUP BY time(10h) ORDER BY DESC LIMIT 20 OFFSET 10;`, now.UTC().Format(time.RFC3339Nano)),
   146  			stmt: &influxql.SelectStatement{
   147  				IsRawQuery: false,
   148  				Fields: []*influxql.Field{
   149  					{Expr: &influxql.Call{Name: "mean", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}}}},
   150  					{Expr: &influxql.Call{Name: "sum", Args: []influxql.Expr{&influxql.VarRef{Val: "field2"}}}},
   151  					{Expr: &influxql.Call{Name: "count", Args: []influxql.Expr{&influxql.VarRef{Val: "field3"}}}, Alias: "field_x"},
   152  				},
   153  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   154  				Condition: &influxql.BinaryExpr{
   155  					Op: influxql.AND,
   156  					LHS: &influxql.BinaryExpr{
   157  						Op:  influxql.EQ,
   158  						LHS: &influxql.VarRef{Val: "host"},
   159  						RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
   160  					},
   161  					RHS: &influxql.BinaryExpr{
   162  						Op:  influxql.GT,
   163  						LHS: &influxql.VarRef{Val: "time"},
   164  						RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   165  					},
   166  				},
   167  				Dimensions: []*influxql.Dimension{{Expr: &influxql.Call{Name: "time", Args: []influxql.Expr{&influxql.DurationLiteral{Val: 10 * time.Hour}}}}},
   168  				SortFields: []*influxql.SortField{
   169  					{Ascending: false},
   170  				},
   171  				Limit:  20,
   172  				Offset: 10,
   173  			},
   174  		},
   175  		{
   176  			s: `SELECT "foo.bar.baz" AS foo FROM myseries`,
   177  			stmt: &influxql.SelectStatement{
   178  				IsRawQuery: true,
   179  				Fields: []*influxql.Field{
   180  					{Expr: &influxql.VarRef{Val: "foo.bar.baz"}, Alias: "foo"},
   181  				},
   182  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   183  			},
   184  		},
   185  		{
   186  			s: `SELECT "foo.bar.baz" AS foo FROM foo`,
   187  			stmt: &influxql.SelectStatement{
   188  				IsRawQuery: true,
   189  				Fields: []*influxql.Field{
   190  					{Expr: &influxql.VarRef{Val: "foo.bar.baz"}, Alias: "foo"},
   191  				},
   192  				Sources: []influxql.Source{&influxql.Measurement{Name: "foo"}},
   193  			},
   194  		},
   195  
   196  		// sample
   197  		{
   198  			s: `SELECT sample(field1, 100) FROM myseries;`,
   199  			stmt: &influxql.SelectStatement{
   200  				IsRawQuery: false,
   201  				Fields: []*influxql.Field{
   202  					{Expr: &influxql.Call{Name: "sample", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.IntegerLiteral{Val: 100}}}},
   203  				},
   204  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   205  			},
   206  		},
   207  
   208  		// derivative
   209  		{
   210  			s: `SELECT derivative(field1, 1h) FROM myseries;`,
   211  			stmt: &influxql.SelectStatement{
   212  				IsRawQuery: false,
   213  				Fields: []*influxql.Field{
   214  					{Expr: &influxql.Call{Name: "derivative", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.DurationLiteral{Val: time.Hour}}}},
   215  				},
   216  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   217  			},
   218  		},
   219  
   220  		{
   221  			s: fmt.Sprintf(`SELECT derivative(field1, 1h) FROM myseries WHERE time > '%s'`, now.UTC().Format(time.RFC3339Nano)),
   222  			stmt: &influxql.SelectStatement{
   223  				IsRawQuery: false,
   224  				Fields: []*influxql.Field{
   225  					{Expr: &influxql.Call{Name: "derivative", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.DurationLiteral{Val: time.Hour}}}},
   226  				},
   227  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   228  				Condition: &influxql.BinaryExpr{
   229  					Op:  influxql.GT,
   230  					LHS: &influxql.VarRef{Val: "time"},
   231  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   232  				},
   233  			},
   234  		},
   235  
   236  		{
   237  			s: `SELECT derivative(field1, 1h) / derivative(field2, 1h) FROM myseries`,
   238  			stmt: &influxql.SelectStatement{
   239  				IsRawQuery: false,
   240  				Fields: []*influxql.Field{
   241  					{
   242  						Expr: &influxql.BinaryExpr{
   243  							LHS: &influxql.Call{
   244  								Name: "derivative",
   245  								Args: []influxql.Expr{
   246  									&influxql.VarRef{Val: "field1"},
   247  									&influxql.DurationLiteral{Val: time.Hour},
   248  								},
   249  							},
   250  							RHS: &influxql.Call{
   251  								Name: "derivative",
   252  								Args: []influxql.Expr{
   253  									&influxql.VarRef{Val: "field2"},
   254  									&influxql.DurationLiteral{Val: time.Hour},
   255  								},
   256  							},
   257  							Op: influxql.DIV,
   258  						},
   259  					},
   260  				},
   261  				Sources: []influxql.Source{
   262  					&influxql.Measurement{Name: "myseries"},
   263  				},
   264  			},
   265  		},
   266  
   267  		// difference
   268  		{
   269  			s: `SELECT difference(field1) FROM myseries;`,
   270  			stmt: &influxql.SelectStatement{
   271  				IsRawQuery: false,
   272  				Fields: []*influxql.Field{
   273  					{Expr: &influxql.Call{Name: "difference", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}}}},
   274  				},
   275  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   276  			},
   277  		},
   278  
   279  		{
   280  			s: fmt.Sprintf(`SELECT difference(max(field1)) FROM myseries WHERE time > '%s' GROUP BY time(1m)`, now.UTC().Format(time.RFC3339Nano)),
   281  			stmt: &influxql.SelectStatement{
   282  				IsRawQuery: false,
   283  				Fields: []*influxql.Field{
   284  					{
   285  						Expr: &influxql.Call{
   286  							Name: "difference",
   287  							Args: []influxql.Expr{
   288  								&influxql.Call{
   289  									Name: "max",
   290  									Args: []influxql.Expr{
   291  										&influxql.VarRef{Val: "field1"},
   292  									},
   293  								},
   294  							},
   295  						},
   296  					},
   297  				},
   298  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   299  				Dimensions: []*influxql.Dimension{
   300  					{
   301  						Expr: &influxql.Call{
   302  							Name: "time",
   303  							Args: []influxql.Expr{
   304  								&influxql.DurationLiteral{Val: time.Minute},
   305  							},
   306  						},
   307  					},
   308  				},
   309  				Condition: &influxql.BinaryExpr{
   310  					Op:  influxql.GT,
   311  					LHS: &influxql.VarRef{Val: "time"},
   312  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   313  				},
   314  			},
   315  		},
   316  
   317  		// non_negative_difference
   318  		{
   319  			s: `SELECT non_negative_difference(field1) FROM myseries;`,
   320  			stmt: &influxql.SelectStatement{
   321  				IsRawQuery: false,
   322  				Fields: []*influxql.Field{
   323  					{Expr: &influxql.Call{Name: "non_negative_difference", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}}}},
   324  				},
   325  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   326  			},
   327  		},
   328  
   329  		{
   330  			s: fmt.Sprintf(`SELECT non_negative_difference(max(field1)) FROM myseries WHERE time > '%s' GROUP BY time(1m)`, now.UTC().Format(time.RFC3339Nano)),
   331  			stmt: &influxql.SelectStatement{
   332  				IsRawQuery: false,
   333  				Fields: []*influxql.Field{
   334  					{
   335  						Expr: &influxql.Call{
   336  							Name: "non_negative_difference",
   337  							Args: []influxql.Expr{
   338  								&influxql.Call{
   339  									Name: "max",
   340  									Args: []influxql.Expr{
   341  										&influxql.VarRef{Val: "field1"},
   342  									},
   343  								},
   344  							},
   345  						},
   346  					},
   347  				},
   348  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   349  				Dimensions: []*influxql.Dimension{
   350  					{
   351  						Expr: &influxql.Call{
   352  							Name: "time",
   353  							Args: []influxql.Expr{
   354  								&influxql.DurationLiteral{Val: time.Minute},
   355  							},
   356  						},
   357  					},
   358  				},
   359  				Condition: &influxql.BinaryExpr{
   360  					Op:  influxql.GT,
   361  					LHS: &influxql.VarRef{Val: "time"},
   362  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   363  				},
   364  			},
   365  		},
   366  
   367  		// moving_average
   368  		{
   369  			s: `SELECT moving_average(field1, 3) FROM myseries;`,
   370  			stmt: &influxql.SelectStatement{
   371  				IsRawQuery: false,
   372  				Fields: []*influxql.Field{
   373  					{Expr: &influxql.Call{Name: "moving_average", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.IntegerLiteral{Val: 3}}}},
   374  				},
   375  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   376  			},
   377  		},
   378  
   379  		{
   380  			s: fmt.Sprintf(`SELECT moving_average(max(field1), 3) FROM myseries WHERE time > '%s' GROUP BY time(1m)`, now.UTC().Format(time.RFC3339Nano)),
   381  			stmt: &influxql.SelectStatement{
   382  				IsRawQuery: false,
   383  				Fields: []*influxql.Field{
   384  					{
   385  						Expr: &influxql.Call{
   386  							Name: "moving_average",
   387  							Args: []influxql.Expr{
   388  								&influxql.Call{
   389  									Name: "max",
   390  									Args: []influxql.Expr{
   391  										&influxql.VarRef{Val: "field1"},
   392  									},
   393  								},
   394  								&influxql.IntegerLiteral{Val: 3},
   395  							},
   396  						},
   397  					},
   398  				},
   399  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   400  				Dimensions: []*influxql.Dimension{
   401  					{
   402  						Expr: &influxql.Call{
   403  							Name: "time",
   404  							Args: []influxql.Expr{
   405  								&influxql.DurationLiteral{Val: time.Minute},
   406  							},
   407  						},
   408  					},
   409  				},
   410  				Condition: &influxql.BinaryExpr{
   411  					Op:  influxql.GT,
   412  					LHS: &influxql.VarRef{Val: "time"},
   413  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   414  				},
   415  			},
   416  		},
   417  
   418  		// cumulative_sum
   419  		{
   420  			s: fmt.Sprintf(`SELECT cumulative_sum(field1) FROM myseries WHERE time > '%s'`, now.UTC().Format(time.RFC3339Nano)),
   421  			stmt: &influxql.SelectStatement{
   422  				Fields: []*influxql.Field{
   423  					{
   424  						Expr: &influxql.Call{
   425  							Name: "cumulative_sum",
   426  							Args: []influxql.Expr{
   427  								&influxql.VarRef{Val: "field1"},
   428  							},
   429  						},
   430  					},
   431  				},
   432  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   433  				Condition: &influxql.BinaryExpr{
   434  					Op:  influxql.GT,
   435  					LHS: &influxql.VarRef{Val: "time"},
   436  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   437  				},
   438  			},
   439  		},
   440  
   441  		{
   442  			s: fmt.Sprintf(`SELECT cumulative_sum(mean(field1)) FROM myseries WHERE time > '%s' GROUP BY time(1m)`, now.UTC().Format(time.RFC3339Nano)),
   443  			stmt: &influxql.SelectStatement{
   444  				Fields: []*influxql.Field{
   445  					{
   446  						Expr: &influxql.Call{
   447  							Name: "cumulative_sum",
   448  							Args: []influxql.Expr{
   449  								&influxql.Call{
   450  									Name: "mean",
   451  									Args: []influxql.Expr{
   452  										&influxql.VarRef{Val: "field1"},
   453  									},
   454  								},
   455  							},
   456  						},
   457  					},
   458  				},
   459  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   460  				Dimensions: []*influxql.Dimension{
   461  					{
   462  						Expr: &influxql.Call{
   463  							Name: "time",
   464  							Args: []influxql.Expr{
   465  								&influxql.DurationLiteral{Val: time.Minute},
   466  							},
   467  						},
   468  					},
   469  				},
   470  				Condition: &influxql.BinaryExpr{
   471  					Op:  influxql.GT,
   472  					LHS: &influxql.VarRef{Val: "time"},
   473  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   474  				},
   475  			},
   476  		},
   477  
   478  		// holt_winters
   479  		{
   480  			s: fmt.Sprintf(`SELECT holt_winters(first(field1), 3, 1) FROM myseries WHERE time > '%s' GROUP BY time(1h);`, now.UTC().Format(time.RFC3339Nano)),
   481  			stmt: &influxql.SelectStatement{
   482  				IsRawQuery: false,
   483  				Fields: []*influxql.Field{
   484  					{Expr: &influxql.Call{
   485  						Name: "holt_winters",
   486  						Args: []influxql.Expr{
   487  							&influxql.Call{
   488  								Name: "first",
   489  								Args: []influxql.Expr{
   490  									&influxql.VarRef{Val: "field1"},
   491  								},
   492  							},
   493  							&influxql.IntegerLiteral{Val: 3},
   494  							&influxql.IntegerLiteral{Val: 1},
   495  						},
   496  					}},
   497  				},
   498  				Dimensions: []*influxql.Dimension{
   499  					{
   500  						Expr: &influxql.Call{
   501  							Name: "time",
   502  							Args: []influxql.Expr{
   503  								&influxql.DurationLiteral{Val: 1 * time.Hour},
   504  							},
   505  						},
   506  					},
   507  				},
   508  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   509  				Condition: &influxql.BinaryExpr{
   510  					Op:  influxql.GT,
   511  					LHS: &influxql.VarRef{Val: "time"},
   512  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   513  				},
   514  			},
   515  		},
   516  
   517  		{
   518  			s: fmt.Sprintf(`SELECT holt_winters_with_fit(first(field1), 3, 1) FROM myseries WHERE time > '%s' GROUP BY time(1h);`, now.UTC().Format(time.RFC3339Nano)),
   519  			stmt: &influxql.SelectStatement{
   520  				IsRawQuery: false,
   521  				Fields: []*influxql.Field{
   522  					{Expr: &influxql.Call{
   523  						Name: "holt_winters_with_fit",
   524  						Args: []influxql.Expr{
   525  							&influxql.Call{
   526  								Name: "first",
   527  								Args: []influxql.Expr{
   528  									&influxql.VarRef{Val: "field1"},
   529  								},
   530  							},
   531  							&influxql.IntegerLiteral{Val: 3},
   532  							&influxql.IntegerLiteral{Val: 1},
   533  						}}},
   534  				},
   535  				Dimensions: []*influxql.Dimension{
   536  					{
   537  						Expr: &influxql.Call{
   538  							Name: "time",
   539  							Args: []influxql.Expr{
   540  								&influxql.DurationLiteral{Val: 1 * time.Hour},
   541  							},
   542  						},
   543  					},
   544  				},
   545  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   546  				Condition: &influxql.BinaryExpr{
   547  					Op:  influxql.GT,
   548  					LHS: &influxql.VarRef{Val: "time"},
   549  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   550  				},
   551  			},
   552  		},
   553  		{
   554  			s: fmt.Sprintf(`SELECT holt_winters(max(field1), 4, 5) FROM myseries WHERE time > '%s' GROUP BY time(1m)`, now.UTC().Format(time.RFC3339Nano)),
   555  			stmt: &influxql.SelectStatement{
   556  				IsRawQuery: false,
   557  				Fields: []*influxql.Field{
   558  					{
   559  						Expr: &influxql.Call{
   560  							Name: "holt_winters",
   561  							Args: []influxql.Expr{
   562  								&influxql.Call{
   563  									Name: "max",
   564  									Args: []influxql.Expr{
   565  										&influxql.VarRef{Val: "field1"},
   566  									},
   567  								},
   568  								&influxql.IntegerLiteral{Val: 4},
   569  								&influxql.IntegerLiteral{Val: 5},
   570  							},
   571  						},
   572  					},
   573  				},
   574  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   575  				Dimensions: []*influxql.Dimension{
   576  					{
   577  						Expr: &influxql.Call{
   578  							Name: "time",
   579  							Args: []influxql.Expr{
   580  								&influxql.DurationLiteral{Val: time.Minute},
   581  							},
   582  						},
   583  					},
   584  				},
   585  				Condition: &influxql.BinaryExpr{
   586  					Op:  influxql.GT,
   587  					LHS: &influxql.VarRef{Val: "time"},
   588  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   589  				},
   590  			},
   591  		},
   592  
   593  		{
   594  			s: fmt.Sprintf(`SELECT holt_winters_with_fit(max(field1), 4, 5) FROM myseries WHERE time > '%s' GROUP BY time(1m)`, now.UTC().Format(time.RFC3339Nano)),
   595  			stmt: &influxql.SelectStatement{
   596  				IsRawQuery: false,
   597  				Fields: []*influxql.Field{
   598  					{
   599  						Expr: &influxql.Call{
   600  							Name: "holt_winters_with_fit",
   601  							Args: []influxql.Expr{
   602  								&influxql.Call{
   603  									Name: "max",
   604  									Args: []influxql.Expr{
   605  										&influxql.VarRef{Val: "field1"},
   606  									},
   607  								},
   608  								&influxql.IntegerLiteral{Val: 4},
   609  								&influxql.IntegerLiteral{Val: 5},
   610  							},
   611  						},
   612  					},
   613  				},
   614  				Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   615  				Dimensions: []*influxql.Dimension{
   616  					{
   617  						Expr: &influxql.Call{
   618  							Name: "time",
   619  							Args: []influxql.Expr{
   620  								&influxql.DurationLiteral{Val: time.Minute},
   621  							},
   622  						},
   623  					},
   624  				},
   625  				Condition: &influxql.BinaryExpr{
   626  					Op:  influxql.GT,
   627  					LHS: &influxql.VarRef{Val: "time"},
   628  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   629  				},
   630  			},
   631  		},
   632  
   633  		// SELECT statement (lowercase)
   634  		{
   635  			s: `select my_field from myseries`,
   636  			stmt: &influxql.SelectStatement{
   637  				IsRawQuery: true,
   638  				Fields:     []*influxql.Field{{Expr: &influxql.VarRef{Val: "my_field"}}},
   639  				Sources:    []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   640  			},
   641  		},
   642  
   643  		// SELECT statement (lowercase) with quoted field
   644  		{
   645  			s: `select 'my_field' from myseries`,
   646  			stmt: &influxql.SelectStatement{
   647  				IsRawQuery: true,
   648  				Fields:     []*influxql.Field{{Expr: &influxql.StringLiteral{Val: "my_field"}}},
   649  				Sources:    []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   650  			},
   651  		},
   652  
   653  		// SELECT statement with multiple ORDER BY fields
   654  		{
   655  			skip: true,
   656  			s:    `SELECT field1 FROM myseries ORDER BY ASC, field1, field2 DESC LIMIT 10`,
   657  			stmt: &influxql.SelectStatement{
   658  				IsRawQuery: true,
   659  				Fields:     []*influxql.Field{{Expr: &influxql.VarRef{Val: "field1"}}},
   660  				Sources:    []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   661  				SortFields: []*influxql.SortField{
   662  					{Ascending: true},
   663  					{Name: "field1"},
   664  					{Name: "field2"},
   665  				},
   666  				Limit: 10,
   667  			},
   668  		},
   669  
   670  		// SELECT statement with SLIMIT and SOFFSET
   671  		{
   672  			s: `SELECT field1 FROM myseries SLIMIT 10 SOFFSET 5`,
   673  			stmt: &influxql.SelectStatement{
   674  				IsRawQuery: true,
   675  				Fields:     []*influxql.Field{{Expr: &influxql.VarRef{Val: "field1"}}},
   676  				Sources:    []influxql.Source{&influxql.Measurement{Name: "myseries"}},
   677  				SLimit:     10,
   678  				SOffset:    5,
   679  			},
   680  		},
   681  
   682  		// SELECT * FROM cpu WHERE host = 'serverC' AND region =~ /.*west.*/
   683  		{
   684  			s: `SELECT * FROM cpu WHERE host = 'serverC' AND region =~ /.*west.*/`,
   685  			stmt: &influxql.SelectStatement{
   686  				IsRawQuery: true,
   687  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   688  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   689  				Condition: &influxql.BinaryExpr{
   690  					Op: influxql.AND,
   691  					LHS: &influxql.BinaryExpr{
   692  						Op:  influxql.EQ,
   693  						LHS: &influxql.VarRef{Val: "host"},
   694  						RHS: &influxql.StringLiteral{Val: "serverC"},
   695  					},
   696  					RHS: &influxql.BinaryExpr{
   697  						Op:  influxql.EQREGEX,
   698  						LHS: &influxql.VarRef{Val: "region"},
   699  						RHS: &influxql.RegexLiteral{Val: regexp.MustCompile(".*west.*")},
   700  					},
   701  				},
   702  			},
   703  		},
   704  
   705  		// select percentile statements
   706  		{
   707  			s: `select percentile("field1", 2.0) from cpu`,
   708  			stmt: &influxql.SelectStatement{
   709  				IsRawQuery: false,
   710  				Fields: []*influxql.Field{
   711  					{Expr: &influxql.Call{Name: "percentile", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2.0}}}},
   712  				},
   713  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   714  			},
   715  		},
   716  
   717  		{
   718  			s: `select percentile("field1", 2.0), field2 from cpu`,
   719  			stmt: &influxql.SelectStatement{
   720  				IsRawQuery: false,
   721  				Fields: []*influxql.Field{
   722  					{Expr: &influxql.Call{Name: "percentile", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.NumberLiteral{Val: 2.0}}}},
   723  					{Expr: &influxql.VarRef{Val: "field2"}},
   724  				},
   725  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   726  			},
   727  		},
   728  
   729  		// select top statements
   730  		{
   731  			s: `select top("field1", 2) from cpu`,
   732  			stmt: &influxql.SelectStatement{
   733  				IsRawQuery: false,
   734  				Fields: []*influxql.Field{
   735  					{Expr: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.IntegerLiteral{Val: 2}}}},
   736  				},
   737  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   738  			},
   739  		},
   740  
   741  		{
   742  			s: `select top(field1, 2) from cpu`,
   743  			stmt: &influxql.SelectStatement{
   744  				IsRawQuery: false,
   745  				Fields: []*influxql.Field{
   746  					{Expr: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.IntegerLiteral{Val: 2}}}},
   747  				},
   748  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   749  			},
   750  		},
   751  
   752  		{
   753  			s: `select top(field1, 2), tag1 from cpu`,
   754  			stmt: &influxql.SelectStatement{
   755  				IsRawQuery: false,
   756  				Fields: []*influxql.Field{
   757  					{Expr: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.IntegerLiteral{Val: 2}}}},
   758  					{Expr: &influxql.VarRef{Val: "tag1"}},
   759  				},
   760  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   761  			},
   762  		},
   763  
   764  		{
   765  			s: `select top(field1, tag1, 2), tag1 from cpu`,
   766  			stmt: &influxql.SelectStatement{
   767  				IsRawQuery: false,
   768  				Fields: []*influxql.Field{
   769  					{Expr: &influxql.Call{Name: "top", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.VarRef{Val: "tag1"}, &influxql.IntegerLiteral{Val: 2}}}},
   770  					{Expr: &influxql.VarRef{Val: "tag1"}},
   771  				},
   772  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   773  			},
   774  		},
   775  
   776  		// select distinct statements
   777  		{
   778  			s: `select distinct(field1) from cpu`,
   779  			stmt: &influxql.SelectStatement{
   780  				IsRawQuery: false,
   781  				Fields: []*influxql.Field{
   782  					{Expr: &influxql.Call{Name: "distinct", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}}}},
   783  				},
   784  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   785  			},
   786  		},
   787  
   788  		{
   789  			s: `select distinct field2 from network`,
   790  			stmt: &influxql.SelectStatement{
   791  				IsRawQuery: true,
   792  				Fields: []*influxql.Field{
   793  					{Expr: &influxql.Distinct{Val: "field2"}},
   794  				},
   795  				Sources: []influxql.Source{&influxql.Measurement{Name: "network"}},
   796  			},
   797  		},
   798  
   799  		{
   800  			s: `select count(distinct field3) from metrics`,
   801  			stmt: &influxql.SelectStatement{
   802  				IsRawQuery: false,
   803  				Fields: []*influxql.Field{
   804  					{Expr: &influxql.Call{Name: "count", Args: []influxql.Expr{&influxql.Distinct{Val: "field3"}}}},
   805  				},
   806  				Sources: []influxql.Source{&influxql.Measurement{Name: "metrics"}},
   807  			},
   808  		},
   809  
   810  		{
   811  			s: `select count(distinct field3), sum(field4) from metrics`,
   812  			stmt: &influxql.SelectStatement{
   813  				IsRawQuery: false,
   814  				Fields: []*influxql.Field{
   815  					{Expr: &influxql.Call{Name: "count", Args: []influxql.Expr{&influxql.Distinct{Val: "field3"}}}},
   816  					{Expr: &influxql.Call{Name: "sum", Args: []influxql.Expr{&influxql.VarRef{Val: "field4"}}}},
   817  				},
   818  				Sources: []influxql.Source{&influxql.Measurement{Name: "metrics"}},
   819  			},
   820  		},
   821  
   822  		{
   823  			s: `select count(distinct(field3)), sum(field4) from metrics`,
   824  			stmt: &influxql.SelectStatement{
   825  				IsRawQuery: false,
   826  				Fields: []*influxql.Field{
   827  					{Expr: &influxql.Call{Name: "count", Args: []influxql.Expr{&influxql.Call{Name: "distinct", Args: []influxql.Expr{&influxql.VarRef{Val: "field3"}}}}}},
   828  					{Expr: &influxql.Call{Name: "sum", Args: []influxql.Expr{&influxql.VarRef{Val: "field4"}}}},
   829  				},
   830  				Sources: []influxql.Source{&influxql.Measurement{Name: "metrics"}},
   831  			},
   832  		},
   833  
   834  		// SELECT * FROM WHERE time
   835  		{
   836  			s: fmt.Sprintf(`SELECT * FROM cpu WHERE time > '%s'`, now.UTC().Format(time.RFC3339Nano)),
   837  			stmt: &influxql.SelectStatement{
   838  				IsRawQuery: true,
   839  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   840  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   841  				Condition: &influxql.BinaryExpr{
   842  					Op:  influxql.GT,
   843  					LHS: &influxql.VarRef{Val: "time"},
   844  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
   845  				},
   846  			},
   847  		},
   848  
   849  		// SELECT * FROM WHERE field comparisons
   850  		{
   851  			s: `SELECT * FROM cpu WHERE load > 100`,
   852  			stmt: &influxql.SelectStatement{
   853  				IsRawQuery: true,
   854  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   855  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   856  				Condition: &influxql.BinaryExpr{
   857  					Op:  influxql.GT,
   858  					LHS: &influxql.VarRef{Val: "load"},
   859  					RHS: &influxql.IntegerLiteral{Val: 100},
   860  				},
   861  			},
   862  		},
   863  		{
   864  			s: `SELECT * FROM cpu WHERE load >= 100`,
   865  			stmt: &influxql.SelectStatement{
   866  				IsRawQuery: true,
   867  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   868  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   869  				Condition: &influxql.BinaryExpr{
   870  					Op:  influxql.GTE,
   871  					LHS: &influxql.VarRef{Val: "load"},
   872  					RHS: &influxql.IntegerLiteral{Val: 100},
   873  				},
   874  			},
   875  		},
   876  		{
   877  			s: `SELECT * FROM cpu WHERE load = 100`,
   878  			stmt: &influxql.SelectStatement{
   879  				IsRawQuery: true,
   880  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   881  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   882  				Condition: &influxql.BinaryExpr{
   883  					Op:  influxql.EQ,
   884  					LHS: &influxql.VarRef{Val: "load"},
   885  					RHS: &influxql.IntegerLiteral{Val: 100},
   886  				},
   887  			},
   888  		},
   889  		{
   890  			s: `SELECT * FROM cpu WHERE load <= 100`,
   891  			stmt: &influxql.SelectStatement{
   892  				IsRawQuery: true,
   893  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   894  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   895  				Condition: &influxql.BinaryExpr{
   896  					Op:  influxql.LTE,
   897  					LHS: &influxql.VarRef{Val: "load"},
   898  					RHS: &influxql.IntegerLiteral{Val: 100},
   899  				},
   900  			},
   901  		},
   902  		{
   903  			s: `SELECT * FROM cpu WHERE load < 100`,
   904  			stmt: &influxql.SelectStatement{
   905  				IsRawQuery: true,
   906  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   907  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   908  				Condition: &influxql.BinaryExpr{
   909  					Op:  influxql.LT,
   910  					LHS: &influxql.VarRef{Val: "load"},
   911  					RHS: &influxql.IntegerLiteral{Val: 100},
   912  				},
   913  			},
   914  		},
   915  		{
   916  			s: `SELECT * FROM cpu WHERE load != 100`,
   917  			stmt: &influxql.SelectStatement{
   918  				IsRawQuery: true,
   919  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   920  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
   921  				Condition: &influxql.BinaryExpr{
   922  					Op:  influxql.NEQ,
   923  					LHS: &influxql.VarRef{Val: "load"},
   924  					RHS: &influxql.IntegerLiteral{Val: 100},
   925  				},
   926  			},
   927  		},
   928  
   929  		// SELECT * FROM /<regex>/
   930  		{
   931  			s: `SELECT * FROM /cpu.*/`,
   932  			stmt: &influxql.SelectStatement{
   933  				IsRawQuery: true,
   934  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   935  				Sources: []influxql.Source{&influxql.Measurement{
   936  					Regex: &influxql.RegexLiteral{Val: regexp.MustCompile("cpu.*")}},
   937  				},
   938  			},
   939  		},
   940  
   941  		// SELECT * FROM "db"."rp"./<regex>/
   942  		{
   943  			s: `SELECT * FROM "db"."rp"./cpu.*/`,
   944  			stmt: &influxql.SelectStatement{
   945  				IsRawQuery: true,
   946  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   947  				Sources: []influxql.Source{&influxql.Measurement{
   948  					Database:        `db`,
   949  					RetentionPolicy: `rp`,
   950  					Regex:           &influxql.RegexLiteral{Val: regexp.MustCompile("cpu.*")}},
   951  				},
   952  			},
   953  		},
   954  
   955  		// SELECT * FROM "db"../<regex>/
   956  		{
   957  			s: `SELECT * FROM "db"../cpu.*/`,
   958  			stmt: &influxql.SelectStatement{
   959  				IsRawQuery: true,
   960  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   961  				Sources: []influxql.Source{&influxql.Measurement{
   962  					Database: `db`,
   963  					Regex:    &influxql.RegexLiteral{Val: regexp.MustCompile("cpu.*")}},
   964  				},
   965  			},
   966  		},
   967  
   968  		// SELECT * FROM "rp"./<regex>/
   969  		{
   970  			s: `SELECT * FROM "rp"./cpu.*/`,
   971  			stmt: &influxql.SelectStatement{
   972  				IsRawQuery: true,
   973  				Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
   974  				Sources: []influxql.Source{&influxql.Measurement{
   975  					RetentionPolicy: `rp`,
   976  					Regex:           &influxql.RegexLiteral{Val: regexp.MustCompile("cpu.*")}},
   977  				},
   978  			},
   979  		},
   980  
   981  		// SELECT statement with group by
   982  		{
   983  			s: `SELECT sum(value) FROM "kbps" WHERE time > now() - 120s AND deliveryservice='steam-dns' and cachegroup = 'total' GROUP BY time(60s)`,
   984  			stmt: &influxql.SelectStatement{
   985  				IsRawQuery: false,
   986  				Fields: []*influxql.Field{
   987  					{Expr: &influxql.Call{Name: "sum", Args: []influxql.Expr{&influxql.VarRef{Val: "value"}}}},
   988  				},
   989  				Sources:    []influxql.Source{&influxql.Measurement{Name: "kbps"}},
   990  				Dimensions: []*influxql.Dimension{{Expr: &influxql.Call{Name: "time", Args: []influxql.Expr{&influxql.DurationLiteral{Val: 60 * time.Second}}}}},
   991  				Condition: &influxql.BinaryExpr{ // 1
   992  					Op: influxql.AND,
   993  					LHS: &influxql.BinaryExpr{ // 2
   994  						Op: influxql.AND,
   995  						LHS: &influxql.BinaryExpr{ //3
   996  							Op:  influxql.GT,
   997  							LHS: &influxql.VarRef{Val: "time"},
   998  							RHS: &influxql.BinaryExpr{
   999  								Op:  influxql.SUB,
  1000  								LHS: &influxql.Call{Name: "now"},
  1001  								RHS: &influxql.DurationLiteral{Val: mustParseDuration("120s")},
  1002  							},
  1003  						},
  1004  						RHS: &influxql.BinaryExpr{
  1005  							Op:  influxql.EQ,
  1006  							LHS: &influxql.VarRef{Val: "deliveryservice"},
  1007  							RHS: &influxql.StringLiteral{Val: "steam-dns"},
  1008  						},
  1009  					},
  1010  					RHS: &influxql.BinaryExpr{
  1011  						Op:  influxql.EQ,
  1012  						LHS: &influxql.VarRef{Val: "cachegroup"},
  1013  						RHS: &influxql.StringLiteral{Val: "total"},
  1014  					},
  1015  				},
  1016  			},
  1017  		},
  1018  		// SELECT statement with group by and multi digit duration (prevent regression from #731://github.com/influxdata/influxdb/pull/7316)
  1019  		{
  1020  			s: fmt.Sprintf(`SELECT count(value) FROM cpu where time < '%s' group by time(500ms)`, now.UTC().Format(time.RFC3339Nano)),
  1021  			stmt: &influxql.SelectStatement{
  1022  				Fields: []*influxql.Field{{
  1023  					Expr: &influxql.Call{
  1024  						Name: "count",
  1025  						Args: []influxql.Expr{&influxql.VarRef{Val: "value"}}}}},
  1026  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1027  				Condition: &influxql.BinaryExpr{
  1028  					Op:  influxql.LT,
  1029  					LHS: &influxql.VarRef{Val: "time"},
  1030  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
  1031  				},
  1032  				Dimensions: []*influxql.Dimension{{Expr: &influxql.Call{Name: "time", Args: []influxql.Expr{&influxql.DurationLiteral{Val: 500 * time.Millisecond}}}}},
  1033  			},
  1034  		},
  1035  
  1036  		// SELECT statement with fill
  1037  		{
  1038  			s: fmt.Sprintf(`SELECT mean(value) FROM cpu where time < '%s' GROUP BY time(5m) fill(1)`, now.UTC().Format(time.RFC3339Nano)),
  1039  			stmt: &influxql.SelectStatement{
  1040  				Fields: []*influxql.Field{{
  1041  					Expr: &influxql.Call{
  1042  						Name: "mean",
  1043  						Args: []influxql.Expr{&influxql.VarRef{Val: "value"}}}}},
  1044  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1045  				Condition: &influxql.BinaryExpr{
  1046  					Op:  influxql.LT,
  1047  					LHS: &influxql.VarRef{Val: "time"},
  1048  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
  1049  				},
  1050  				Dimensions: []*influxql.Dimension{{Expr: &influxql.Call{Name: "time", Args: []influxql.Expr{&influxql.DurationLiteral{Val: 5 * time.Minute}}}}},
  1051  				Fill:       influxql.NumberFill,
  1052  				FillValue:  int64(1),
  1053  			},
  1054  		},
  1055  
  1056  		// SELECT statement with FILL(none) -- check case insensitivity
  1057  		{
  1058  			s: fmt.Sprintf(`SELECT mean(value) FROM cpu where time < '%s' GROUP BY time(5m) FILL(none)`, now.UTC().Format(time.RFC3339Nano)),
  1059  			stmt: &influxql.SelectStatement{
  1060  				Fields: []*influxql.Field{{
  1061  					Expr: &influxql.Call{
  1062  						Name: "mean",
  1063  						Args: []influxql.Expr{&influxql.VarRef{Val: "value"}}}}},
  1064  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1065  				Condition: &influxql.BinaryExpr{
  1066  					Op:  influxql.LT,
  1067  					LHS: &influxql.VarRef{Val: "time"},
  1068  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
  1069  				},
  1070  				Dimensions: []*influxql.Dimension{{Expr: &influxql.Call{Name: "time", Args: []influxql.Expr{&influxql.DurationLiteral{Val: 5 * time.Minute}}}}},
  1071  				Fill:       influxql.NoFill,
  1072  			},
  1073  		},
  1074  
  1075  		// SELECT statement with previous fill
  1076  		{
  1077  			s: fmt.Sprintf(`SELECT mean(value) FROM cpu where time < '%s' GROUP BY time(5m) FILL(previous)`, now.UTC().Format(time.RFC3339Nano)),
  1078  			stmt: &influxql.SelectStatement{
  1079  				Fields: []*influxql.Field{{
  1080  					Expr: &influxql.Call{
  1081  						Name: "mean",
  1082  						Args: []influxql.Expr{&influxql.VarRef{Val: "value"}}}}},
  1083  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1084  				Condition: &influxql.BinaryExpr{
  1085  					Op:  influxql.LT,
  1086  					LHS: &influxql.VarRef{Val: "time"},
  1087  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
  1088  				},
  1089  				Dimensions: []*influxql.Dimension{{Expr: &influxql.Call{Name: "time", Args: []influxql.Expr{&influxql.DurationLiteral{Val: 5 * time.Minute}}}}},
  1090  				Fill:       influxql.PreviousFill,
  1091  			},
  1092  		},
  1093  
  1094  		// SELECT statement with average fill
  1095  		{
  1096  			s: fmt.Sprintf(`SELECT mean(value) FROM cpu where time < '%s' GROUP BY time(5m) FILL(linear)`, now.UTC().Format(time.RFC3339Nano)),
  1097  			stmt: &influxql.SelectStatement{
  1098  				Fields: []*influxql.Field{{
  1099  					Expr: &influxql.Call{
  1100  						Name: "mean",
  1101  						Args: []influxql.Expr{&influxql.VarRef{Val: "value"}}}}},
  1102  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1103  				Condition: &influxql.BinaryExpr{
  1104  					Op:  influxql.LT,
  1105  					LHS: &influxql.VarRef{Val: "time"},
  1106  					RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)},
  1107  				},
  1108  				Dimensions: []*influxql.Dimension{{Expr: &influxql.Call{Name: "time", Args: []influxql.Expr{&influxql.DurationLiteral{Val: 5 * time.Minute}}}}},
  1109  				Fill:       influxql.LinearFill,
  1110  			},
  1111  		},
  1112  
  1113  		// SELECT casts
  1114  		{
  1115  			s: `SELECT field1::float, field2::integer, field6::unsigned, field3::string, field4::boolean, field5::field, tag1::tag FROM cpu`,
  1116  			stmt: &influxql.SelectStatement{
  1117  				IsRawQuery: true,
  1118  				Fields: []*influxql.Field{
  1119  					{
  1120  						Expr: &influxql.VarRef{
  1121  							Val:  "field1",
  1122  							Type: influxql.Float,
  1123  						},
  1124  					},
  1125  					{
  1126  						Expr: &influxql.VarRef{
  1127  							Val:  "field2",
  1128  							Type: influxql.Integer,
  1129  						},
  1130  					},
  1131  					{
  1132  						Expr: &influxql.VarRef{
  1133  							Val:  "field6",
  1134  							Type: influxql.Unsigned,
  1135  						},
  1136  					},
  1137  					{
  1138  						Expr: &influxql.VarRef{
  1139  							Val:  "field3",
  1140  							Type: influxql.String,
  1141  						},
  1142  					},
  1143  					{
  1144  						Expr: &influxql.VarRef{
  1145  							Val:  "field4",
  1146  							Type: influxql.Boolean,
  1147  						},
  1148  					},
  1149  					{
  1150  						Expr: &influxql.VarRef{
  1151  							Val:  "field5",
  1152  							Type: influxql.AnyField,
  1153  						},
  1154  					},
  1155  					{
  1156  						Expr: &influxql.VarRef{
  1157  							Val:  "tag1",
  1158  							Type: influxql.Tag,
  1159  						},
  1160  					},
  1161  				},
  1162  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1163  			},
  1164  		},
  1165  
  1166  		// SELECT statement with a bound parameter
  1167  		{
  1168  			s: `SELECT value FROM cpu WHERE value > $value`,
  1169  			params: map[string]interface{}{
  1170  				"value": int64(2),
  1171  			},
  1172  			stmt: &influxql.SelectStatement{
  1173  				IsRawQuery: true,
  1174  				Fields: []*influxql.Field{{
  1175  					Expr: &influxql.VarRef{Val: "value"}}},
  1176  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1177  				Condition: &influxql.BinaryExpr{
  1178  					Op:  influxql.GT,
  1179  					LHS: &influxql.VarRef{Val: "value"},
  1180  					RHS: &influxql.IntegerLiteral{Val: 2},
  1181  				},
  1182  			},
  1183  		},
  1184  
  1185  		// SELECT statement with a bound parameter that contains spaces
  1186  		{
  1187  			s: `SELECT value FROM cpu WHERE value > $"multi-word value"`,
  1188  			params: map[string]interface{}{
  1189  				"multi-word value": int64(2),
  1190  			},
  1191  			stmt: &influxql.SelectStatement{
  1192  				IsRawQuery: true,
  1193  				Fields: []*influxql.Field{{
  1194  					Expr: &influxql.VarRef{Val: "value"}}},
  1195  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1196  				Condition: &influxql.BinaryExpr{
  1197  					Op:  influxql.GT,
  1198  					LHS: &influxql.VarRef{Val: "value"},
  1199  					RHS: &influxql.IntegerLiteral{Val: 2},
  1200  				},
  1201  			},
  1202  		},
  1203  
  1204  		// SELECT statement with a field as a bound parameter.
  1205  		{
  1206  			s: `SELECT mean($field) FROM cpu`,
  1207  			params: map[string]interface{}{
  1208  				"field": map[string]interface{}{"identifier": "value"},
  1209  			},
  1210  			stmt: &influxql.SelectStatement{
  1211  				Fields: []*influxql.Field{{
  1212  					Expr: &influxql.Call{
  1213  						Name: "mean",
  1214  						Args: []influxql.Expr{
  1215  							&influxql.VarRef{Val: "value"},
  1216  						}}},
  1217  				},
  1218  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1219  			},
  1220  		},
  1221  
  1222  		// SELECT statement with a function as a bound parameter.
  1223  		{
  1224  			s: `SELECT $fn(value) FROM cpu`,
  1225  			params: map[string]interface{}{
  1226  				"fn": map[string]interface{}{"identifier": "mean"},
  1227  			},
  1228  			stmt: &influxql.SelectStatement{
  1229  				Fields: []*influxql.Field{{
  1230  					Expr: &influxql.Call{
  1231  						Name: "mean",
  1232  						Args: []influxql.Expr{
  1233  							&influxql.VarRef{Val: "value"},
  1234  						}}},
  1235  				},
  1236  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1237  			},
  1238  		},
  1239  
  1240  		// SELECT statement with a regex as a bound parameter.
  1241  		{
  1242  			s: `SELECT mean(value) FROM cpu WHERE host =~ $host`,
  1243  			params: map[string]interface{}{
  1244  				"host": map[string]interface{}{"regex": "^server.*"},
  1245  			},
  1246  			stmt: &influxql.SelectStatement{
  1247  				Fields: []*influxql.Field{{
  1248  					Expr: &influxql.Call{
  1249  						Name: "mean",
  1250  						Args: []influxql.Expr{
  1251  							&influxql.VarRef{Val: "value"},
  1252  						}}},
  1253  				},
  1254  				Condition: &influxql.BinaryExpr{
  1255  					Op: influxql.EQREGEX,
  1256  					LHS: &influxql.VarRef{
  1257  						Val: "host",
  1258  					},
  1259  					RHS: &influxql.RegexLiteral{
  1260  						Val: regexp.MustCompile(`^server.*`),
  1261  					},
  1262  				},
  1263  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1264  			},
  1265  		},
  1266  
  1267  		// SELECT statement with a field and type as a bound parameter.
  1268  		{
  1269  			s: `SELECT $field::$type FROM cpu`,
  1270  			params: map[string]interface{}{
  1271  				"field": map[string]interface{}{"identifier": "value"},
  1272  				"type":  map[string]interface{}{"identifier": "integer"},
  1273  			},
  1274  			stmt: &influxql.SelectStatement{
  1275  				IsRawQuery: true,
  1276  				Fields: []*influxql.Field{{
  1277  					Expr: &influxql.VarRef{
  1278  						Val:  "value",
  1279  						Type: influxql.Integer,
  1280  					}},
  1281  				},
  1282  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1283  			},
  1284  		},
  1285  
  1286  		// SELECT statement with a float as a bound parameter.
  1287  		{
  1288  			s: `SELECT value FROM cpu WHERE value > $f`,
  1289  			params: map[string]interface{}{
  1290  				"f": map[string]interface{}{"float": 2.0},
  1291  			},
  1292  			stmt: &influxql.SelectStatement{
  1293  				IsRawQuery: true,
  1294  				Fields: []*influxql.Field{{
  1295  					Expr: &influxql.VarRef{
  1296  						Val: "value",
  1297  					}},
  1298  				},
  1299  				Condition: &influxql.BinaryExpr{
  1300  					Op: influxql.GT,
  1301  					LHS: &influxql.VarRef{
  1302  						Val: "value",
  1303  					},
  1304  					RHS: &influxql.NumberLiteral{
  1305  						Val: 2,
  1306  					},
  1307  				},
  1308  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1309  			},
  1310  		},
  1311  
  1312  		// SELECT statement with a float as an integer in a bound parameter.
  1313  		{
  1314  			s: `SELECT value FROM cpu WHERE value > $f`,
  1315  			params: map[string]interface{}{
  1316  				"f": map[string]interface{}{"float": int64(2)},
  1317  			},
  1318  			stmt: &influxql.SelectStatement{
  1319  				IsRawQuery: true,
  1320  				Fields: []*influxql.Field{{
  1321  					Expr: &influxql.VarRef{
  1322  						Val: "value",
  1323  					}},
  1324  				},
  1325  				Condition: &influxql.BinaryExpr{
  1326  					Op: influxql.GT,
  1327  					LHS: &influxql.VarRef{
  1328  						Val: "value",
  1329  					},
  1330  					RHS: &influxql.NumberLiteral{
  1331  						Val: 2,
  1332  					},
  1333  				},
  1334  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1335  			},
  1336  		},
  1337  
  1338  		// SELECT statement with an integer in a bound parameter.
  1339  		{
  1340  			s: `SELECT value FROM cpu WHERE value > $i`,
  1341  			params: map[string]interface{}{
  1342  				"i": map[string]interface{}{"integer": int64(2)},
  1343  			},
  1344  			stmt: &influxql.SelectStatement{
  1345  				IsRawQuery: true,
  1346  				Fields: []*influxql.Field{{
  1347  					Expr: &influxql.VarRef{
  1348  						Val: "value",
  1349  					}},
  1350  				},
  1351  				Condition: &influxql.BinaryExpr{
  1352  					Op: influxql.GT,
  1353  					LHS: &influxql.VarRef{
  1354  						Val: "value",
  1355  					},
  1356  					RHS: &influxql.IntegerLiteral{
  1357  						Val: 2,
  1358  					},
  1359  				},
  1360  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1361  			},
  1362  		},
  1363  
  1364  		// SELECT statement with group by interval with a bound parameter.
  1365  		{
  1366  			s: `SELECT mean(value) FROM cpu GROUP BY time($interval)`,
  1367  			params: map[string]interface{}{
  1368  				"interval": map[string]interface{}{"duration": "10s"},
  1369  			},
  1370  			stmt: &influxql.SelectStatement{
  1371  				Fields: []*influxql.Field{{
  1372  					Expr: &influxql.Call{
  1373  						Name: "mean",
  1374  						Args: []influxql.Expr{
  1375  							&influxql.VarRef{Val: "value"},
  1376  						},
  1377  					}},
  1378  				},
  1379  				Dimensions: []*influxql.Dimension{{
  1380  					Expr: &influxql.Call{
  1381  						Name: "time",
  1382  						Args: []influxql.Expr{
  1383  							&influxql.DurationLiteral{Val: 10 * time.Second},
  1384  						},
  1385  					},
  1386  				}},
  1387  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1388  			},
  1389  		},
  1390  
  1391  		// SELECT statement with group by interval integer with a bound parameter.
  1392  		{
  1393  			s: `SELECT mean(value) FROM cpu GROUP BY time($interval)`,
  1394  			params: map[string]interface{}{
  1395  				"interval": map[string]interface{}{"duration": int64(10 * time.Second)},
  1396  			},
  1397  			stmt: &influxql.SelectStatement{
  1398  				Fields: []*influxql.Field{{
  1399  					Expr: &influxql.Call{
  1400  						Name: "mean",
  1401  						Args: []influxql.Expr{
  1402  							&influxql.VarRef{Val: "value"},
  1403  						},
  1404  					}},
  1405  				},
  1406  				Dimensions: []*influxql.Dimension{{
  1407  					Expr: &influxql.Call{
  1408  						Name: "time",
  1409  						Args: []influxql.Expr{
  1410  							&influxql.DurationLiteral{Val: 10 * time.Second},
  1411  						},
  1412  					},
  1413  				}},
  1414  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1415  			},
  1416  		},
  1417  
  1418  		// SELECT statement with group by interval integer with a bound parameter and nanosecond precision.
  1419  		{
  1420  			s: `SELECT mean(value) FROM cpu GROUP BY time($interval)`,
  1421  			params: map[string]interface{}{
  1422  				"interval": map[string]interface{}{"duration": int64(10)},
  1423  			},
  1424  			stmt: &influxql.SelectStatement{
  1425  				Fields: []*influxql.Field{{
  1426  					Expr: &influxql.Call{
  1427  						Name: "mean",
  1428  						Args: []influxql.Expr{
  1429  							&influxql.VarRef{Val: "value"},
  1430  						},
  1431  					}},
  1432  				},
  1433  				Dimensions: []*influxql.Dimension{{
  1434  					Expr: &influxql.Call{
  1435  						Name: "time",
  1436  						Args: []influxql.Expr{
  1437  							&influxql.DurationLiteral{Val: 10},
  1438  						},
  1439  					},
  1440  				}},
  1441  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1442  			},
  1443  		},
  1444  
  1445  		// SELECT statement with group by interval json number with a bound parameter and nanosecond precision.
  1446  		{
  1447  			s: `SELECT mean(value) FROM cpu GROUP BY time($interval)`,
  1448  			params: map[string]interface{}{
  1449  				"interval": map[string]interface{}{"duration": json.Number("10")},
  1450  			},
  1451  			stmt: &influxql.SelectStatement{
  1452  				Fields: []*influxql.Field{{
  1453  					Expr: &influxql.Call{
  1454  						Name: "mean",
  1455  						Args: []influxql.Expr{
  1456  							&influxql.VarRef{Val: "value"},
  1457  						},
  1458  					}},
  1459  				},
  1460  				Dimensions: []*influxql.Dimension{{
  1461  					Expr: &influxql.Call{
  1462  						Name: "time",
  1463  						Args: []influxql.Expr{
  1464  							&influxql.DurationLiteral{Val: 10},
  1465  						},
  1466  					},
  1467  				}},
  1468  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1469  			},
  1470  		},
  1471  
  1472  		// SELECT statement with a subquery
  1473  		{
  1474  			s: `SELECT sum(derivative) FROM (SELECT derivative(value) FROM cpu GROUP BY host) WHERE time >= now() - 1d GROUP BY time(1h)`,
  1475  			stmt: &influxql.SelectStatement{
  1476  				Fields: []*influxql.Field{{
  1477  					Expr: &influxql.Call{
  1478  						Name: "sum",
  1479  						Args: []influxql.Expr{
  1480  							&influxql.VarRef{Val: "derivative"},
  1481  						}},
  1482  				}},
  1483  				Dimensions: []*influxql.Dimension{{
  1484  					Expr: &influxql.Call{
  1485  						Name: "time",
  1486  						Args: []influxql.Expr{
  1487  							&influxql.DurationLiteral{Val: time.Hour},
  1488  						},
  1489  					},
  1490  				}},
  1491  				Sources: []influxql.Source{
  1492  					&influxql.SubQuery{
  1493  						Statement: &influxql.SelectStatement{
  1494  							Fields: []*influxql.Field{{
  1495  								Expr: &influxql.Call{
  1496  									Name: "derivative",
  1497  									Args: []influxql.Expr{
  1498  										&influxql.VarRef{Val: "value"},
  1499  									},
  1500  								},
  1501  							}},
  1502  							Dimensions: []*influxql.Dimension{{
  1503  								Expr: &influxql.VarRef{Val: "host"},
  1504  							}},
  1505  							Sources: []influxql.Source{
  1506  								&influxql.Measurement{Name: "cpu"},
  1507  							},
  1508  						},
  1509  					},
  1510  				},
  1511  				Condition: &influxql.BinaryExpr{
  1512  					Op:  influxql.GTE,
  1513  					LHS: &influxql.VarRef{Val: "time"},
  1514  					RHS: &influxql.BinaryExpr{
  1515  						Op:  influxql.SUB,
  1516  						LHS: &influxql.Call{Name: "now"},
  1517  						RHS: &influxql.DurationLiteral{Val: 24 * time.Hour},
  1518  					},
  1519  				},
  1520  			},
  1521  		},
  1522  
  1523  		{
  1524  			s: `SELECT sum(mean) FROM (SELECT mean(value) FROM cpu GROUP BY time(1h)) WHERE time >= now() - 1d`,
  1525  			stmt: &influxql.SelectStatement{
  1526  				Fields: []*influxql.Field{{
  1527  					Expr: &influxql.Call{
  1528  						Name: "sum",
  1529  						Args: []influxql.Expr{
  1530  							&influxql.VarRef{Val: "mean"},
  1531  						}},
  1532  				}},
  1533  				Sources: []influxql.Source{
  1534  					&influxql.SubQuery{
  1535  						Statement: &influxql.SelectStatement{
  1536  							Fields: []*influxql.Field{{
  1537  								Expr: &influxql.Call{
  1538  									Name: "mean",
  1539  									Args: []influxql.Expr{
  1540  										&influxql.VarRef{Val: "value"},
  1541  									},
  1542  								},
  1543  							}},
  1544  							Dimensions: []*influxql.Dimension{{
  1545  								Expr: &influxql.Call{
  1546  									Name: "time",
  1547  									Args: []influxql.Expr{
  1548  										&influxql.DurationLiteral{Val: time.Hour},
  1549  									},
  1550  								},
  1551  							}},
  1552  							Sources: []influxql.Source{
  1553  								&influxql.Measurement{Name: "cpu"},
  1554  							},
  1555  						},
  1556  					},
  1557  				},
  1558  				Condition: &influxql.BinaryExpr{
  1559  					Op:  influxql.GTE,
  1560  					LHS: &influxql.VarRef{Val: "time"},
  1561  					RHS: &influxql.BinaryExpr{
  1562  						Op:  influxql.SUB,
  1563  						LHS: &influxql.Call{Name: "now"},
  1564  						RHS: &influxql.DurationLiteral{Val: 24 * time.Hour},
  1565  					},
  1566  				},
  1567  			},
  1568  		},
  1569  
  1570  		{
  1571  			s: `SELECT sum(mean) FROM (SELECT mean(value) FROM cpu WHERE time >= now() - 1d GROUP BY time(1h))`,
  1572  			stmt: &influxql.SelectStatement{
  1573  				Fields: []*influxql.Field{{
  1574  					Expr: &influxql.Call{
  1575  						Name: "sum",
  1576  						Args: []influxql.Expr{
  1577  							&influxql.VarRef{Val: "mean"},
  1578  						}},
  1579  				}},
  1580  				Sources: []influxql.Source{
  1581  					&influxql.SubQuery{
  1582  						Statement: &influxql.SelectStatement{
  1583  							Fields: []*influxql.Field{{
  1584  								Expr: &influxql.Call{
  1585  									Name: "mean",
  1586  									Args: []influxql.Expr{
  1587  										&influxql.VarRef{Val: "value"},
  1588  									},
  1589  								},
  1590  							}},
  1591  							Dimensions: []*influxql.Dimension{{
  1592  								Expr: &influxql.Call{
  1593  									Name: "time",
  1594  									Args: []influxql.Expr{
  1595  										&influxql.DurationLiteral{Val: time.Hour},
  1596  									},
  1597  								},
  1598  							}},
  1599  							Condition: &influxql.BinaryExpr{
  1600  								Op:  influxql.GTE,
  1601  								LHS: &influxql.VarRef{Val: "time"},
  1602  								RHS: &influxql.BinaryExpr{
  1603  									Op:  influxql.SUB,
  1604  									LHS: &influxql.Call{Name: "now"},
  1605  									RHS: &influxql.DurationLiteral{Val: 24 * time.Hour},
  1606  								},
  1607  							},
  1608  							Sources: []influxql.Source{
  1609  								&influxql.Measurement{Name: "cpu"},
  1610  							},
  1611  						},
  1612  					},
  1613  				},
  1614  			},
  1615  		},
  1616  
  1617  		{
  1618  			s: `SELECT sum(derivative) FROM (SELECT derivative(mean(value)) FROM cpu GROUP BY host) WHERE time >= now() - 1d GROUP BY time(1h)`,
  1619  			stmt: &influxql.SelectStatement{
  1620  				Fields: []*influxql.Field{{
  1621  					Expr: &influxql.Call{
  1622  						Name: "sum",
  1623  						Args: []influxql.Expr{
  1624  							&influxql.VarRef{Val: "derivative"},
  1625  						}},
  1626  				}},
  1627  				Dimensions: []*influxql.Dimension{{
  1628  					Expr: &influxql.Call{
  1629  						Name: "time",
  1630  						Args: []influxql.Expr{
  1631  							&influxql.DurationLiteral{Val: time.Hour},
  1632  						},
  1633  					},
  1634  				}},
  1635  				Sources: []influxql.Source{
  1636  					&influxql.SubQuery{
  1637  						Statement: &influxql.SelectStatement{
  1638  							Fields: []*influxql.Field{{
  1639  								Expr: &influxql.Call{
  1640  									Name: "derivative",
  1641  									Args: []influxql.Expr{
  1642  										&influxql.Call{
  1643  											Name: "mean",
  1644  											Args: []influxql.Expr{
  1645  												&influxql.VarRef{Val: "value"},
  1646  											},
  1647  										},
  1648  									},
  1649  								},
  1650  							}},
  1651  							Dimensions: []*influxql.Dimension{{
  1652  								Expr: &influxql.VarRef{Val: "host"},
  1653  							}},
  1654  							Sources: []influxql.Source{
  1655  								&influxql.Measurement{Name: "cpu"},
  1656  							},
  1657  						},
  1658  					},
  1659  				},
  1660  				Condition: &influxql.BinaryExpr{
  1661  					Op:  influxql.GTE,
  1662  					LHS: &influxql.VarRef{Val: "time"},
  1663  					RHS: &influxql.BinaryExpr{
  1664  						Op:  influxql.SUB,
  1665  						LHS: &influxql.Call{Name: "now"},
  1666  						RHS: &influxql.DurationLiteral{Val: 24 * time.Hour},
  1667  					},
  1668  				},
  1669  			},
  1670  		},
  1671  
  1672  		// select statements with intertwined comments
  1673  		{
  1674  			s: `SELECT "user" /*, system, idle */ FROM cpu`,
  1675  			stmt: &influxql.SelectStatement{
  1676  				IsRawQuery: true,
  1677  				Fields: []*influxql.Field{
  1678  					{Expr: &influxql.VarRef{Val: "user"}},
  1679  				},
  1680  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1681  			},
  1682  		},
  1683  
  1684  		{
  1685  			s: `SELECT /foo\/*bar/ FROM /foo\/*bar*/ WHERE x = 1`,
  1686  			stmt: &influxql.SelectStatement{
  1687  				IsRawQuery: true,
  1688  				Fields: []*influxql.Field{
  1689  					{Expr: &influxql.RegexLiteral{Val: regexp.MustCompile(`foo/*bar`)}},
  1690  				},
  1691  				Sources: []influxql.Source{
  1692  					&influxql.Measurement{
  1693  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`foo/*bar*`)},
  1694  					},
  1695  				},
  1696  				Condition: &influxql.BinaryExpr{
  1697  					Op:  influxql.EQ,
  1698  					LHS: &influxql.VarRef{Val: "x"},
  1699  					RHS: &influxql.IntegerLiteral{Val: 1},
  1700  				},
  1701  			},
  1702  		},
  1703  
  1704  		// SELECT statement with a time zone
  1705  		{
  1706  			s: `SELECT mean(value) FROM cpu WHERE time >= now() - 7d GROUP BY time(1d) TZ('America/Los_Angeles')`,
  1707  			stmt: &influxql.SelectStatement{
  1708  				Fields: []*influxql.Field{{
  1709  					Expr: &influxql.Call{
  1710  						Name: "mean",
  1711  						Args: []influxql.Expr{
  1712  							&influxql.VarRef{Val: "value"}},
  1713  					}}},
  1714  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1715  				Condition: &influxql.BinaryExpr{
  1716  					Op:  influxql.GTE,
  1717  					LHS: &influxql.VarRef{Val: "time"},
  1718  					RHS: &influxql.BinaryExpr{
  1719  						Op:  influxql.SUB,
  1720  						LHS: &influxql.Call{Name: "now"},
  1721  						RHS: &influxql.DurationLiteral{Val: 7 * 24 * time.Hour},
  1722  					},
  1723  				},
  1724  				Dimensions: []*influxql.Dimension{{
  1725  					Expr: &influxql.Call{
  1726  						Name: "time",
  1727  						Args: []influxql.Expr{
  1728  							&influxql.DurationLiteral{Val: 24 * time.Hour}}}}},
  1729  				Location: LosAngeles,
  1730  			},
  1731  		},
  1732  
  1733  		// EXPLAIN ...
  1734  		{
  1735  			s: `EXPLAIN SELECT * FROM cpu`,
  1736  			stmt: &influxql.ExplainStatement{
  1737  				Statement: &influxql.SelectStatement{
  1738  					IsRawQuery: true,
  1739  					Fields: []*influxql.Field{
  1740  						{Expr: &influxql.Wildcard{}},
  1741  					},
  1742  					Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1743  				},
  1744  			},
  1745  		},
  1746  
  1747  		// EXPLAIN ANALYZE ...
  1748  		{
  1749  			s: `EXPLAIN ANALYZE SELECT * FROM cpu`,
  1750  			stmt: &influxql.ExplainStatement{
  1751  				Statement: &influxql.SelectStatement{
  1752  					IsRawQuery: true,
  1753  					Fields: []*influxql.Field{
  1754  						{Expr: &influxql.Wildcard{}},
  1755  					},
  1756  					Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1757  				},
  1758  				Analyze: true,
  1759  			},
  1760  		},
  1761  
  1762  		// See issues https://github.com/influxdata/influxdb/issues/1647
  1763  		// and https://github.com/influxdata/influxdb/issues/4404
  1764  		// DELETE statement
  1765  		//{
  1766  		//	s: `DELETE FROM myseries WHERE host = 'hosta.influxdb.org'`,
  1767  		//	stmt: &influxql.DeleteStatement{
  1768  		//		Source: &influxql.Measurement{Name: "myseries"},
  1769  		//		Condition: &influxql.BinaryExpr{
  1770  		//			Op:  influxql.EQ,
  1771  		//			LHS: &influxql.VarRef{Val: "host"},
  1772  		//			RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  1773  		//		},
  1774  		//	},
  1775  		//},
  1776  
  1777  		// SHOW GRANTS
  1778  		{
  1779  			s:    `SHOW GRANTS FOR jdoe`,
  1780  			stmt: &influxql.ShowGrantsForUserStatement{Name: "jdoe"},
  1781  		},
  1782  
  1783  		// SHOW DATABASES
  1784  		{
  1785  			s:    `SHOW DATABASES`,
  1786  			stmt: &influxql.ShowDatabasesStatement{},
  1787  		},
  1788  
  1789  		// SHOW SERIES statement
  1790  		{
  1791  			s:    `SHOW SERIES`,
  1792  			stmt: &influxql.ShowSeriesStatement{},
  1793  		},
  1794  
  1795  		// SHOW SERIES FROM
  1796  		{
  1797  			s: `SHOW SERIES FROM cpu`,
  1798  			stmt: &influxql.ShowSeriesStatement{
  1799  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1800  			},
  1801  		},
  1802  
  1803  		// SHOW SERIES ON db0
  1804  		{
  1805  			s: `SHOW SERIES ON db0`,
  1806  			stmt: &influxql.ShowSeriesStatement{
  1807  				Database: "db0",
  1808  			},
  1809  		},
  1810  
  1811  		// SHOW SERIES FROM /<regex>/
  1812  		{
  1813  			s: `SHOW SERIES FROM /[cg]pu/`,
  1814  			stmt: &influxql.ShowSeriesStatement{
  1815  				Sources: []influxql.Source{
  1816  					&influxql.Measurement{
  1817  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  1818  					},
  1819  				},
  1820  			},
  1821  		},
  1822  
  1823  		// SHOW SERIES with OFFSET 0
  1824  		{
  1825  			s:    `SHOW SERIES OFFSET 0`,
  1826  			stmt: &influxql.ShowSeriesStatement{Offset: 0},
  1827  		},
  1828  
  1829  		// SHOW SERIES with LIMIT 2 OFFSET 0
  1830  		{
  1831  			s:    `SHOW SERIES LIMIT 2 OFFSET 0`,
  1832  			stmt: &influxql.ShowSeriesStatement{Offset: 0, Limit: 2},
  1833  		},
  1834  
  1835  		// SHOW SERIES WHERE with ORDER BY and LIMIT
  1836  		{
  1837  			skip: true,
  1838  			s:    `SHOW SERIES WHERE region = 'order by desc' ORDER BY DESC, field1, field2 DESC LIMIT 10`,
  1839  			stmt: &influxql.ShowSeriesStatement{
  1840  				Condition: &influxql.BinaryExpr{
  1841  					Op:  influxql.EQ,
  1842  					LHS: &influxql.VarRef{Val: "region"},
  1843  					RHS: &influxql.StringLiteral{Val: "order by desc"},
  1844  				},
  1845  				SortFields: []*influxql.SortField{
  1846  					&influxql.SortField{Ascending: false},
  1847  					&influxql.SortField{Name: "field1", Ascending: true},
  1848  					&influxql.SortField{Name: "field2"},
  1849  				},
  1850  				Limit: 10,
  1851  			},
  1852  		},
  1853  
  1854  		// SHOW SERIES CARDINALITY statement
  1855  		{
  1856  			s:    `SHOW SERIES CARDINALITY`,
  1857  			stmt: &influxql.ShowSeriesCardinalityStatement{},
  1858  		},
  1859  
  1860  		// SHOW SERIES CARDINALITY ON dbz statement
  1861  		{
  1862  			s:    `SHOW SERIES CARDINALITY ON dbz`,
  1863  			stmt: &influxql.ShowSeriesCardinalityStatement{Database: "dbz"},
  1864  		},
  1865  
  1866  		// SHOW SERIES EXACT CARDINALITY statement
  1867  		{
  1868  			s:    `SHOW SERIES EXACT CARDINALITY`,
  1869  			stmt: &influxql.ShowSeriesCardinalityStatement{Exact: true},
  1870  		},
  1871  
  1872  		// SHOW SERIES EXACT CARDINALITY FROM cpu
  1873  		{
  1874  			s: `SHOW SERIES EXACT CARDINALITY FROM cpu`,
  1875  			stmt: &influxql.ShowSeriesCardinalityStatement{
  1876  				Exact:   true,
  1877  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1878  			},
  1879  		},
  1880  
  1881  		// SHOW SERIES EXACT CARDINALITY ON db0
  1882  		{
  1883  			s: `SHOW SERIES EXACT CARDINALITY ON db0`,
  1884  			stmt: &influxql.ShowSeriesCardinalityStatement{
  1885  				Exact:    true,
  1886  				Database: "db0",
  1887  			},
  1888  		},
  1889  
  1890  		// SHOW SERIES EXACT CARDINALITY FROM /<regex>/
  1891  		{
  1892  			s: `SHOW SERIES EXACT CARDINALITY FROM /[cg]pu/`,
  1893  			stmt: &influxql.ShowSeriesCardinalityStatement{
  1894  				Exact: true,
  1895  				Sources: []influxql.Source{
  1896  					&influxql.Measurement{
  1897  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  1898  					},
  1899  				},
  1900  			},
  1901  		},
  1902  
  1903  		// SHOW SERIES EXACT CARDINALITY with OFFSET 0
  1904  		{
  1905  			s:    `SHOW SERIES EXACT CARDINALITY OFFSET 0`,
  1906  			stmt: &influxql.ShowSeriesCardinalityStatement{Exact: true, Offset: 0},
  1907  		},
  1908  
  1909  		// SHOW SERIES EXACT CARDINALITY with LIMIT 2 OFFSET 0
  1910  		{
  1911  			s:    `SHOW SERIES EXACT CARDINALITY LIMIT 2 OFFSET 0`,
  1912  			stmt: &influxql.ShowSeriesCardinalityStatement{Exact: true, Offset: 0, Limit: 2},
  1913  		},
  1914  
  1915  		// SHOW SERIES EXACT CARDINALITY WHERE with ORDER BY and LIMIT
  1916  		{
  1917  			s: `SHOW SERIES EXACT CARDINALITY WHERE region = 'order by desc' LIMIT 10`,
  1918  			stmt: &influxql.ShowSeriesCardinalityStatement{
  1919  				Exact: true,
  1920  				Condition: &influxql.BinaryExpr{
  1921  					Op:  influxql.EQ,
  1922  					LHS: &influxql.VarRef{Val: "region"},
  1923  					RHS: &influxql.StringLiteral{Val: "order by desc"},
  1924  				},
  1925  				Limit: 10,
  1926  			},
  1927  		},
  1928  
  1929  		// SHOW MEASUREMENTS WHERE with ORDER BY and LIMIT
  1930  		{
  1931  			skip: true,
  1932  			s:    `SHOW MEASUREMENTS WHERE region = 'uswest' ORDER BY ASC, field1, field2 DESC LIMIT 10`,
  1933  			stmt: &influxql.ShowMeasurementsStatement{
  1934  				Condition: &influxql.BinaryExpr{
  1935  					Op:  influxql.EQ,
  1936  					LHS: &influxql.VarRef{Val: "region"},
  1937  					RHS: &influxql.StringLiteral{Val: "uswest"},
  1938  				},
  1939  				SortFields: []*influxql.SortField{
  1940  					{Ascending: true},
  1941  					{Name: "field1"},
  1942  					{Name: "field2"},
  1943  				},
  1944  				Limit: 10,
  1945  			},
  1946  		},
  1947  
  1948  		// SHOW MEASUREMENTS ON db0
  1949  		{
  1950  			s: `SHOW MEASUREMENTS ON db0`,
  1951  			stmt: &influxql.ShowMeasurementsStatement{
  1952  				Database: "db0",
  1953  			},
  1954  		},
  1955  
  1956  		// SHOW MEASUREMENTS WITH MEASUREMENT = cpu
  1957  		{
  1958  			s: `SHOW MEASUREMENTS WITH MEASUREMENT = cpu`,
  1959  			stmt: &influxql.ShowMeasurementsStatement{
  1960  				Source: &influxql.Measurement{Name: "cpu"},
  1961  			},
  1962  		},
  1963  
  1964  		// SHOW MEASUREMENTS WITH MEASUREMENT =~ /regex/
  1965  		{
  1966  			s: `SHOW MEASUREMENTS WITH MEASUREMENT =~ /[cg]pu/`,
  1967  			stmt: &influxql.ShowMeasurementsStatement{
  1968  				Source: &influxql.Measurement{
  1969  					Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  1970  				},
  1971  			},
  1972  		},
  1973  
  1974  		// SHOW MEASUREMENT CARDINALITY statement
  1975  		{
  1976  			s:    `SHOW MEASUREMENT CARDINALITY`,
  1977  			stmt: &influxql.ShowMeasurementCardinalityStatement{},
  1978  		},
  1979  
  1980  		// SHOW MEASUREMENT CARDINALITY ON db0 statement
  1981  		{
  1982  			s: `SHOW MEASUREMENT CARDINALITY ON db0`,
  1983  			stmt: &influxql.ShowMeasurementCardinalityStatement{
  1984  				Exact:    false,
  1985  				Database: "db0",
  1986  			},
  1987  		},
  1988  
  1989  		// SHOW MEASUREMENT EXACT CARDINALITY statement
  1990  		{
  1991  			s: `SHOW MEASUREMENT EXACT CARDINALITY`,
  1992  			stmt: &influxql.ShowMeasurementCardinalityStatement{
  1993  				Exact: true,
  1994  			},
  1995  		},
  1996  
  1997  		// SHOW MEASUREMENT EXACT CARDINALITY FROM cpu
  1998  		{
  1999  			s: `SHOW MEASUREMENT EXACT CARDINALITY FROM cpu`,
  2000  			stmt: &influxql.ShowMeasurementCardinalityStatement{
  2001  				Exact:   true,
  2002  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  2003  			},
  2004  		},
  2005  
  2006  		// SHOW MEASUREMENT EXACT CARDINALITY ON db0
  2007  		{
  2008  			s: `SHOW MEASUREMENT EXACT CARDINALITY ON db0`,
  2009  			stmt: &influxql.ShowMeasurementCardinalityStatement{
  2010  				Exact:    true,
  2011  				Database: "db0",
  2012  			},
  2013  		},
  2014  
  2015  		// SHOW MEASUREMENT EXACT CARDINALITY FROM /<regex>/
  2016  		{
  2017  			s: `SHOW MEASUREMENT EXACT CARDINALITY FROM /[cg]pu/`,
  2018  			stmt: &influxql.ShowMeasurementCardinalityStatement{
  2019  				Exact: true,
  2020  				Sources: []influxql.Source{
  2021  					&influxql.Measurement{
  2022  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  2023  					},
  2024  				},
  2025  			},
  2026  		},
  2027  
  2028  		// SHOW MEASUREMENT EXACT CARDINALITY with OFFSET 0
  2029  		{
  2030  			s: `SHOW MEASUREMENT EXACT CARDINALITY OFFSET 0`,
  2031  			stmt: &influxql.ShowMeasurementCardinalityStatement{
  2032  				Exact: true, Offset: 0},
  2033  		},
  2034  
  2035  		// SHOW MEASUREMENT EXACT CARDINALITY with LIMIT 2 OFFSET 0
  2036  		{
  2037  			s: `SHOW MEASUREMENT EXACT CARDINALITY LIMIT 2 OFFSET 0`,
  2038  			stmt: &influxql.ShowMeasurementCardinalityStatement{
  2039  				Exact: true, Offset: 0, Limit: 2},
  2040  		},
  2041  
  2042  		// SHOW MEASUREMENT EXACT CARDINALITY WHERE with ORDER BY and LIMIT
  2043  		{
  2044  			s: `SHOW MEASUREMENT EXACT CARDINALITY WHERE region = 'order by desc' LIMIT 10`,
  2045  			stmt: &influxql.ShowMeasurementCardinalityStatement{
  2046  				Exact: true,
  2047  				Condition: &influxql.BinaryExpr{
  2048  					Op:  influxql.EQ,
  2049  					LHS: &influxql.VarRef{Val: "region"},
  2050  					RHS: &influxql.StringLiteral{Val: "order by desc"},
  2051  				},
  2052  				Limit: 10,
  2053  			},
  2054  		},
  2055  
  2056  		// SHOW QUERIES
  2057  		{
  2058  			s:    `SHOW QUERIES`,
  2059  			stmt: &influxql.ShowQueriesStatement{},
  2060  		},
  2061  
  2062  		// KILL QUERY 4
  2063  		{
  2064  			s: `KILL QUERY 4`,
  2065  			stmt: &influxql.KillQueryStatement{
  2066  				QueryID: 4,
  2067  			},
  2068  		},
  2069  
  2070  		// KILL QUERY 4 ON localhost
  2071  		{
  2072  			s: `KILL QUERY 4 ON localhost`,
  2073  			stmt: &influxql.KillQueryStatement{
  2074  				QueryID: 4,
  2075  				Host:    "localhost",
  2076  			},
  2077  		},
  2078  
  2079  		// SHOW RETENTION POLICIES
  2080  		{
  2081  			s:    `SHOW RETENTION POLICIES`,
  2082  			stmt: &influxql.ShowRetentionPoliciesStatement{},
  2083  		},
  2084  
  2085  		// SHOW RETENTION POLICIES ON db0
  2086  		{
  2087  			s: `SHOW RETENTION POLICIES ON db0`,
  2088  			stmt: &influxql.ShowRetentionPoliciesStatement{
  2089  				Database: "db0",
  2090  			},
  2091  		},
  2092  		// SHOW TAG KEY CARDINALITY statement
  2093  		{
  2094  			s:    `SHOW TAG KEY CARDINALITY`,
  2095  			stmt: &influxql.ShowTagKeyCardinalityStatement{},
  2096  		},
  2097  
  2098  		// SHOW TAG KEY CARDINALITY FROM cpu
  2099  		{
  2100  			s: `SHOW TAG KEY CARDINALITY FROM cpu`,
  2101  			stmt: &influxql.ShowTagKeyCardinalityStatement{
  2102  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  2103  			},
  2104  		},
  2105  
  2106  		// SHOW TAG KEY CARDINALITY ON db0
  2107  		{
  2108  			s: `SHOW TAG KEY CARDINALITY ON db0`,
  2109  			stmt: &influxql.ShowTagKeyCardinalityStatement{
  2110  				Database: "db0",
  2111  			},
  2112  		},
  2113  
  2114  		// SHOW TAG KEY CARDINALITY FROM /<regex>/
  2115  		{
  2116  			s: `SHOW TAG KEY CARDINALITY FROM /[cg]pu/`,
  2117  			stmt: &influxql.ShowTagKeyCardinalityStatement{
  2118  				Sources: []influxql.Source{
  2119  					&influxql.Measurement{
  2120  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  2121  					},
  2122  				},
  2123  			},
  2124  		},
  2125  
  2126  		// SHOW TAG KEY CARDINALITY with OFFSET 0
  2127  		{
  2128  			s:    `SHOW TAG KEY CARDINALITY OFFSET 0`,
  2129  			stmt: &influxql.ShowTagKeyCardinalityStatement{Offset: 0},
  2130  		},
  2131  
  2132  		// SHOW TAG KEY CARDINALITY with LIMIT 2 OFFSET 0
  2133  		{
  2134  			s:    `SHOW TAG KEY CARDINALITY LIMIT 2 OFFSET 0`,
  2135  			stmt: &influxql.ShowTagKeyCardinalityStatement{Offset: 0, Limit: 2},
  2136  		},
  2137  
  2138  		// SHOW TAG KEY CARDINALITY WHERE with ORDER BY and LIMIT
  2139  		{
  2140  			s: `SHOW TAG KEY CARDINALITY WHERE region = 'order by desc' LIMIT 10`,
  2141  			stmt: &influxql.ShowTagKeyCardinalityStatement{
  2142  				Condition: &influxql.BinaryExpr{
  2143  					Op:  influxql.EQ,
  2144  					LHS: &influxql.VarRef{Val: "region"},
  2145  					RHS: &influxql.StringLiteral{Val: "order by desc"},
  2146  				},
  2147  				Limit: 10,
  2148  			},
  2149  		},
  2150  
  2151  		// SHOW TAG KEY EXACT CARDINALITY statement
  2152  		{
  2153  			s: `SHOW TAG KEY EXACT CARDINALITY`,
  2154  			stmt: &influxql.ShowTagKeyCardinalityStatement{
  2155  				Exact: true,
  2156  			},
  2157  		},
  2158  
  2159  		// SHOW TAG KEY EXACT CARDINALITY FROM cpu
  2160  		{
  2161  			s: `SHOW TAG KEY EXACT CARDINALITY FROM cpu`,
  2162  			stmt: &influxql.ShowTagKeyCardinalityStatement{
  2163  				Exact:   true,
  2164  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  2165  			},
  2166  		},
  2167  
  2168  		// SHOW TAG KEY EXACT CARDINALITY ON db0
  2169  		{
  2170  			s: `SHOW TAG KEY EXACT CARDINALITY ON db0`,
  2171  			stmt: &influxql.ShowTagKeyCardinalityStatement{
  2172  				Exact:    true,
  2173  				Database: "db0",
  2174  			},
  2175  		},
  2176  
  2177  		// SHOW TAG KEY EXACT CARDINALITY FROM /<regex>/
  2178  		{
  2179  			s: `SHOW TAG KEY EXACT CARDINALITY FROM /[cg]pu/`,
  2180  			stmt: &influxql.ShowTagKeyCardinalityStatement{
  2181  				Exact: true,
  2182  				Sources: []influxql.Source{
  2183  					&influxql.Measurement{
  2184  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  2185  					},
  2186  				},
  2187  			},
  2188  		},
  2189  
  2190  		// SHOW TAG KEY EXACT CARDINALITY with OFFSET 0
  2191  		{
  2192  			s:    `SHOW TAG KEY EXACT CARDINALITY OFFSET 0`,
  2193  			stmt: &influxql.ShowTagKeyCardinalityStatement{Exact: true, Offset: 0},
  2194  		},
  2195  
  2196  		// SHOW TAG KEY EXACT CARDINALITY with LIMIT 2 OFFSET 0
  2197  		{
  2198  			s:    `SHOW TAG KEY EXACT CARDINALITY LIMIT 2 OFFSET 0`,
  2199  			stmt: &influxql.ShowTagKeyCardinalityStatement{Exact: true, Offset: 0, Limit: 2},
  2200  		},
  2201  
  2202  		// SHOW TAG KEY EXACT CARDINALITY WHERE with ORDER BY and LIMIT
  2203  		{
  2204  			s: `SHOW TAG KEY EXACT CARDINALITY WHERE region = 'order by desc' LIMIT 10`,
  2205  			stmt: &influxql.ShowTagKeyCardinalityStatement{
  2206  				Exact: true,
  2207  				Condition: &influxql.BinaryExpr{
  2208  					Op:  influxql.EQ,
  2209  					LHS: &influxql.VarRef{Val: "region"},
  2210  					RHS: &influxql.StringLiteral{Val: "order by desc"},
  2211  				},
  2212  				Limit: 10,
  2213  			},
  2214  		},
  2215  
  2216  		// SHOW TAG KEYS
  2217  		{
  2218  			s: `SHOW TAG KEYS FROM src`,
  2219  			stmt: &influxql.ShowTagKeysStatement{
  2220  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2221  			},
  2222  		},
  2223  
  2224  		// SHOW TAG KEYS ON db0
  2225  		{
  2226  			s: `SHOW TAG KEYS ON db0`,
  2227  			stmt: &influxql.ShowTagKeysStatement{
  2228  				Database: "db0",
  2229  			},
  2230  		},
  2231  
  2232  		// SHOW TAG KEYS with LIMIT
  2233  		{
  2234  			s: `SHOW TAG KEYS FROM src LIMIT 2`,
  2235  			stmt: &influxql.ShowTagKeysStatement{
  2236  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2237  				Limit:   2,
  2238  			},
  2239  		},
  2240  
  2241  		// SHOW TAG KEYS with OFFSET
  2242  		{
  2243  			s: `SHOW TAG KEYS FROM src OFFSET 1`,
  2244  			stmt: &influxql.ShowTagKeysStatement{
  2245  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2246  				Offset:  1,
  2247  			},
  2248  		},
  2249  
  2250  		// SHOW TAG KEYS with LIMIT and OFFSET
  2251  		{
  2252  			s: `SHOW TAG KEYS FROM src LIMIT 2 OFFSET 1`,
  2253  			stmt: &influxql.ShowTagKeysStatement{
  2254  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2255  				Limit:   2,
  2256  				Offset:  1,
  2257  			},
  2258  		},
  2259  
  2260  		// SHOW TAG KEYS with SLIMIT
  2261  		{
  2262  			s: `SHOW TAG KEYS FROM src SLIMIT 2`,
  2263  			stmt: &influxql.ShowTagKeysStatement{
  2264  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2265  				SLimit:  2,
  2266  			},
  2267  		},
  2268  
  2269  		// SHOW TAG KEYS with SOFFSET
  2270  		{
  2271  			s: `SHOW TAG KEYS FROM src SOFFSET 1`,
  2272  			stmt: &influxql.ShowTagKeysStatement{
  2273  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2274  				SOffset: 1,
  2275  			},
  2276  		},
  2277  
  2278  		// SHOW TAG KEYS with SLIMIT and SOFFSET
  2279  		{
  2280  			s: `SHOW TAG KEYS FROM src SLIMIT 2 SOFFSET 1`,
  2281  			stmt: &influxql.ShowTagKeysStatement{
  2282  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2283  				SLimit:  2,
  2284  				SOffset: 1,
  2285  			},
  2286  		},
  2287  
  2288  		// SHOW TAG KEYS with LIMIT, OFFSET, SLIMIT, and SOFFSET
  2289  		{
  2290  			s: `SHOW TAG KEYS FROM src LIMIT 4 OFFSET 3 SLIMIT 2 SOFFSET 1`,
  2291  			stmt: &influxql.ShowTagKeysStatement{
  2292  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2293  				Limit:   4,
  2294  				Offset:  3,
  2295  				SLimit:  2,
  2296  				SOffset: 1,
  2297  			},
  2298  		},
  2299  
  2300  		// SHOW TAG KEYS FROM /<regex>/
  2301  		{
  2302  			s: `SHOW TAG KEYS FROM /[cg]pu/`,
  2303  			stmt: &influxql.ShowTagKeysStatement{
  2304  				Sources: []influxql.Source{
  2305  					&influxql.Measurement{
  2306  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  2307  					},
  2308  				},
  2309  			},
  2310  		},
  2311  
  2312  		// SHOW TAG KEYS
  2313  		{
  2314  			skip: true,
  2315  			s:    `SHOW TAG KEYS FROM src WHERE region = 'uswest' ORDER BY ASC, field1, field2 DESC LIMIT 10`,
  2316  			stmt: &influxql.ShowTagKeysStatement{
  2317  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2318  				Condition: &influxql.BinaryExpr{
  2319  					Op:  influxql.EQ,
  2320  					LHS: &influxql.VarRef{Val: "region"},
  2321  					RHS: &influxql.StringLiteral{Val: "uswest"},
  2322  				},
  2323  				SortFields: []*influxql.SortField{
  2324  					{Ascending: true},
  2325  					{Name: "field1"},
  2326  					{Name: "field2"},
  2327  				},
  2328  				Limit: 10,
  2329  			},
  2330  		},
  2331  
  2332  		// SHOW TAG VALUES FROM ... WITH KEY = ...
  2333  		{
  2334  			skip: true,
  2335  			s:    `SHOW TAG VALUES FROM src WITH KEY = region WHERE region = 'uswest' ORDER BY ASC, field1, field2 DESC LIMIT 10`,
  2336  			stmt: &influxql.ShowTagValuesStatement{
  2337  				Sources:    []influxql.Source{&influxql.Measurement{Name: "src"}},
  2338  				Op:         influxql.EQ,
  2339  				TagKeyExpr: &influxql.StringLiteral{Val: "region"},
  2340  				Condition: &influxql.BinaryExpr{
  2341  					Op:  influxql.EQ,
  2342  					LHS: &influxql.VarRef{Val: "region"},
  2343  					RHS: &influxql.StringLiteral{Val: "uswest"},
  2344  				},
  2345  				SortFields: []*influxql.SortField{
  2346  					{Ascending: true},
  2347  					{Name: "field1"},
  2348  					{Name: "field2"},
  2349  				},
  2350  				Limit: 10,
  2351  			},
  2352  		},
  2353  
  2354  		// SHOW TAG VALUES FROM ... WITH KEY IN...
  2355  		{
  2356  			s: `SHOW TAG VALUES FROM cpu WITH KEY IN (region, host) WHERE region = 'uswest'`,
  2357  			stmt: &influxql.ShowTagValuesStatement{
  2358  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  2359  				Op:         influxql.IN,
  2360  				TagKeyExpr: &influxql.ListLiteral{Vals: []string{"region", "host"}},
  2361  				Condition: &influxql.BinaryExpr{
  2362  					Op:  influxql.EQ,
  2363  					LHS: &influxql.VarRef{Val: "region"},
  2364  					RHS: &influxql.StringLiteral{Val: "uswest"},
  2365  				},
  2366  			},
  2367  		},
  2368  
  2369  		// SHOW TAG VALUES ... AND TAG KEY =
  2370  		{
  2371  			s: `SHOW TAG VALUES FROM cpu WITH KEY IN (region,service,host)WHERE region = 'uswest'`,
  2372  			stmt: &influxql.ShowTagValuesStatement{
  2373  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  2374  				Op:         influxql.IN,
  2375  				TagKeyExpr: &influxql.ListLiteral{Vals: []string{"region", "service", "host"}},
  2376  				Condition: &influxql.BinaryExpr{
  2377  					Op:  influxql.EQ,
  2378  					LHS: &influxql.VarRef{Val: "region"},
  2379  					RHS: &influxql.StringLiteral{Val: "uswest"},
  2380  				},
  2381  			},
  2382  		},
  2383  
  2384  		// SHOW TAG VALUES WITH KEY = ...
  2385  		{
  2386  			s: `SHOW TAG VALUES WITH KEY = host WHERE region = 'uswest'`,
  2387  			stmt: &influxql.ShowTagValuesStatement{
  2388  				Op:         influxql.EQ,
  2389  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2390  				Condition: &influxql.BinaryExpr{
  2391  					Op:  influxql.EQ,
  2392  					LHS: &influxql.VarRef{Val: "region"},
  2393  					RHS: &influxql.StringLiteral{Val: "uswest"},
  2394  				},
  2395  			},
  2396  		},
  2397  
  2398  		// SHOW TAG VALUES FROM /<regex>/ WITH KEY = ...
  2399  		{
  2400  			s: `SHOW TAG VALUES FROM /[cg]pu/ WITH KEY = host`,
  2401  			stmt: &influxql.ShowTagValuesStatement{
  2402  				Sources: []influxql.Source{
  2403  					&influxql.Measurement{
  2404  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  2405  					},
  2406  				},
  2407  				Op:         influxql.EQ,
  2408  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2409  			},
  2410  		},
  2411  
  2412  		// SHOW TAG VALUES WITH KEY = "..."
  2413  		{
  2414  			s: `SHOW TAG VALUES WITH KEY = "host" WHERE region = 'uswest'`,
  2415  			stmt: &influxql.ShowTagValuesStatement{
  2416  				Op:         influxql.EQ,
  2417  				TagKeyExpr: &influxql.StringLiteral{Val: `host`},
  2418  				Condition: &influxql.BinaryExpr{
  2419  					Op:  influxql.EQ,
  2420  					LHS: &influxql.VarRef{Val: "region"},
  2421  					RHS: &influxql.StringLiteral{Val: "uswest"},
  2422  				},
  2423  			},
  2424  		},
  2425  
  2426  		// SHOW TAG VALUES WITH KEY =~ /<regex>/
  2427  		{
  2428  			s: `SHOW TAG VALUES WITH KEY =~ /(host|region)/`,
  2429  			stmt: &influxql.ShowTagValuesStatement{
  2430  				Op:         influxql.EQREGEX,
  2431  				TagKeyExpr: &influxql.RegexLiteral{Val: regexp.MustCompile(`(host|region)`)},
  2432  			},
  2433  		},
  2434  
  2435  		// SHOW TAG VALUES ON db0
  2436  		{
  2437  			s: `SHOW TAG VALUES ON db0 WITH KEY = "host"`,
  2438  			stmt: &influxql.ShowTagValuesStatement{
  2439  				Database:   "db0",
  2440  				Op:         influxql.EQ,
  2441  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2442  			},
  2443  		},
  2444  
  2445  		// SHOW TAG VALUES CARDINALITY statement
  2446  		{
  2447  			s: `SHOW TAG VALUES CARDINALITY WITH KEY = host`,
  2448  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2449  				Op:         influxql.EQ,
  2450  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2451  			},
  2452  		},
  2453  
  2454  		// SHOW TAG VALUES CARDINALITY FROM cpu
  2455  		{
  2456  			s: `SHOW TAG VALUES CARDINALITY FROM cpu WITH KEY =  host`,
  2457  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2458  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  2459  				Op:         influxql.EQ,
  2460  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2461  			},
  2462  		},
  2463  
  2464  		// SHOW TAG VALUES CARDINALITY ON db0
  2465  		{
  2466  			s: `SHOW TAG VALUES CARDINALITY ON db0 WITH KEY = host`,
  2467  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2468  				Database:   "db0",
  2469  				Op:         influxql.EQ,
  2470  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2471  			},
  2472  		},
  2473  
  2474  		// SHOW TAG VALUES CARDINALITY FROM /<regex>/
  2475  		{
  2476  			s: `SHOW TAG VALUES CARDINALITY FROM /[cg]pu/ WITH KEY = host`,
  2477  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2478  				Sources: []influxql.Source{
  2479  					&influxql.Measurement{
  2480  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  2481  					},
  2482  				},
  2483  				Op:         influxql.EQ,
  2484  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2485  			},
  2486  		},
  2487  
  2488  		// SHOW TAG VALUES CARDINALITY with OFFSET 0
  2489  		{
  2490  			s: `SHOW TAG VALUES CARDINALITY WITH KEY = host OFFSET 0`,
  2491  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2492  				Op:         influxql.EQ,
  2493  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2494  				Offset:     0,
  2495  			},
  2496  		},
  2497  
  2498  		// SHOW TAG VALUES CARDINALITY with LIMIT 2 OFFSET 0
  2499  		{
  2500  			s: `SHOW TAG VALUES CARDINALITY WITH KEY = host LIMIT 2 OFFSET 0`,
  2501  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2502  				Op:         influxql.EQ,
  2503  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2504  				Offset:     0,
  2505  				Limit:      2,
  2506  			},
  2507  		},
  2508  
  2509  		// SHOW TAG VALUES CARDINALITY WHERE with ORDER BY and LIMIT
  2510  		{
  2511  			s: `SHOW TAG VALUES CARDINALITY WITH KEY = host WHERE region = 'order by desc' LIMIT 10`,
  2512  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2513  				Op:         influxql.EQ,
  2514  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2515  				Condition: &influxql.BinaryExpr{
  2516  					Op:  influxql.EQ,
  2517  					LHS: &influxql.VarRef{Val: "region"},
  2518  					RHS: &influxql.StringLiteral{Val: "order by desc"},
  2519  				},
  2520  				Limit: 10,
  2521  			},
  2522  		},
  2523  
  2524  		// SHOW TAG VALUES EXACT CARDINALITY statement
  2525  		{
  2526  			s: `SHOW TAG VALUES EXACT CARDINALITY WITH KEY = host`,
  2527  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2528  				Exact:      true,
  2529  				Op:         influxql.EQ,
  2530  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2531  			},
  2532  		},
  2533  
  2534  		// SHOW TAG VALUES EXACT CARDINALITY FROM cpu
  2535  		{
  2536  			s: `SHOW TAG VALUES EXACT CARDINALITY FROM cpu WITH KEY =  host`,
  2537  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2538  				Exact:      true,
  2539  				Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  2540  				Op:         influxql.EQ,
  2541  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2542  			},
  2543  		},
  2544  
  2545  		// SHOW TAG VALUES EXACT CARDINALITY ON db0
  2546  		{
  2547  			s: `SHOW TAG VALUES EXACT CARDINALITY ON db0 WITH KEY = host`,
  2548  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2549  				Exact:      true,
  2550  				Database:   "db0",
  2551  				Op:         influxql.EQ,
  2552  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2553  			},
  2554  		},
  2555  
  2556  		// SHOW TAG VALUES EXACT CARDINALITY FROM /<regex>/
  2557  		{
  2558  			s: `SHOW TAG VALUES EXACT CARDINALITY FROM /[cg]pu/ WITH KEY = host`,
  2559  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2560  				Exact: true,
  2561  				Sources: []influxql.Source{
  2562  					&influxql.Measurement{
  2563  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  2564  					},
  2565  				},
  2566  				Op:         influxql.EQ,
  2567  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2568  			},
  2569  		},
  2570  
  2571  		// SHOW TAG VALUES EXACT CARDINALITY with OFFSET 0
  2572  		{
  2573  			s: `SHOW TAG VALUES EXACT CARDINALITY WITH KEY = host OFFSET 0`,
  2574  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2575  				Exact:      true,
  2576  				Op:         influxql.EQ,
  2577  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2578  				Offset:     0,
  2579  			},
  2580  		},
  2581  
  2582  		// SHOW TAG VALUES EXACT CARDINALITY with LIMIT 2 OFFSET 0
  2583  		{
  2584  			s: `SHOW TAG VALUES EXACT CARDINALITY WITH KEY = host LIMIT 2 OFFSET 0`,
  2585  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2586  				Exact:      true,
  2587  				Op:         influxql.EQ,
  2588  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2589  				Offset:     0,
  2590  				Limit:      2,
  2591  			},
  2592  		},
  2593  
  2594  		// SHOW TAG VALUES EXACT CARDINALITY WHERE with ORDER BY and LIMIT
  2595  		{
  2596  			s: `SHOW TAG VALUES EXACT CARDINALITY WITH KEY = host WHERE region = 'order by desc' LIMIT 10`,
  2597  			stmt: &influxql.ShowTagValuesCardinalityStatement{
  2598  				Exact:      true,
  2599  				Op:         influxql.EQ,
  2600  				TagKeyExpr: &influxql.StringLiteral{Val: "host"},
  2601  				Condition: &influxql.BinaryExpr{
  2602  					Op:  influxql.EQ,
  2603  					LHS: &influxql.VarRef{Val: "region"},
  2604  					RHS: &influxql.StringLiteral{Val: "order by desc"},
  2605  				},
  2606  				Limit: 10,
  2607  			},
  2608  		},
  2609  
  2610  		// SHOW USERS
  2611  		{
  2612  			s:    `SHOW USERS`,
  2613  			stmt: &influxql.ShowUsersStatement{},
  2614  		},
  2615  
  2616  		// SHOW FIELD KEYS
  2617  		{
  2618  			skip: true,
  2619  			s:    `SHOW FIELD KEYS FROM src ORDER BY ASC, field1, field2 DESC LIMIT 10`,
  2620  			stmt: &influxql.ShowFieldKeysStatement{
  2621  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2622  				SortFields: []*influxql.SortField{
  2623  					{Ascending: true},
  2624  					{Name: "field1"},
  2625  					{Name: "field2"},
  2626  				},
  2627  				Limit: 10,
  2628  			},
  2629  		},
  2630  		{
  2631  			s: `SHOW FIELD KEYS FROM /[cg]pu/`,
  2632  			stmt: &influxql.ShowFieldKeysStatement{
  2633  				Sources: []influxql.Source{
  2634  					&influxql.Measurement{
  2635  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  2636  					},
  2637  				},
  2638  			},
  2639  		},
  2640  		{
  2641  			s: `SHOW FIELD KEYS ON db0`,
  2642  			stmt: &influxql.ShowFieldKeysStatement{
  2643  				Database: "db0",
  2644  			},
  2645  		},
  2646  
  2647  		// SHOW FIELD KEY CARDINALITY statement
  2648  		{
  2649  			s:    `SHOW FIELD KEY CARDINALITY`,
  2650  			stmt: &influxql.ShowFieldKeyCardinalityStatement{},
  2651  		},
  2652  
  2653  		// SHOW FIELD KEY CARDINALITY FROM cpu
  2654  		{
  2655  			s: `SHOW FIELD KEY CARDINALITY FROM cpu`,
  2656  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2657  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  2658  			},
  2659  		},
  2660  
  2661  		// SHOW FIELD KEY CARDINALITY ON db0
  2662  		{
  2663  			s: `SHOW FIELD KEY CARDINALITY ON db0`,
  2664  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2665  				Database: "db0",
  2666  			},
  2667  		},
  2668  
  2669  		// SHOW FIELD KEY CARDINALITY FROM /<regex>/
  2670  		{
  2671  			s: `SHOW FIELD KEY CARDINALITY FROM /[cg]pu/`,
  2672  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2673  				Sources: []influxql.Source{
  2674  					&influxql.Measurement{
  2675  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  2676  					},
  2677  				},
  2678  			},
  2679  		},
  2680  
  2681  		// SHOW FIELD KEY CARDINALITY with OFFSET 0
  2682  		{
  2683  			s: `SHOW FIELD KEY CARDINALITY OFFSET 0`,
  2684  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2685  				Offset: 0,
  2686  			},
  2687  		},
  2688  
  2689  		// SHOW FIELD KEY CARDINALITY with LIMIT 2 OFFSET 0
  2690  		{
  2691  			s: `SHOW FIELD KEY CARDINALITY LIMIT 2 OFFSET 0`,
  2692  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2693  				Offset: 0,
  2694  				Limit:  2,
  2695  			},
  2696  		},
  2697  
  2698  		// SHOW FIELD KEY CARDINALITY WHERE with ORDER BY and LIMIT
  2699  		{
  2700  			s: `SHOW FIELD KEY CARDINALITY WHERE region = 'order by desc' LIMIT 10`,
  2701  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2702  				Condition: &influxql.BinaryExpr{
  2703  					Op:  influxql.EQ,
  2704  					LHS: &influxql.VarRef{Val: "region"},
  2705  					RHS: &influxql.StringLiteral{Val: "order by desc"},
  2706  				},
  2707  				Limit: 10,
  2708  			},
  2709  		},
  2710  
  2711  		// SHOW FIELD KEY EXACT CARDINALITY statement
  2712  		{
  2713  			s: `SHOW FIELD KEY EXACT CARDINALITY`,
  2714  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2715  				Exact: true,
  2716  			},
  2717  		},
  2718  
  2719  		// SHOW FIELD KEY EXACT CARDINALITY FROM cpu
  2720  		{
  2721  			s: `SHOW FIELD KEY EXACT CARDINALITY FROM cpu`,
  2722  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2723  				Exact:   true,
  2724  				Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  2725  			},
  2726  		},
  2727  
  2728  		// SHOW FIELD KEY EXACT CARDINALITY ON db0
  2729  		{
  2730  			s: `SHOW FIELD KEY EXACT CARDINALITY ON db0`,
  2731  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2732  				Exact:    true,
  2733  				Database: "db0",
  2734  			},
  2735  		},
  2736  
  2737  		// SHOW FIELD KEY EXACT CARDINALITY FROM /<regex>/
  2738  		{
  2739  			s: `SHOW FIELD KEY EXACT CARDINALITY FROM /[cg]pu/`,
  2740  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2741  				Exact: true,
  2742  				Sources: []influxql.Source{
  2743  					&influxql.Measurement{
  2744  						Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`[cg]pu`)},
  2745  					},
  2746  				},
  2747  			},
  2748  		},
  2749  
  2750  		// SHOW FIELD KEY EXACT CARDINALITY with OFFSET 0
  2751  		{
  2752  			s: `SHOW FIELD KEY EXACT CARDINALITY OFFSET 0`,
  2753  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2754  				Exact:  true,
  2755  				Offset: 0,
  2756  			},
  2757  		},
  2758  
  2759  		// SHOW FIELD KEY EXACT CARDINALITY with LIMIT 2 OFFSET 0
  2760  		{
  2761  			s: `SHOW FIELD KEY EXACT CARDINALITY LIMIT 2 OFFSET 0`,
  2762  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2763  				Exact:  true,
  2764  				Offset: 0,
  2765  				Limit:  2,
  2766  			},
  2767  		},
  2768  
  2769  		// SHOW FIELD KEY EXACT CARDINALITY WHERE with ORDER BY and LIMIT
  2770  		{
  2771  			s: `SHOW FIELD KEY EXACT CARDINALITY WHERE region = 'order by desc' LIMIT 10`,
  2772  			stmt: &influxql.ShowFieldKeyCardinalityStatement{
  2773  				Exact: true,
  2774  				Condition: &influxql.BinaryExpr{
  2775  					Op:  influxql.EQ,
  2776  					LHS: &influxql.VarRef{Val: "region"},
  2777  					RHS: &influxql.StringLiteral{Val: "order by desc"},
  2778  				},
  2779  				Limit: 10,
  2780  			},
  2781  		},
  2782  		// DELETE statement
  2783  		{
  2784  			s:    `DELETE FROM src`,
  2785  			stmt: &influxql.DeleteSeriesStatement{Sources: []influxql.Source{&influxql.Measurement{Name: "src"}}},
  2786  		},
  2787  		{
  2788  			s: `DELETE WHERE host = 'hosta.influxdb.org'`,
  2789  			stmt: &influxql.DeleteSeriesStatement{
  2790  				Condition: &influxql.BinaryExpr{
  2791  					Op:  influxql.EQ,
  2792  					LHS: &influxql.VarRef{Val: "host"},
  2793  					RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  2794  				},
  2795  			},
  2796  		},
  2797  		{
  2798  			s: `DELETE FROM src WHERE host = 'hosta.influxdb.org'`,
  2799  			stmt: &influxql.DeleteSeriesStatement{
  2800  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2801  				Condition: &influxql.BinaryExpr{
  2802  					Op:  influxql.EQ,
  2803  					LHS: &influxql.VarRef{Val: "host"},
  2804  					RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  2805  				},
  2806  			},
  2807  		},
  2808  
  2809  		// DROP SERIES statement
  2810  		{
  2811  			s:    `DROP SERIES FROM src`,
  2812  			stmt: &influxql.DropSeriesStatement{Sources: []influxql.Source{&influxql.Measurement{Name: "src"}}},
  2813  		},
  2814  		{
  2815  			s: `DROP SERIES WHERE host = 'hosta.influxdb.org'`,
  2816  			stmt: &influxql.DropSeriesStatement{
  2817  				Condition: &influxql.BinaryExpr{
  2818  					Op:  influxql.EQ,
  2819  					LHS: &influxql.VarRef{Val: "host"},
  2820  					RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  2821  				},
  2822  			},
  2823  		},
  2824  		{
  2825  			s: `DROP SERIES FROM src WHERE host = 'hosta.influxdb.org'`,
  2826  			stmt: &influxql.DropSeriesStatement{
  2827  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  2828  				Condition: &influxql.BinaryExpr{
  2829  					Op:  influxql.EQ,
  2830  					LHS: &influxql.VarRef{Val: "host"},
  2831  					RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  2832  				},
  2833  			},
  2834  		},
  2835  
  2836  		// SHOW CONTINUOUS QUERIES statement
  2837  		{
  2838  			s:    `SHOW CONTINUOUS QUERIES`,
  2839  			stmt: &influxql.ShowContinuousQueriesStatement{},
  2840  		},
  2841  
  2842  		// CREATE CONTINUOUS QUERY ... INTO <measurement>
  2843  		{
  2844  			s: `CREATE CONTINUOUS QUERY myquery ON testdb RESAMPLE EVERY 1m FOR 1h BEGIN SELECT count(field1) INTO measure1 FROM myseries GROUP BY time(5m) END`,
  2845  			stmt: &influxql.CreateContinuousQueryStatement{
  2846  				Name:     "myquery",
  2847  				Database: "testdb",
  2848  				Source: &influxql.SelectStatement{
  2849  					Fields:  []*influxql.Field{{Expr: &influxql.Call{Name: "count", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}}}}},
  2850  					Target:  &influxql.Target{Measurement: &influxql.Measurement{Name: "measure1", IsTarget: true}},
  2851  					Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
  2852  					Dimensions: []*influxql.Dimension{
  2853  						{
  2854  							Expr: &influxql.Call{
  2855  								Name: "time",
  2856  								Args: []influxql.Expr{
  2857  									&influxql.DurationLiteral{Val: 5 * time.Minute},
  2858  								},
  2859  							},
  2860  						},
  2861  					},
  2862  				},
  2863  				ResampleEvery: time.Minute,
  2864  				ResampleFor:   time.Hour,
  2865  			},
  2866  		},
  2867  
  2868  		{
  2869  			s: `CREATE CONTINUOUS QUERY myquery ON testdb RESAMPLE FOR 1h BEGIN SELECT count(field1) INTO measure1 FROM myseries GROUP BY time(5m) END`,
  2870  			stmt: &influxql.CreateContinuousQueryStatement{
  2871  				Name:     "myquery",
  2872  				Database: "testdb",
  2873  				Source: &influxql.SelectStatement{
  2874  					Fields:  []*influxql.Field{{Expr: &influxql.Call{Name: "count", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}}}}},
  2875  					Target:  &influxql.Target{Measurement: &influxql.Measurement{Name: "measure1", IsTarget: true}},
  2876  					Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
  2877  					Dimensions: []*influxql.Dimension{
  2878  						{
  2879  							Expr: &influxql.Call{
  2880  								Name: "time",
  2881  								Args: []influxql.Expr{
  2882  									&influxql.DurationLiteral{Val: 5 * time.Minute},
  2883  								},
  2884  							},
  2885  						},
  2886  					},
  2887  				},
  2888  				ResampleFor: time.Hour,
  2889  			},
  2890  		},
  2891  
  2892  		{
  2893  			s: `CREATE CONTINUOUS QUERY myquery ON testdb RESAMPLE EVERY 1m BEGIN SELECT count(field1) INTO measure1 FROM myseries GROUP BY time(5m) END`,
  2894  			stmt: &influxql.CreateContinuousQueryStatement{
  2895  				Name:     "myquery",
  2896  				Database: "testdb",
  2897  				Source: &influxql.SelectStatement{
  2898  					Fields:  []*influxql.Field{{Expr: &influxql.Call{Name: "count", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}}}}},
  2899  					Target:  &influxql.Target{Measurement: &influxql.Measurement{Name: "measure1", IsTarget: true}},
  2900  					Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
  2901  					Dimensions: []*influxql.Dimension{
  2902  						{
  2903  							Expr: &influxql.Call{
  2904  								Name: "time",
  2905  								Args: []influxql.Expr{
  2906  									&influxql.DurationLiteral{Val: 5 * time.Minute},
  2907  								},
  2908  							},
  2909  						},
  2910  					},
  2911  				},
  2912  				ResampleEvery: time.Minute,
  2913  			},
  2914  		},
  2915  
  2916  		{
  2917  			s: `create continuous query "this.is-a.test" on segments begin select * into measure1 from cpu_load_short end`,
  2918  			stmt: &influxql.CreateContinuousQueryStatement{
  2919  				Name:     "this.is-a.test",
  2920  				Database: "segments",
  2921  				Source: &influxql.SelectStatement{
  2922  					IsRawQuery: true,
  2923  					Fields:     []*influxql.Field{{Expr: &influxql.Wildcard{}}},
  2924  					Target:     &influxql.Target{Measurement: &influxql.Measurement{Name: "measure1", IsTarget: true}},
  2925  					Sources:    []influxql.Source{&influxql.Measurement{Name: "cpu_load_short"}},
  2926  				},
  2927  			},
  2928  		},
  2929  
  2930  		// CREATE CONTINUOUS QUERY ... INTO <retention-policy>.<measurement>
  2931  		{
  2932  			s: `CREATE CONTINUOUS QUERY myquery ON testdb BEGIN SELECT count(field1) INTO "1h.policy1"."cpu.load" FROM myseries GROUP BY time(5m) END`,
  2933  			stmt: &influxql.CreateContinuousQueryStatement{
  2934  				Name:     "myquery",
  2935  				Database: "testdb",
  2936  				Source: &influxql.SelectStatement{
  2937  					Fields: []*influxql.Field{{Expr: &influxql.Call{Name: "count", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}}}}},
  2938  					Target: &influxql.Target{
  2939  						Measurement: &influxql.Measurement{RetentionPolicy: "1h.policy1", Name: "cpu.load", IsTarget: true},
  2940  					},
  2941  					Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
  2942  					Dimensions: []*influxql.Dimension{
  2943  						{
  2944  							Expr: &influxql.Call{
  2945  								Name: "time",
  2946  								Args: []influxql.Expr{
  2947  									&influxql.DurationLiteral{Val: 5 * time.Minute},
  2948  								},
  2949  							},
  2950  						},
  2951  					},
  2952  				},
  2953  			},
  2954  		},
  2955  
  2956  		// CREATE CONTINUOUS QUERY for non-aggregate SELECT stmts
  2957  		{
  2958  			s: `CREATE CONTINUOUS QUERY myquery ON testdb BEGIN SELECT value INTO "policy1"."value" FROM myseries END`,
  2959  			stmt: &influxql.CreateContinuousQueryStatement{
  2960  				Name:     "myquery",
  2961  				Database: "testdb",
  2962  				Source: &influxql.SelectStatement{
  2963  					IsRawQuery: true,
  2964  					Fields:     []*influxql.Field{{Expr: &influxql.VarRef{Val: "value"}}},
  2965  					Target: &influxql.Target{
  2966  						Measurement: &influxql.Measurement{RetentionPolicy: "policy1", Name: "value", IsTarget: true},
  2967  					},
  2968  					Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
  2969  				},
  2970  			},
  2971  		},
  2972  
  2973  		// CREATE CONTINUOUS QUERY for non-aggregate SELECT stmts with multiple values
  2974  		{
  2975  			s: `CREATE CONTINUOUS QUERY myquery ON testdb BEGIN SELECT transmit_rx, transmit_tx INTO "policy1"."network" FROM myseries END`,
  2976  			stmt: &influxql.CreateContinuousQueryStatement{
  2977  				Name:     "myquery",
  2978  				Database: "testdb",
  2979  				Source: &influxql.SelectStatement{
  2980  					IsRawQuery: true,
  2981  					Fields: []*influxql.Field{{Expr: &influxql.VarRef{Val: "transmit_rx"}},
  2982  						{Expr: &influxql.VarRef{Val: "transmit_tx"}}},
  2983  					Target: &influxql.Target{
  2984  						Measurement: &influxql.Measurement{RetentionPolicy: "policy1", Name: "network", IsTarget: true},
  2985  					},
  2986  					Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}},
  2987  				},
  2988  			},
  2989  		},
  2990  
  2991  		// CREATE CONTINUOUS QUERY with backreference measurement name
  2992  		{
  2993  			s: `CREATE CONTINUOUS QUERY myquery ON testdb BEGIN SELECT mean(value) INTO "policy1".:measurement FROM /^[a-z]+.*/ GROUP BY time(1m) END`,
  2994  			stmt: &influxql.CreateContinuousQueryStatement{
  2995  				Name:     "myquery",
  2996  				Database: "testdb",
  2997  				Source: &influxql.SelectStatement{
  2998  					Fields: []*influxql.Field{{Expr: &influxql.Call{Name: "mean", Args: []influxql.Expr{&influxql.VarRef{Val: "value"}}}}},
  2999  					Target: &influxql.Target{
  3000  						Measurement: &influxql.Measurement{RetentionPolicy: "policy1", IsTarget: true},
  3001  					},
  3002  					Sources: []influxql.Source{&influxql.Measurement{Regex: &influxql.RegexLiteral{Val: regexp.MustCompile(`^[a-z]+.*`)}}},
  3003  					Dimensions: []*influxql.Dimension{
  3004  						{
  3005  							Expr: &influxql.Call{
  3006  								Name: "time",
  3007  								Args: []influxql.Expr{
  3008  									&influxql.DurationLiteral{Val: 1 * time.Minute},
  3009  								},
  3010  							},
  3011  						},
  3012  					},
  3013  				},
  3014  			},
  3015  		},
  3016  
  3017  		// CREATE DATABASE statement
  3018  		{
  3019  			s: `CREATE DATABASE testdb`,
  3020  			stmt: &influxql.CreateDatabaseStatement{
  3021  				Name:                  "testdb",
  3022  				RetentionPolicyCreate: false,
  3023  			},
  3024  		},
  3025  		{
  3026  			s: `CREATE DATABASE testdb WITH DURATION 24h`,
  3027  			stmt: &influxql.CreateDatabaseStatement{
  3028  				Name:                    "testdb",
  3029  				RetentionPolicyCreate:   true,
  3030  				RetentionPolicyDuration: duration(24 * time.Hour),
  3031  			},
  3032  		},
  3033  		{
  3034  			s: `CREATE DATABASE testdb WITH SHARD DURATION 30m`,
  3035  			stmt: &influxql.CreateDatabaseStatement{
  3036  				Name:                              "testdb",
  3037  				RetentionPolicyCreate:             true,
  3038  				RetentionPolicyShardGroupDuration: 30 * time.Minute,
  3039  			},
  3040  		},
  3041  		{
  3042  			s: `CREATE DATABASE testdb WITH REPLICATION 2`,
  3043  			stmt: &influxql.CreateDatabaseStatement{
  3044  				Name:                       "testdb",
  3045  				RetentionPolicyCreate:      true,
  3046  				RetentionPolicyReplication: intptr(2),
  3047  			},
  3048  		},
  3049  		{
  3050  			s: `CREATE DATABASE testdb WITH NAME test_name`,
  3051  			stmt: &influxql.CreateDatabaseStatement{
  3052  				Name:                  "testdb",
  3053  				RetentionPolicyCreate: true,
  3054  				RetentionPolicyName:   "test_name",
  3055  			},
  3056  		},
  3057  		{
  3058  			s: `CREATE DATABASE testdb WITH DURATION 24h REPLICATION 2 NAME test_name`,
  3059  			stmt: &influxql.CreateDatabaseStatement{
  3060  				Name:                       "testdb",
  3061  				RetentionPolicyCreate:      true,
  3062  				RetentionPolicyDuration:    duration(24 * time.Hour),
  3063  				RetentionPolicyReplication: intptr(2),
  3064  				RetentionPolicyName:        "test_name",
  3065  			},
  3066  		},
  3067  		{
  3068  			s: `CREATE DATABASE testdb WITH DURATION 24h REPLICATION 2 SHARD DURATION 10m NAME test_name `,
  3069  			stmt: &influxql.CreateDatabaseStatement{
  3070  				Name:                              "testdb",
  3071  				RetentionPolicyCreate:             true,
  3072  				RetentionPolicyDuration:           duration(24 * time.Hour),
  3073  				RetentionPolicyReplication:        intptr(2),
  3074  				RetentionPolicyName:               "test_name",
  3075  				RetentionPolicyShardGroupDuration: 10 * time.Minute,
  3076  			},
  3077  		},
  3078  
  3079  		// CREATE USER statement
  3080  		{
  3081  			s: `CREATE USER testuser WITH PASSWORD 'pwd1337'`,
  3082  			stmt: &influxql.CreateUserStatement{
  3083  				Name:     "testuser",
  3084  				Password: "pwd1337",
  3085  			},
  3086  		},
  3087  
  3088  		// CREATE USER ... WITH ALL PRIVILEGES
  3089  		{
  3090  			s: `CREATE USER testuser WITH PASSWORD 'pwd1337' WITH ALL PRIVILEGES`,
  3091  			stmt: &influxql.CreateUserStatement{
  3092  				Name:     "testuser",
  3093  				Password: "pwd1337",
  3094  				Admin:    true,
  3095  			},
  3096  		},
  3097  
  3098  		// SET PASSWORD FOR USER
  3099  		{
  3100  			s: `SET PASSWORD FOR testuser = 'pwd1337'`,
  3101  			stmt: &influxql.SetPasswordUserStatement{
  3102  				Name:     "testuser",
  3103  				Password: "pwd1337",
  3104  			},
  3105  		},
  3106  
  3107  		// DROP CONTINUOUS QUERY statement
  3108  		{
  3109  			s:    `DROP CONTINUOUS QUERY myquery ON foo`,
  3110  			stmt: &influxql.DropContinuousQueryStatement{Name: "myquery", Database: "foo"},
  3111  		},
  3112  
  3113  		// DROP DATABASE statement
  3114  		{
  3115  			s: `DROP DATABASE testdb`,
  3116  			stmt: &influxql.DropDatabaseStatement{
  3117  				Name: "testdb",
  3118  			},
  3119  		},
  3120  
  3121  		// DROP MEASUREMENT statement
  3122  		{
  3123  			s:    `DROP MEASUREMENT cpu`,
  3124  			stmt: &influxql.DropMeasurementStatement{Name: "cpu"},
  3125  		},
  3126  
  3127  		// DROP RETENTION POLICY
  3128  		{
  3129  			s: `DROP RETENTION POLICY "1h.cpu" ON mydb`,
  3130  			stmt: &influxql.DropRetentionPolicyStatement{
  3131  				Name:     `1h.cpu`,
  3132  				Database: `mydb`,
  3133  			},
  3134  		},
  3135  
  3136  		// DROP USER statement
  3137  		{
  3138  			s:    `DROP USER jdoe`,
  3139  			stmt: &influxql.DropUserStatement{Name: "jdoe"},
  3140  		},
  3141  
  3142  		// GRANT READ
  3143  		{
  3144  			s: `GRANT READ ON testdb TO jdoe`,
  3145  			stmt: &influxql.GrantStatement{
  3146  				Privilege: influxql.ReadPrivilege,
  3147  				On:        "testdb",
  3148  				User:      "jdoe",
  3149  			},
  3150  		},
  3151  
  3152  		// GRANT WRITE
  3153  		{
  3154  			s: `GRANT WRITE ON testdb TO jdoe`,
  3155  			stmt: &influxql.GrantStatement{
  3156  				Privilege: influxql.WritePrivilege,
  3157  				On:        "testdb",
  3158  				User:      "jdoe",
  3159  			},
  3160  		},
  3161  
  3162  		// GRANT ALL
  3163  		{
  3164  			s: `GRANT ALL ON testdb TO jdoe`,
  3165  			stmt: &influxql.GrantStatement{
  3166  				Privilege: influxql.AllPrivileges,
  3167  				On:        "testdb",
  3168  				User:      "jdoe",
  3169  			},
  3170  		},
  3171  
  3172  		// GRANT ALL PRIVILEGES
  3173  		{
  3174  			s: `GRANT ALL PRIVILEGES ON testdb TO jdoe`,
  3175  			stmt: &influxql.GrantStatement{
  3176  				Privilege: influxql.AllPrivileges,
  3177  				On:        "testdb",
  3178  				User:      "jdoe",
  3179  			},
  3180  		},
  3181  
  3182  		// GRANT ALL admin privilege
  3183  		{
  3184  			s: `GRANT ALL TO jdoe`,
  3185  			stmt: &influxql.GrantAdminStatement{
  3186  				User: "jdoe",
  3187  			},
  3188  		},
  3189  
  3190  		// GRANT ALL PRVILEGES admin privilege
  3191  		{
  3192  			s: `GRANT ALL PRIVILEGES TO jdoe`,
  3193  			stmt: &influxql.GrantAdminStatement{
  3194  				User: "jdoe",
  3195  			},
  3196  		},
  3197  
  3198  		// REVOKE READ
  3199  		{
  3200  			s: `REVOKE READ on testdb FROM jdoe`,
  3201  			stmt: &influxql.RevokeStatement{
  3202  				Privilege: influxql.ReadPrivilege,
  3203  				On:        "testdb",
  3204  				User:      "jdoe",
  3205  			},
  3206  		},
  3207  
  3208  		// REVOKE WRITE
  3209  		{
  3210  			s: `REVOKE WRITE ON testdb FROM jdoe`,
  3211  			stmt: &influxql.RevokeStatement{
  3212  				Privilege: influxql.WritePrivilege,
  3213  				On:        "testdb",
  3214  				User:      "jdoe",
  3215  			},
  3216  		},
  3217  
  3218  		// REVOKE ALL
  3219  		{
  3220  			s: `REVOKE ALL ON testdb FROM jdoe`,
  3221  			stmt: &influxql.RevokeStatement{
  3222  				Privilege: influxql.AllPrivileges,
  3223  				On:        "testdb",
  3224  				User:      "jdoe",
  3225  			},
  3226  		},
  3227  
  3228  		// REVOKE ALL PRIVILEGES
  3229  		{
  3230  			s: `REVOKE ALL PRIVILEGES ON testdb FROM jdoe`,
  3231  			stmt: &influxql.RevokeStatement{
  3232  				Privilege: influxql.AllPrivileges,
  3233  				On:        "testdb",
  3234  				User:      "jdoe",
  3235  			},
  3236  		},
  3237  
  3238  		// REVOKE ALL admin privilege
  3239  		{
  3240  			s: `REVOKE ALL FROM jdoe`,
  3241  			stmt: &influxql.RevokeAdminStatement{
  3242  				User: "jdoe",
  3243  			},
  3244  		},
  3245  
  3246  		// REVOKE ALL PRIVILEGES admin privilege
  3247  		{
  3248  			s: `REVOKE ALL PRIVILEGES FROM jdoe`,
  3249  			stmt: &influxql.RevokeAdminStatement{
  3250  				User: "jdoe",
  3251  			},
  3252  		},
  3253  
  3254  		// CREATE RETENTION POLICY
  3255  		{
  3256  			s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION 2`,
  3257  			stmt: &influxql.CreateRetentionPolicyStatement{
  3258  				Name:        "policy1",
  3259  				Database:    "testdb",
  3260  				Duration:    time.Hour,
  3261  				Replication: 2,
  3262  			},
  3263  		},
  3264  
  3265  		// CREATE RETENTION POLICY with infinite retention
  3266  		{
  3267  			s: `CREATE RETENTION POLICY policy1 ON testdb DURATION INF REPLICATION 2`,
  3268  			stmt: &influxql.CreateRetentionPolicyStatement{
  3269  				Name:        "policy1",
  3270  				Database:    "testdb",
  3271  				Duration:    0,
  3272  				Replication: 2,
  3273  			},
  3274  		},
  3275  
  3276  		// CREATE RETENTION POLICY ... DEFAULT
  3277  		{
  3278  			s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 2m REPLICATION 4 DEFAULT`,
  3279  			stmt: &influxql.CreateRetentionPolicyStatement{
  3280  				Name:        "policy1",
  3281  				Database:    "testdb",
  3282  				Duration:    2 * time.Minute,
  3283  				Replication: 4,
  3284  				Default:     true,
  3285  			},
  3286  		},
  3287  		// CREATE RETENTION POLICY
  3288  		{
  3289  			s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION 2 SHARD DURATION 30m`,
  3290  			stmt: &influxql.CreateRetentionPolicyStatement{
  3291  				Name:               "policy1",
  3292  				Database:           "testdb",
  3293  				Duration:           time.Hour,
  3294  				Replication:        2,
  3295  				ShardGroupDuration: 30 * time.Minute,
  3296  			},
  3297  		},
  3298  		{
  3299  			s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION 2 SHARD DURATION 0s`,
  3300  			stmt: &influxql.CreateRetentionPolicyStatement{
  3301  				Name:               "policy1",
  3302  				Database:           "testdb",
  3303  				Duration:           time.Hour,
  3304  				Replication:        2,
  3305  				ShardGroupDuration: 0,
  3306  			},
  3307  		},
  3308  		{
  3309  			s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION 2 SHARD DURATION 1s`,
  3310  			stmt: &influxql.CreateRetentionPolicyStatement{
  3311  				Name:               "policy1",
  3312  				Database:           "testdb",
  3313  				Duration:           time.Hour,
  3314  				Replication:        2,
  3315  				ShardGroupDuration: time.Second,
  3316  			},
  3317  		},
  3318  
  3319  		// ALTER RETENTION POLICY
  3320  		{
  3321  			s:    `ALTER RETENTION POLICY policy1 ON testdb DURATION 1m REPLICATION 4 DEFAULT`,
  3322  			stmt: newAlterRetentionPolicyStatement("policy1", "testdb", time.Minute, -1, 4, true),
  3323  		},
  3324  
  3325  		// ALTER RETENTION POLICY with options in reverse order
  3326  		{
  3327  			s:    `ALTER RETENTION POLICY policy1 ON testdb DEFAULT REPLICATION 4 DURATION 1m`,
  3328  			stmt: newAlterRetentionPolicyStatement("policy1", "testdb", time.Minute, -1, 4, true),
  3329  		},
  3330  
  3331  		// ALTER RETENTION POLICY with infinite retention
  3332  		{
  3333  			s:    `ALTER RETENTION POLICY policy1 ON testdb DEFAULT REPLICATION 4 DURATION INF`,
  3334  			stmt: newAlterRetentionPolicyStatement("policy1", "testdb", 0, -1, 4, true),
  3335  		},
  3336  
  3337  		// ALTER RETENTION POLICY without optional DURATION
  3338  		{
  3339  			s:    `ALTER RETENTION POLICY policy1 ON testdb DEFAULT REPLICATION 4`,
  3340  			stmt: newAlterRetentionPolicyStatement("policy1", "testdb", -1, -1, 4, true),
  3341  		},
  3342  
  3343  		// ALTER RETENTION POLICY without optional REPLICATION
  3344  		{
  3345  			s:    `ALTER RETENTION POLICY policy1 ON testdb DEFAULT`,
  3346  			stmt: newAlterRetentionPolicyStatement("policy1", "testdb", -1, -1, -1, true),
  3347  		},
  3348  
  3349  		// ALTER RETENTION POLICY without optional DEFAULT
  3350  		{
  3351  			s:    `ALTER RETENTION POLICY policy1 ON testdb REPLICATION 4`,
  3352  			stmt: newAlterRetentionPolicyStatement("policy1", "testdb", -1, -1, 4, false),
  3353  		},
  3354  		// ALTER default retention policy unquoted
  3355  		{
  3356  			s:    `ALTER RETENTION POLICY default ON testdb REPLICATION 4`,
  3357  			stmt: newAlterRetentionPolicyStatement("default", "testdb", -1, -1, 4, false),
  3358  		},
  3359  		// ALTER RETENTION POLICY with SHARD duration
  3360  		{
  3361  			s:    `ALTER RETENTION POLICY policy1 ON testdb REPLICATION 4 SHARD DURATION 10m`,
  3362  			stmt: newAlterRetentionPolicyStatement("policy1", "testdb", -1, 10*time.Minute, 4, false),
  3363  		},
  3364  		// ALTER RETENTION POLICY with all options
  3365  		{
  3366  			s:    `ALTER RETENTION POLICY default ON testdb DURATION 0s REPLICATION 4 SHARD DURATION 10m DEFAULT`,
  3367  			stmt: newAlterRetentionPolicyStatement("default", "testdb", time.Duration(0), 10*time.Minute, 4, true),
  3368  		},
  3369  		// ALTER RETENTION POLICY with 0s shard duration
  3370  		{
  3371  			s:    `ALTER RETENTION POLICY default ON testdb DURATION 0s REPLICATION 1 SHARD DURATION 0s`,
  3372  			stmt: newAlterRetentionPolicyStatement("default", "testdb", time.Duration(0), 0, 1, false),
  3373  		},
  3374  
  3375  		// SHOW STATS
  3376  		{
  3377  			s: `SHOW STATS`,
  3378  			stmt: &influxql.ShowStatsStatement{
  3379  				Module: "",
  3380  			},
  3381  		},
  3382  		{
  3383  			s: `SHOW STATS FOR 'cluster'`,
  3384  			stmt: &influxql.ShowStatsStatement{
  3385  				Module: "cluster",
  3386  			},
  3387  		},
  3388  
  3389  		// SHOW SHARD GROUPS
  3390  		{
  3391  			s:    `SHOW SHARD GROUPS`,
  3392  			stmt: &influxql.ShowShardGroupsStatement{},
  3393  		},
  3394  
  3395  		// SHOW SHARDS
  3396  		{
  3397  			s:    `SHOW SHARDS`,
  3398  			stmt: &influxql.ShowShardsStatement{},
  3399  		},
  3400  
  3401  		// SHOW DIAGNOSTICS
  3402  		{
  3403  			s:    `SHOW DIAGNOSTICS`,
  3404  			stmt: &influxql.ShowDiagnosticsStatement{},
  3405  		},
  3406  		{
  3407  			s: `SHOW DIAGNOSTICS FOR 'build'`,
  3408  			stmt: &influxql.ShowDiagnosticsStatement{
  3409  				Module: "build",
  3410  			},
  3411  		},
  3412  
  3413  		// CREATE SUBSCRIPTION
  3414  		{
  3415  			s: `CREATE SUBSCRIPTION "name" ON "db"."rp" DESTINATIONS ANY 'udp://host1:9093', 'udp://host2:9093'`,
  3416  			stmt: &influxql.CreateSubscriptionStatement{
  3417  				Name:            "name",
  3418  				Database:        "db",
  3419  				RetentionPolicy: "rp",
  3420  				Destinations:    []string{"udp://host1:9093", "udp://host2:9093"},
  3421  				Mode:            "ANY",
  3422  			},
  3423  		},
  3424  
  3425  		// DROP SUBSCRIPTION
  3426  		{
  3427  			s: `DROP SUBSCRIPTION "name" ON "db"."rp"`,
  3428  			stmt: &influxql.DropSubscriptionStatement{
  3429  				Name:            "name",
  3430  				Database:        "db",
  3431  				RetentionPolicy: "rp",
  3432  			},
  3433  		},
  3434  
  3435  		// SHOW SUBSCRIPTIONS
  3436  		{
  3437  			s:    `SHOW SUBSCRIPTIONS`,
  3438  			stmt: &influxql.ShowSubscriptionsStatement{},
  3439  		},
  3440  
  3441  		// Errors
  3442  		{s: ``, err: `found EOF, expected SELECT, DELETE, SHOW, CREATE, DROP, EXPLAIN, GRANT, REVOKE, ALTER, SET, KILL at line 1, char 1`},
  3443  		{s: `SELECT`, err: `found EOF, expected identifier, string, number, bool at line 1, char 8`},
  3444  		{s: `blah blah`, err: `found blah, expected SELECT, DELETE, SHOW, CREATE, DROP, EXPLAIN, GRANT, REVOKE, ALTER, SET, KILL at line 1, char 1`},
  3445  		{s: `SELECT field1 X`, err: `found X, expected FROM at line 1, char 15`},
  3446  		{s: `SELECT field1 FROM "series" WHERE X +;`, err: `found ;, expected identifier, string, number, bool at line 1, char 38`},
  3447  		{s: `SELECT field1 FROM myseries GROUP`, err: `found EOF, expected BY at line 1, char 35`},
  3448  		{s: `SELECT field1 FROM myseries LIMIT`, err: `found EOF, expected integer at line 1, char 35`},
  3449  		{s: `SELECT field1 FROM myseries LIMIT 10.5`, err: `found 10.5, expected integer at line 1, char 35`},
  3450  		{s: `SELECT field1 FROM myseries OFFSET`, err: `found EOF, expected integer at line 1, char 36`},
  3451  		{s: `SELECT field1 FROM myseries OFFSET 10.5`, err: `found 10.5, expected integer at line 1, char 36`},
  3452  		{s: `SELECT field1 FROM myseries ORDER`, err: `found EOF, expected BY at line 1, char 35`},
  3453  		{s: `SELECT field1 FROM myseries ORDER BY`, err: `found EOF, expected identifier, ASC, DESC at line 1, char 38`},
  3454  		{s: `SELECT field1 FROM myseries ORDER BY /`, err: `found /, expected identifier, ASC, DESC at line 1, char 38`},
  3455  		{s: `SELECT field1 FROM myseries ORDER BY 1`, err: `found 1, expected identifier, ASC, DESC at line 1, char 38`},
  3456  		{s: `SELECT field1 FROM myseries ORDER BY time ASC,`, err: `found EOF, expected identifier at line 1, char 47`},
  3457  		{s: `SELECT field1 FROM myseries ORDER BY time, field1`, err: `only ORDER BY time supported at this time`},
  3458  		{s: `SELECT field1 AS`, err: `found EOF, expected identifier at line 1, char 18`},
  3459  		{s: `SELECT field1 FROM 12`, err: `found 12, expected identifier at line 1, char 20`},
  3460  		{s: `SELECT 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 FROM myseries`, err: `unable to parse integer at line 1, char 8`},
  3461  		{s: `SELECT 10.5h FROM myseries`, err: `found h, expected FROM at line 1, char 12`},
  3462  		{s: `SELECT distinct FROM myseries`, err: `found FROM, expected identifier at line 1, char 17`},
  3463  		{s: `SELECT count(distinct) FROM myseries`, err: `found ), expected (, identifier at line 1, char 22`},
  3464  		{s: `SELECT field1 from myseries WHERE host =~ 'asd' LIMIT 1`, err: `found asd, expected regex at line 1, char 42`},
  3465  		{s: `SELECT value > 2 FROM cpu`, err: `invalid operator > in SELECT clause at line 1, char 8; operator is intended for WHERE clause`},
  3466  		{s: `SELECT value = 2 FROM cpu`, err: `invalid operator = in SELECT clause at line 1, char 8; operator is intended for WHERE clause`},
  3467  		{s: `SELECT s =~ /foo/ FROM cpu`, err: `invalid operator =~ in SELECT clause at line 1, char 8; operator is intended for WHERE clause`},
  3468  		{s: `SELECT mean(value) FROM cpu FILL + value`, err: `fill must be a function call`},
  3469  		// See issues https://github.com/influxdata/influxdb/issues/1647
  3470  		// and https://github.com/influxdata/influxdb/issues/4404
  3471  		//{s: `DELETE`, err: `found EOF, expected FROM at line 1, char 8`},
  3472  		//{s: `DELETE FROM`, err: `found EOF, expected identifier at line 1, char 13`},
  3473  		//{s: `DELETE FROM myseries WHERE`, err: `found EOF, expected identifier, string, number, bool at line 1, char 28`},
  3474  		{s: `DELETE`, err: `found EOF, expected FROM, WHERE at line 1, char 8`},
  3475  		{s: `DELETE FROM`, err: `found EOF, expected identifier at line 1, char 13`},
  3476  		{s: `DELETE FROM myseries WHERE`, err: `found EOF, expected identifier, string, number, bool at line 1, char 28`},
  3477  		{s: `DELETE FROM "foo".myseries`, err: `retention policy not supported at line 1, char 1`},
  3478  		{s: `DELETE FROM foo..myseries`, err: `database not supported at line 1, char 1`},
  3479  		{s: `DROP MEASUREMENT`, err: `found EOF, expected identifier at line 1, char 18`},
  3480  		{s: `DROP SERIES`, err: `found EOF, expected FROM, WHERE at line 1, char 13`},
  3481  		{s: `DROP SERIES FROM`, err: `found EOF, expected identifier at line 1, char 18`},
  3482  		{s: `DROP SERIES FROM src WHERE`, err: `found EOF, expected identifier, string, number, bool at line 1, char 28`},
  3483  		{s: `DROP SERIES FROM "foo".myseries`, err: `retention policy not supported at line 1, char 1`},
  3484  		{s: `DROP SERIES FROM foo..myseries`, err: `database not supported at line 1, char 1`},
  3485  		{s: `SHOW CONTINUOUS`, err: `found EOF, expected QUERIES at line 1, char 17`},
  3486  		{s: `SHOW RETENTION`, err: `found EOF, expected POLICIES at line 1, char 16`},
  3487  		{s: `SHOW RETENTION ON`, err: `found ON, expected POLICIES at line 1, char 16`},
  3488  		{s: `SHOW RETENTION POLICIES ON`, err: `found EOF, expected identifier at line 1, char 28`},
  3489  		{s: `SHOW SHARD`, err: `found EOF, expected GROUPS at line 1, char 12`},
  3490  		{s: `SHOW FOO`, err: `found FOO, expected CONTINUOUS, DATABASES, DIAGNOSTICS, FIELD, GRANTS, MEASUREMENT, MEASUREMENTS, QUERIES, RETENTION, SERIES, SHARD, SHARDS, STATS, SUBSCRIPTIONS, TAG, USERS at line 1, char 6`},
  3491  		{s: `SHOW STATS FOR`, err: `found EOF, expected string at line 1, char 16`},
  3492  		{s: `SHOW DIAGNOSTICS FOR`, err: `found EOF, expected string at line 1, char 22`},
  3493  		{s: `SHOW GRANTS`, err: `found EOF, expected FOR at line 1, char 13`},
  3494  		{s: `SHOW GRANTS FOR`, err: `found EOF, expected identifier at line 1, char 17`},
  3495  		{s: `DROP CONTINUOUS`, err: `found EOF, expected QUERY at line 1, char 17`},
  3496  		{s: `DROP CONTINUOUS QUERY`, err: `found EOF, expected identifier at line 1, char 23`},
  3497  		{s: `DROP CONTINUOUS QUERY myquery`, err: `found EOF, expected ON at line 1, char 31`},
  3498  		{s: `DROP CONTINUOUS QUERY myquery ON`, err: `found EOF, expected identifier at line 1, char 34`},
  3499  		{s: `CREATE CONTINUOUS`, err: `found EOF, expected QUERY at line 1, char 19`},
  3500  		{s: `CREATE CONTINUOUS QUERY`, err: `found EOF, expected identifier at line 1, char 25`},
  3501  		{s: `CREATE CONTINUOUS QUERY cq ON db RESAMPLE FOR 5s BEGIN SELECT mean(value) INTO cpu_mean FROM cpu GROUP BY time(10s) END`, err: `FOR duration must be >= GROUP BY time duration: must be a minimum of 10s, got 5s`},
  3502  		{s: `CREATE CONTINUOUS QUERY cq ON db RESAMPLE EVERY 10s FOR 5s BEGIN SELECT mean(value) INTO cpu_mean FROM cpu GROUP BY time(5s) END`, err: `FOR duration must be >= GROUP BY time duration: must be a minimum of 10s, got 5s`},
  3503  		{s: `DROP FOO`, err: `found FOO, expected CONTINUOUS, DATABASE, MEASUREMENT, RETENTION, SERIES, SHARD, SUBSCRIPTION, USER at line 1, char 6`},
  3504  		{s: `CREATE FOO`, err: `found FOO, expected CONTINUOUS, DATABASE, USER, RETENTION, SUBSCRIPTION at line 1, char 8`},
  3505  		{s: `CREATE DATABASE`, err: `found EOF, expected identifier at line 1, char 17`},
  3506  		{s: `CREATE DATABASE "testdb" WITH`, err: `found EOF, expected DURATION, NAME, REPLICATION, SHARD at line 1, char 31`},
  3507  		{s: `CREATE DATABASE "testdb" WITH DURATION`, err: `found EOF, expected duration at line 1, char 40`},
  3508  		{s: `CREATE DATABASE "testdb" WITH REPLICATION`, err: `found EOF, expected integer at line 1, char 43`},
  3509  		{s: `CREATE DATABASE "testdb" WITH NAME`, err: `found EOF, expected identifier at line 1, char 36`},
  3510  		{s: `CREATE DATABASE "testdb" WITH SHARD`, err: `found EOF, expected DURATION at line 1, char 37`},
  3511  		{s: `DROP DATABASE`, err: `found EOF, expected identifier at line 1, char 15`},
  3512  		{s: `DROP RETENTION`, err: `found EOF, expected POLICY at line 1, char 16`},
  3513  		{s: `DROP RETENTION POLICY`, err: `found EOF, expected identifier at line 1, char 23`},
  3514  		{s: `DROP RETENTION POLICY "1h.cpu"`, err: `found EOF, expected ON at line 1, char 31`},
  3515  		{s: `DROP RETENTION POLICY "1h.cpu" ON`, err: `found EOF, expected identifier at line 1, char 35`},
  3516  		{s: `DROP USER`, err: `found EOF, expected identifier at line 1, char 11`},
  3517  		{s: `DROP SUBSCRIPTION`, err: `found EOF, expected identifier at line 1, char 19`},
  3518  		{s: `DROP SUBSCRIPTION "name"`, err: `found EOF, expected ON at line 1, char 25`},
  3519  		{s: `DROP SUBSCRIPTION "name" ON `, err: `found EOF, expected identifier at line 1, char 30`},
  3520  		{s: `DROP SUBSCRIPTION "name" ON "db"`, err: `found EOF, expected . at line 1, char 33`},
  3521  		{s: `DROP SUBSCRIPTION "name" ON "db".`, err: `found EOF, expected identifier at line 1, char 34`},
  3522  		{s: `CREATE USER testuser`, err: `found EOF, expected WITH at line 1, char 22`},
  3523  		{s: `CREATE USER testuser WITH`, err: `found EOF, expected PASSWORD at line 1, char 27`},
  3524  		{s: `CREATE USER testuser WITH PASSWORD`, err: `found EOF, expected string at line 1, char 36`},
  3525  		{s: `CREATE USER testuser WITH PASSWORD 'pwd' WITH`, err: `found EOF, expected ALL at line 1, char 47`},
  3526  		{s: `CREATE USER testuser WITH PASSWORD 'pwd' WITH ALL`, err: `found EOF, expected PRIVILEGES at line 1, char 51`},
  3527  		{s: `CREATE SUBSCRIPTION`, err: `found EOF, expected identifier at line 1, char 21`},
  3528  		{s: `CREATE SUBSCRIPTION "name"`, err: `found EOF, expected ON at line 1, char 27`},
  3529  		{s: `CREATE SUBSCRIPTION "name" ON `, err: `found EOF, expected identifier at line 1, char 32`},
  3530  		{s: `CREATE SUBSCRIPTION "name" ON "db"`, err: `found EOF, expected . at line 1, char 35`},
  3531  		{s: `CREATE SUBSCRIPTION "name" ON "db".`, err: `found EOF, expected identifier at line 1, char 36`},
  3532  		{s: `CREATE SUBSCRIPTION "name" ON "db"."rp"`, err: `found EOF, expected DESTINATIONS at line 1, char 40`},
  3533  		{s: `CREATE SUBSCRIPTION "name" ON "db"."rp" DESTINATIONS`, err: `found EOF, expected ALL, ANY at line 1, char 54`},
  3534  		{s: `CREATE SUBSCRIPTION "name" ON "db"."rp" DESTINATIONS ALL `, err: `found EOF, expected string at line 1, char 59`},
  3535  		{s: `GRANT`, err: `found EOF, expected READ, WRITE, ALL [PRIVILEGES] at line 1, char 7`},
  3536  		{s: `GRANT BOGUS`, err: `found BOGUS, expected READ, WRITE, ALL [PRIVILEGES] at line 1, char 7`},
  3537  		{s: `GRANT READ`, err: `found EOF, expected ON at line 1, char 12`},
  3538  		{s: `GRANT READ FROM`, err: `found FROM, expected ON at line 1, char 12`},
  3539  		{s: `GRANT READ ON`, err: `found EOF, expected identifier at line 1, char 15`},
  3540  		{s: `GRANT READ ON TO`, err: `found TO, expected identifier at line 1, char 15`},
  3541  		{s: `GRANT READ ON testdb`, err: `found EOF, expected TO at line 1, char 22`},
  3542  		{s: `GRANT READ ON testdb TO`, err: `found EOF, expected identifier at line 1, char 25`},
  3543  		{s: `GRANT READ TO`, err: `found TO, expected ON at line 1, char 12`},
  3544  		{s: `GRANT WRITE`, err: `found EOF, expected ON at line 1, char 13`},
  3545  		{s: `GRANT WRITE FROM`, err: `found FROM, expected ON at line 1, char 13`},
  3546  		{s: `GRANT WRITE ON`, err: `found EOF, expected identifier at line 1, char 16`},
  3547  		{s: `GRANT WRITE ON TO`, err: `found TO, expected identifier at line 1, char 16`},
  3548  		{s: `GRANT WRITE ON testdb`, err: `found EOF, expected TO at line 1, char 23`},
  3549  		{s: `GRANT WRITE ON testdb TO`, err: `found EOF, expected identifier at line 1, char 26`},
  3550  		{s: `GRANT WRITE TO`, err: `found TO, expected ON at line 1, char 13`},
  3551  		{s: `GRANT ALL`, err: `found EOF, expected ON, TO at line 1, char 11`},
  3552  		{s: `GRANT ALL PRIVILEGES`, err: `found EOF, expected ON, TO at line 1, char 22`},
  3553  		{s: `GRANT ALL FROM`, err: `found FROM, expected ON, TO at line 1, char 11`},
  3554  		{s: `GRANT ALL PRIVILEGES FROM`, err: `found FROM, expected ON, TO at line 1, char 22`},
  3555  		{s: `GRANT ALL ON`, err: `found EOF, expected identifier at line 1, char 14`},
  3556  		{s: `GRANT ALL PRIVILEGES ON`, err: `found EOF, expected identifier at line 1, char 25`},
  3557  		{s: `GRANT ALL ON TO`, err: `found TO, expected identifier at line 1, char 14`},
  3558  		{s: `GRANT ALL PRIVILEGES ON TO`, err: `found TO, expected identifier at line 1, char 25`},
  3559  		{s: `GRANT ALL ON testdb`, err: `found EOF, expected TO at line 1, char 21`},
  3560  		{s: `GRANT ALL PRIVILEGES ON testdb`, err: `found EOF, expected TO at line 1, char 32`},
  3561  		{s: `GRANT ALL ON testdb FROM`, err: `found FROM, expected TO at line 1, char 21`},
  3562  		{s: `GRANT ALL PRIVILEGES ON testdb FROM`, err: `found FROM, expected TO at line 1, char 32`},
  3563  		{s: `GRANT ALL ON testdb TO`, err: `found EOF, expected identifier at line 1, char 24`},
  3564  		{s: `GRANT ALL PRIVILEGES ON testdb TO`, err: `found EOF, expected identifier at line 1, char 35`},
  3565  		{s: `GRANT ALL TO`, err: `found EOF, expected identifier at line 1, char 14`},
  3566  		{s: `GRANT ALL PRIVILEGES TO`, err: `found EOF, expected identifier at line 1, char 25`},
  3567  		{s: `KILL`, err: `found EOF, expected QUERY at line 1, char 6`},
  3568  		{s: `KILL QUERY 10s`, err: `found 10s, expected integer at line 1, char 12`},
  3569  		{s: `KILL QUERY 4 ON 'host'`, err: `found host, expected identifier at line 1, char 16`},
  3570  		{s: `REVOKE`, err: `found EOF, expected READ, WRITE, ALL [PRIVILEGES] at line 1, char 8`},
  3571  		{s: `REVOKE BOGUS`, err: `found BOGUS, expected READ, WRITE, ALL [PRIVILEGES] at line 1, char 8`},
  3572  		{s: `REVOKE READ`, err: `found EOF, expected ON at line 1, char 13`},
  3573  		{s: `REVOKE READ TO`, err: `found TO, expected ON at line 1, char 13`},
  3574  		{s: `REVOKE READ ON`, err: `found EOF, expected identifier at line 1, char 16`},
  3575  		{s: `REVOKE READ ON FROM`, err: `found FROM, expected identifier at line 1, char 16`},
  3576  		{s: `REVOKE READ ON testdb`, err: `found EOF, expected FROM at line 1, char 23`},
  3577  		{s: `REVOKE READ ON testdb FROM`, err: `found EOF, expected identifier at line 1, char 28`},
  3578  		{s: `REVOKE READ FROM`, err: `found FROM, expected ON at line 1, char 13`},
  3579  		{s: `REVOKE WRITE`, err: `found EOF, expected ON at line 1, char 14`},
  3580  		{s: `REVOKE WRITE TO`, err: `found TO, expected ON at line 1, char 14`},
  3581  		{s: `REVOKE WRITE ON`, err: `found EOF, expected identifier at line 1, char 17`},
  3582  		{s: `REVOKE WRITE ON FROM`, err: `found FROM, expected identifier at line 1, char 17`},
  3583  		{s: `REVOKE WRITE ON testdb`, err: `found EOF, expected FROM at line 1, char 24`},
  3584  		{s: `REVOKE WRITE ON testdb FROM`, err: `found EOF, expected identifier at line 1, char 29`},
  3585  		{s: `REVOKE WRITE FROM`, err: `found FROM, expected ON at line 1, char 14`},
  3586  		{s: `REVOKE ALL`, err: `found EOF, expected ON, FROM at line 1, char 12`},
  3587  		{s: `REVOKE ALL PRIVILEGES`, err: `found EOF, expected ON, FROM at line 1, char 23`},
  3588  		{s: `REVOKE ALL TO`, err: `found TO, expected ON, FROM at line 1, char 12`},
  3589  		{s: `REVOKE ALL PRIVILEGES TO`, err: `found TO, expected ON, FROM at line 1, char 23`},
  3590  		{s: `REVOKE ALL ON`, err: `found EOF, expected identifier at line 1, char 15`},
  3591  		{s: `REVOKE ALL PRIVILEGES ON`, err: `found EOF, expected identifier at line 1, char 26`},
  3592  		{s: `REVOKE ALL ON FROM`, err: `found FROM, expected identifier at line 1, char 15`},
  3593  		{s: `REVOKE ALL PRIVILEGES ON FROM`, err: `found FROM, expected identifier at line 1, char 26`},
  3594  		{s: `REVOKE ALL ON testdb`, err: `found EOF, expected FROM at line 1, char 22`},
  3595  		{s: `REVOKE ALL PRIVILEGES ON testdb`, err: `found EOF, expected FROM at line 1, char 33`},
  3596  		{s: `REVOKE ALL ON testdb TO`, err: `found TO, expected FROM at line 1, char 22`},
  3597  		{s: `REVOKE ALL PRIVILEGES ON testdb TO`, err: `found TO, expected FROM at line 1, char 33`},
  3598  		{s: `REVOKE ALL ON testdb FROM`, err: `found EOF, expected identifier at line 1, char 27`},
  3599  		{s: `REVOKE ALL PRIVILEGES ON testdb FROM`, err: `found EOF, expected identifier at line 1, char 38`},
  3600  		{s: `REVOKE ALL FROM`, err: `found EOF, expected identifier at line 1, char 17`},
  3601  		{s: `REVOKE ALL PRIVILEGES FROM`, err: `found EOF, expected identifier at line 1, char 28`},
  3602  		{s: `CREATE RETENTION`, err: `found EOF, expected POLICY at line 1, char 18`},
  3603  		{s: `CREATE RETENTION POLICY`, err: `found EOF, expected identifier at line 1, char 25`},
  3604  		{s: `CREATE RETENTION POLICY policy1`, err: `found EOF, expected ON at line 1, char 33`},
  3605  		{s: `CREATE RETENTION POLICY policy1 ON`, err: `found EOF, expected identifier at line 1, char 36`},
  3606  		{s: `CREATE RETENTION POLICY policy1 ON testdb`, err: `found EOF, expected DURATION at line 1, char 43`},
  3607  		{s: `CREATE RETENTION POLICY policy1 ON testdb DURATION`, err: `found EOF, expected duration at line 1, char 52`},
  3608  		{s: `CREATE RETENTION POLICY policy1 ON testdb DURATION bad`, err: `found bad, expected duration at line 1, char 52`},
  3609  		{s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 1h`, err: `found EOF, expected REPLICATION at line 1, char 54`},
  3610  		{s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION`, err: `found EOF, expected integer at line 1, char 67`},
  3611  		{s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION 3.14`, err: `found 3.14, expected integer at line 1, char 67`},
  3612  		{s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION 0`, err: `invalid value 0: must be 1 <= n <= 2147483647 at line 1, char 67`},
  3613  		{s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION bad`, err: `found bad, expected integer at line 1, char 67`},
  3614  		{s: `CREATE RETENTION POLICY policy1 ON testdb DURATION 1h REPLICATION 2 SHARD DURATION INF`, err: `invalid duration INF for shard duration at line 1, char 84`},
  3615  		{s: `ALTER`, err: `found EOF, expected RETENTION at line 1, char 7`},
  3616  		{s: `ALTER RETENTION`, err: `found EOF, expected POLICY at line 1, char 17`},
  3617  		{s: `ALTER RETENTION POLICY`, err: `found EOF, expected identifier at line 1, char 24`},
  3618  		{s: `ALTER RETENTION POLICY policy1`, err: `found EOF, expected ON at line 1, char 32`}, {s: `ALTER RETENTION POLICY policy1 ON`, err: `found EOF, expected identifier at line 1, char 35`},
  3619  		{s: `ALTER RETENTION POLICY policy1 ON testdb`, err: `found EOF, expected DURATION, REPLICATION, SHARD, DEFAULT at line 1, char 42`},
  3620  		{s: `ALTER RETENTION POLICY policy1 ON testdb REPLICATION 1 REPLICATION 2`, err: `found duplicate REPLICATION option at line 1, char 56`},
  3621  		{s: `ALTER RETENTION POLICY policy1 ON testdb DURATION 15251w`, err: `overflowed duration 15251w: choose a smaller duration or INF at line 1, char 51`},
  3622  		{s: `ALTER RETENTION POLICY policy1 ON testdb DURATION INF SHARD DURATION INF`, err: `invalid duration INF for shard duration at line 1, char 70`},
  3623  		{s: `SET`, err: `found EOF, expected PASSWORD at line 1, char 5`},
  3624  		{s: `SET PASSWORD`, err: `found EOF, expected FOR at line 1, char 14`},
  3625  		{s: `SET PASSWORD something`, err: `found something, expected FOR at line 1, char 14`},
  3626  		{s: `SET PASSWORD FOR`, err: `found EOF, expected identifier at line 1, char 18`},
  3627  		{s: `SET PASSWORD FOR dejan`, err: `found EOF, expected = at line 1, char 24`},
  3628  		{s: `SET PASSWORD FOR dejan =`, err: `found EOF, expected string at line 1, char 25`},
  3629  		{s: `SET PASSWORD FOR dejan = bla`, err: `found bla, expected string at line 1, char 26`},
  3630  		{s: `$SHOW$DATABASES`, err: `found $SHOW, expected SELECT, DELETE, SHOW, CREATE, DROP, EXPLAIN, GRANT, REVOKE, ALTER, SET, KILL at line 1, char 1`},
  3631  		{s: `SELECT * FROM cpu WHERE "tagkey" = $$`, err: `empty bound parameter`},
  3632  
  3633  		// Create a database with a bound parameter.
  3634  		{
  3635  			s: `CREATE DATABASE $db`,
  3636  			params: map[string]interface{}{
  3637  				"db": map[string]interface{}{"identifier": "mydb"},
  3638  			},
  3639  			stmt: &influxql.CreateDatabaseStatement{
  3640  				Name: "mydb",
  3641  			},
  3642  		},
  3643  
  3644  		// Count records in a measurement.
  3645  		{
  3646  			s: `SELECT count($value) FROM $m`,
  3647  			params: map[string]interface{}{
  3648  				"value": map[string]interface{}{"identifier": "my_value"},
  3649  				"m":     map[string]interface{}{"identifier": "my_measurement"},
  3650  			},
  3651  			stmt: &influxql.SelectStatement{
  3652  				Fields: []*influxql.Field{{
  3653  					Expr: &influxql.Call{
  3654  						Name: "count",
  3655  						Args: []influxql.Expr{
  3656  							&influxql.VarRef{Val: "my_value"},
  3657  						}}},
  3658  				},
  3659  				Sources: []influxql.Source{&influxql.Measurement{Name: "my_measurement"}},
  3660  			},
  3661  		},
  3662  
  3663  		// Find the last 10 shapes records.
  3664  		{
  3665  			s: `SELECT * FROM $m LIMIT $limit`,
  3666  			params: map[string]interface{}{
  3667  				"m":     map[string]interface{}{"identifier": "shapes"},
  3668  				"limit": int64(10),
  3669  			},
  3670  			stmt: &influxql.SelectStatement{
  3671  				IsRawQuery: true,
  3672  				Fields: []*influxql.Field{{
  3673  					Expr: &influxql.Wildcard{},
  3674  				}},
  3675  				Sources: []influxql.Source{&influxql.Measurement{Name: "shapes"}},
  3676  				Limit:   10,
  3677  			},
  3678  		},
  3679  
  3680  		// Find the last 10 shapes records (advanced syntax).
  3681  		{
  3682  			s: `SELECT * FROM $m LIMIT $limit`,
  3683  			params: map[string]interface{}{
  3684  				"m":     map[string]interface{}{"identifier": "shapes"},
  3685  				"limit": map[string]interface{}{"integer": json.Number("10")},
  3686  			},
  3687  			stmt: &influxql.SelectStatement{
  3688  				IsRawQuery: true,
  3689  				Fields: []*influxql.Field{{
  3690  					Expr: &influxql.Wildcard{},
  3691  				}},
  3692  				Sources: []influxql.Source{&influxql.Measurement{Name: "shapes"}},
  3693  				Limit:   10,
  3694  			},
  3695  		},
  3696  	}
  3697  
  3698  	for i, tt := range tests {
  3699  		if tt.skip {
  3700  			continue
  3701  		}
  3702  		p := influxql.NewParser(strings.NewReader(tt.s))
  3703  		if tt.params != nil {
  3704  			p.SetParams(tt.params)
  3705  		}
  3706  		stmt, err := p.ParseStatement()
  3707  
  3708  		// if it's a CQ, there is a non-exported field that gets memoized during parsing that needs to be set
  3709  		if st, ok := stmt.(*influxql.CreateContinuousQueryStatement); ok {
  3710  			if st != nil && st.Source != nil {
  3711  				tt.stmt.(*influxql.CreateContinuousQueryStatement).Source.GroupByInterval()
  3712  			}
  3713  		}
  3714  
  3715  		if !reflect.DeepEqual(tt.err, errstring(err)) {
  3716  			t.Errorf("%d. %q: error mismatch:\n  exp=%s\n  got=%s\n\n", i, tt.s, tt.err, err)
  3717  		} else if tt.err == "" {
  3718  			if !reflect.DeepEqual(tt.stmt, stmt) {
  3719  				t.Logf("\n# %s\nexp=%s\ngot=%s\n", tt.s, mustMarshalJSON(tt.stmt), mustMarshalJSON(stmt))
  3720  				t.Logf("\nSQL exp=%s\nSQL got=%s\n", tt.stmt.String(), stmt.String())
  3721  				t.Errorf("%d. %q\n\nstmt mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.stmt, stmt)
  3722  			} else {
  3723  				// Attempt to reparse the statement as a string and confirm it parses the same.
  3724  				// Skip this if we have some kind of statement with a password since those will never be reparsed.
  3725  				switch stmt.(type) {
  3726  				case *influxql.CreateUserStatement, *influxql.SetPasswordUserStatement:
  3727  					continue
  3728  				}
  3729  
  3730  				stmt2, err := influxql.ParseStatement(stmt.String())
  3731  				if err != nil {
  3732  					t.Errorf("%d. %q: unable to parse statement string: %s", i, stmt.String(), err)
  3733  				} else if !reflect.DeepEqual(tt.stmt, stmt2) {
  3734  					t.Logf("\n# %s\nexp=%s\ngot=%s\n", tt.s, mustMarshalJSON(tt.stmt), mustMarshalJSON(stmt2))
  3735  					t.Logf("\nSQL exp=%s\nSQL got=%s\n", tt.stmt.String(), stmt2.String())
  3736  					t.Errorf("%d. %q\n\nstmt reparse mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.stmt, stmt2)
  3737  				}
  3738  			}
  3739  		}
  3740  	}
  3741  }
  3742  
  3743  // Ensure the parser can parse expressions into an AST.
  3744  func TestParser_ParseExpr(t *testing.T) {
  3745  	var tests = []struct {
  3746  		s    string
  3747  		expr influxql.Expr
  3748  		err  string
  3749  	}{
  3750  		// Primitives
  3751  		{s: `100.0`, expr: &influxql.NumberLiteral{Val: 100}},
  3752  		{s: `100`, expr: &influxql.IntegerLiteral{Val: 100}},
  3753  		{s: `9223372036854775808`, expr: &influxql.UnsignedLiteral{Val: 9223372036854775808}},
  3754  		{s: `-9223372036854775808`, expr: &influxql.IntegerLiteral{Val: -9223372036854775808}},
  3755  		{s: `-9223372036854775809`, err: `constant -9223372036854775809 underflows int64`},
  3756  		{s: `-100.0`, expr: &influxql.NumberLiteral{Val: -100}},
  3757  		{s: `-100`, expr: &influxql.IntegerLiteral{Val: -100}},
  3758  		{s: `100.`, expr: &influxql.NumberLiteral{Val: 100}},
  3759  		{s: `-100.`, expr: &influxql.NumberLiteral{Val: -100}},
  3760  		{s: `.23`, expr: &influxql.NumberLiteral{Val: 0.23}},
  3761  		{s: `-.23`, expr: &influxql.NumberLiteral{Val: -0.23}},
  3762  		{s: `1s`, expr: &influxql.DurationLiteral{Val: time.Second}},
  3763  		{s: `-1s`, expr: &influxql.DurationLiteral{Val: -time.Second}},
  3764  		{s: `-+1`, err: `found +, expected identifier, number, duration, ( at line 1, char 2`},
  3765  		{s: `'foo bar'`, expr: &influxql.StringLiteral{Val: "foo bar"}},
  3766  		{s: `true`, expr: &influxql.BooleanLiteral{Val: true}},
  3767  		{s: `false`, expr: &influxql.BooleanLiteral{Val: false}},
  3768  		{s: `my_ident`, expr: &influxql.VarRef{Val: "my_ident"}},
  3769  		{s: `'2000-01-01 00:00:00'`, expr: &influxql.StringLiteral{Val: "2000-01-01 00:00:00"}},
  3770  		{s: `'2000-01-01'`, expr: &influxql.StringLiteral{Val: "2000-01-01"}},
  3771  
  3772  		// Simple binary expression
  3773  		{
  3774  			s: `1 + 2`,
  3775  			expr: &influxql.BinaryExpr{
  3776  				Op:  influxql.ADD,
  3777  				LHS: &influxql.IntegerLiteral{Val: 1},
  3778  				RHS: &influxql.IntegerLiteral{Val: 2},
  3779  			},
  3780  		},
  3781  
  3782  		// Binary expression with LHS precedence
  3783  		{
  3784  			s: `1 * 2 + 3`,
  3785  			expr: &influxql.BinaryExpr{
  3786  				Op: influxql.ADD,
  3787  				LHS: &influxql.BinaryExpr{
  3788  					Op:  influxql.MUL,
  3789  					LHS: &influxql.IntegerLiteral{Val: 1},
  3790  					RHS: &influxql.IntegerLiteral{Val: 2},
  3791  				},
  3792  				RHS: &influxql.IntegerLiteral{Val: 3},
  3793  			},
  3794  		},
  3795  
  3796  		// Binary expression with RHS precedence
  3797  		{
  3798  			s: `1 + 2 * 3`,
  3799  			expr: &influxql.BinaryExpr{
  3800  				Op:  influxql.ADD,
  3801  				LHS: &influxql.IntegerLiteral{Val: 1},
  3802  				RHS: &influxql.BinaryExpr{
  3803  					Op:  influxql.MUL,
  3804  					LHS: &influxql.IntegerLiteral{Val: 2},
  3805  					RHS: &influxql.IntegerLiteral{Val: 3},
  3806  				},
  3807  			},
  3808  		},
  3809  
  3810  		// Binary expression with LHS precedence
  3811  		{
  3812  			s: `1 / 2 + 3`,
  3813  			expr: &influxql.BinaryExpr{
  3814  				Op: influxql.ADD,
  3815  				LHS: &influxql.BinaryExpr{
  3816  					Op:  influxql.DIV,
  3817  					LHS: &influxql.IntegerLiteral{Val: 1},
  3818  					RHS: &influxql.IntegerLiteral{Val: 2},
  3819  				},
  3820  				RHS: &influxql.IntegerLiteral{Val: 3},
  3821  			},
  3822  		},
  3823  
  3824  		// Binary expression with RHS precedence
  3825  		{
  3826  			s: `1 + 2 / 3`,
  3827  			expr: &influxql.BinaryExpr{
  3828  				Op:  influxql.ADD,
  3829  				LHS: &influxql.IntegerLiteral{Val: 1},
  3830  				RHS: &influxql.BinaryExpr{
  3831  					Op:  influxql.DIV,
  3832  					LHS: &influxql.IntegerLiteral{Val: 2},
  3833  					RHS: &influxql.IntegerLiteral{Val: 3},
  3834  				},
  3835  			},
  3836  		},
  3837  
  3838  		// Binary expression with LHS precedence
  3839  		{
  3840  			s: `1 % 2 + 3`,
  3841  			expr: &influxql.BinaryExpr{
  3842  				Op: influxql.ADD,
  3843  				LHS: &influxql.BinaryExpr{
  3844  					Op:  influxql.MOD,
  3845  					LHS: &influxql.IntegerLiteral{Val: 1},
  3846  					RHS: &influxql.IntegerLiteral{Val: 2},
  3847  				},
  3848  				RHS: &influxql.IntegerLiteral{Val: 3},
  3849  			},
  3850  		},
  3851  
  3852  		// Binary expression with RHS precedence
  3853  		{
  3854  			s: `1 + 2 % 3`,
  3855  			expr: &influxql.BinaryExpr{
  3856  				Op:  influxql.ADD,
  3857  				LHS: &influxql.IntegerLiteral{Val: 1},
  3858  				RHS: &influxql.BinaryExpr{
  3859  					Op:  influxql.MOD,
  3860  					LHS: &influxql.IntegerLiteral{Val: 2},
  3861  					RHS: &influxql.IntegerLiteral{Val: 3},
  3862  				},
  3863  			},
  3864  		},
  3865  
  3866  		// Binary expression with LHS paren group.
  3867  		{
  3868  			s: `(1 + 2) * 3`,
  3869  			expr: &influxql.BinaryExpr{
  3870  				Op: influxql.MUL,
  3871  				LHS: &influxql.ParenExpr{
  3872  					Expr: &influxql.BinaryExpr{
  3873  						Op:  influxql.ADD,
  3874  						LHS: &influxql.IntegerLiteral{Val: 1},
  3875  						RHS: &influxql.IntegerLiteral{Val: 2},
  3876  					},
  3877  				},
  3878  				RHS: &influxql.IntegerLiteral{Val: 3},
  3879  			},
  3880  		},
  3881  
  3882  		// Binary expression with no precedence, tests left associativity.
  3883  		{
  3884  			s: `1 * 2 * 3`,
  3885  			expr: &influxql.BinaryExpr{
  3886  				Op: influxql.MUL,
  3887  				LHS: &influxql.BinaryExpr{
  3888  					Op:  influxql.MUL,
  3889  					LHS: &influxql.IntegerLiteral{Val: 1},
  3890  					RHS: &influxql.IntegerLiteral{Val: 2},
  3891  				},
  3892  				RHS: &influxql.IntegerLiteral{Val: 3},
  3893  			},
  3894  		},
  3895  
  3896  		// Addition and subtraction without whitespace.
  3897  		{
  3898  			s: `1+2-3`,
  3899  			expr: &influxql.BinaryExpr{
  3900  				Op: influxql.SUB,
  3901  				LHS: &influxql.BinaryExpr{
  3902  					Op:  influxql.ADD,
  3903  					LHS: &influxql.IntegerLiteral{Val: 1},
  3904  					RHS: &influxql.IntegerLiteral{Val: 2},
  3905  				},
  3906  				RHS: &influxql.IntegerLiteral{Val: 3},
  3907  			},
  3908  		},
  3909  
  3910  		{
  3911  			s: `time>now()-5m`,
  3912  			expr: &influxql.BinaryExpr{
  3913  				Op:  influxql.GT,
  3914  				LHS: &influxql.VarRef{Val: "time"},
  3915  				RHS: &influxql.BinaryExpr{
  3916  					Op:  influxql.SUB,
  3917  					LHS: &influxql.Call{Name: "now"},
  3918  					RHS: &influxql.DurationLiteral{Val: 5 * time.Minute},
  3919  				},
  3920  			},
  3921  		},
  3922  
  3923  		// Simple unary expression.
  3924  		{
  3925  			s: `-value`,
  3926  			expr: &influxql.BinaryExpr{
  3927  				Op:  influxql.MUL,
  3928  				LHS: &influxql.IntegerLiteral{Val: -1},
  3929  				RHS: &influxql.VarRef{Val: "value"},
  3930  			},
  3931  		},
  3932  
  3933  		{
  3934  			s: `-mean(value)`,
  3935  			expr: &influxql.BinaryExpr{
  3936  				Op:  influxql.MUL,
  3937  				LHS: &influxql.IntegerLiteral{Val: -1},
  3938  				RHS: &influxql.Call{
  3939  					Name: "mean",
  3940  					Args: []influxql.Expr{
  3941  						&influxql.VarRef{Val: "value"}},
  3942  				},
  3943  			},
  3944  		},
  3945  
  3946  		// Unary expressions with parenthesis.
  3947  		{
  3948  			s: `-(-4)`,
  3949  			expr: &influxql.BinaryExpr{
  3950  				Op:  influxql.MUL,
  3951  				LHS: &influxql.IntegerLiteral{Val: -1},
  3952  				RHS: &influxql.ParenExpr{
  3953  					Expr: &influxql.IntegerLiteral{Val: -4},
  3954  				},
  3955  			},
  3956  		},
  3957  
  3958  		// Multiplication with leading subtraction.
  3959  		{
  3960  			s: `-2 * 3`,
  3961  			expr: &influxql.BinaryExpr{
  3962  				Op:  influxql.MUL,
  3963  				LHS: &influxql.IntegerLiteral{Val: -2},
  3964  				RHS: &influxql.IntegerLiteral{Val: 3},
  3965  			},
  3966  		},
  3967  
  3968  		// Binary expression with regex.
  3969  		{
  3970  			s: `region =~ /us.*/`,
  3971  			expr: &influxql.BinaryExpr{
  3972  				Op:  influxql.EQREGEX,
  3973  				LHS: &influxql.VarRef{Val: "region"},
  3974  				RHS: &influxql.RegexLiteral{Val: regexp.MustCompile(`us.*`)},
  3975  			},
  3976  		},
  3977  
  3978  		// Binary expression with quoted '/' regex.
  3979  		{
  3980  			s: `url =~ /http\:\/\/www\.example\.com/`,
  3981  			expr: &influxql.BinaryExpr{
  3982  				Op:  influxql.EQREGEX,
  3983  				LHS: &influxql.VarRef{Val: "url"},
  3984  				RHS: &influxql.RegexLiteral{Val: regexp.MustCompile(`http\://www\.example\.com`)},
  3985  			},
  3986  		},
  3987  
  3988  		// Binary expression with quoted '/' regex without space around operator. Influxdb #9058
  3989  		{
  3990  			s: `url=~/http\:\/\/www\.example\.com/`,
  3991  			expr: &influxql.BinaryExpr{
  3992  				Op:  influxql.EQREGEX,
  3993  				LHS: &influxql.VarRef{Val: "url"},
  3994  				RHS: &influxql.RegexLiteral{Val: regexp.MustCompile(`http\://www\.example\.com`)},
  3995  			},
  3996  		},
  3997  
  3998  		// Complex binary expression.
  3999  		{
  4000  			s: `value + 3 < 30 AND 1 + 2 OR true`,
  4001  			expr: &influxql.BinaryExpr{
  4002  				Op: influxql.OR,
  4003  				LHS: &influxql.BinaryExpr{
  4004  					Op: influxql.AND,
  4005  					LHS: &influxql.BinaryExpr{
  4006  						Op: influxql.LT,
  4007  						LHS: &influxql.BinaryExpr{
  4008  							Op:  influxql.ADD,
  4009  							LHS: &influxql.VarRef{Val: "value"},
  4010  							RHS: &influxql.IntegerLiteral{Val: 3},
  4011  						},
  4012  						RHS: &influxql.IntegerLiteral{Val: 30},
  4013  					},
  4014  					RHS: &influxql.BinaryExpr{
  4015  						Op:  influxql.ADD,
  4016  						LHS: &influxql.IntegerLiteral{Val: 1},
  4017  						RHS: &influxql.IntegerLiteral{Val: 2},
  4018  					},
  4019  				},
  4020  				RHS: &influxql.BooleanLiteral{Val: true},
  4021  			},
  4022  		},
  4023  
  4024  		// Complex binary expression.
  4025  		{
  4026  			s: `time > now() - 1d AND time < now() + 1d`,
  4027  			expr: &influxql.BinaryExpr{
  4028  				Op: influxql.AND,
  4029  				LHS: &influxql.BinaryExpr{
  4030  					Op:  influxql.GT,
  4031  					LHS: &influxql.VarRef{Val: "time"},
  4032  					RHS: &influxql.BinaryExpr{
  4033  						Op:  influxql.SUB,
  4034  						LHS: &influxql.Call{Name: "now"},
  4035  						RHS: &influxql.DurationLiteral{Val: mustParseDuration("1d")},
  4036  					},
  4037  				},
  4038  				RHS: &influxql.BinaryExpr{
  4039  					Op:  influxql.LT,
  4040  					LHS: &influxql.VarRef{Val: "time"},
  4041  					RHS: &influxql.BinaryExpr{
  4042  						Op:  influxql.ADD,
  4043  						LHS: &influxql.Call{Name: "now"},
  4044  						RHS: &influxql.DurationLiteral{Val: mustParseDuration("1d")},
  4045  					},
  4046  				},
  4047  			},
  4048  		},
  4049  
  4050  		// Duration math with an invalid literal.
  4051  		{
  4052  			s:   `time > now() - 1y`,
  4053  			err: `invalid duration`,
  4054  		},
  4055  
  4056  		// Function call (empty)
  4057  		{
  4058  			s: `my_func()`,
  4059  			expr: &influxql.Call{
  4060  				Name: "my_func",
  4061  			},
  4062  		},
  4063  
  4064  		// Function call (multi-arg)
  4065  		{
  4066  			s: `my_func(1, 2 + 3)`,
  4067  			expr: &influxql.Call{
  4068  				Name: "my_func",
  4069  				Args: []influxql.Expr{
  4070  					&influxql.IntegerLiteral{Val: 1},
  4071  					&influxql.BinaryExpr{
  4072  						Op:  influxql.ADD,
  4073  						LHS: &influxql.IntegerLiteral{Val: 2},
  4074  						RHS: &influxql.IntegerLiteral{Val: 3},
  4075  					},
  4076  				},
  4077  			},
  4078  		},
  4079  	}
  4080  
  4081  	for i, tt := range tests {
  4082  		expr, err := influxql.NewParser(strings.NewReader(tt.s)).ParseExpr()
  4083  		if !reflect.DeepEqual(tt.err, errstring(err)) {
  4084  			t.Errorf("%d. %q: error mismatch:\n  exp=%s\n  got=%s\n\n", i, tt.s, tt.err, err)
  4085  		} else if tt.err == "" && !reflect.DeepEqual(tt.expr, expr) {
  4086  			t.Errorf("%d. %q\n\nexpr mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.expr, expr)
  4087  		} else if err == nil {
  4088  			// Attempt to reparse the expr as a string and confirm it parses the same.
  4089  			expr2, err := influxql.ParseExpr(expr.String())
  4090  			if err != nil {
  4091  				t.Errorf("%d. %q: unable to parse expr string: %s", i, expr.String(), err)
  4092  			} else if !reflect.DeepEqual(tt.expr, expr2) {
  4093  				t.Logf("\n# %s\nexp=%s\ngot=%s\n", tt.s, mustMarshalJSON(tt.expr), mustMarshalJSON(expr2))
  4094  				t.Logf("\nSQL exp=%s\nSQL got=%s\n", tt.expr.String(), expr2.String())
  4095  				t.Errorf("%d. %q\n\nexpr reparse mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.expr, expr2)
  4096  			}
  4097  		}
  4098  	}
  4099  }
  4100  
  4101  // Ensure a time duration can be parsed.
  4102  func TestParseDuration(t *testing.T) {
  4103  	var tests = []struct {
  4104  		s   string
  4105  		d   time.Duration
  4106  		err string
  4107  	}{
  4108  		{s: `10ns`, d: 10},
  4109  		{s: `10u`, d: 10 * time.Microsecond},
  4110  		{s: `10ยต`, d: 10 * time.Microsecond},
  4111  		{s: `15ms`, d: 15 * time.Millisecond},
  4112  		{s: `100s`, d: 100 * time.Second},
  4113  		{s: `2m`, d: 2 * time.Minute},
  4114  		{s: `2h`, d: 2 * time.Hour},
  4115  		{s: `2d`, d: 2 * 24 * time.Hour},
  4116  		{s: `2w`, d: 2 * 7 * 24 * time.Hour},
  4117  		{s: `1h30m`, d: time.Hour + 30*time.Minute},
  4118  		{s: `30ms3000u`, d: 30*time.Millisecond + 3000*time.Microsecond},
  4119  		{s: `-5s`, d: -5 * time.Second},
  4120  		{s: `-5m30s`, d: -5*time.Minute - 30*time.Second},
  4121  
  4122  		{s: ``, err: "invalid duration"},
  4123  		{s: `3`, err: "invalid duration"},
  4124  		{s: `1000`, err: "invalid duration"},
  4125  		{s: `w`, err: "invalid duration"},
  4126  		{s: `ms`, err: "invalid duration"},
  4127  		{s: `1.2w`, err: "invalid duration"},
  4128  		{s: `10x`, err: "invalid duration"},
  4129  		{s: `10n`, err: "invalid duration"},
  4130  	}
  4131  
  4132  	for i, tt := range tests {
  4133  		d, err := influxql.ParseDuration(tt.s)
  4134  		if !reflect.DeepEqual(tt.err, errstring(err)) {
  4135  			t.Errorf("%d. %q: error mismatch:\n  exp=%s\n  got=%s\n\n", i, tt.s, tt.err, err)
  4136  		} else if tt.d != d {
  4137  			t.Errorf("%d. %q\n\nduration mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.d, d)
  4138  		}
  4139  	}
  4140  }
  4141  
  4142  // Ensure a time duration can be formatted.
  4143  func TestFormatDuration(t *testing.T) {
  4144  	var tests = []struct {
  4145  		d time.Duration
  4146  		s string
  4147  	}{
  4148  		{d: 3 * time.Microsecond, s: `3u`},
  4149  		{d: 1001 * time.Microsecond, s: `1001u`},
  4150  		{d: 15 * time.Millisecond, s: `15ms`},
  4151  		{d: 100 * time.Second, s: `100s`},
  4152  		{d: 2 * time.Minute, s: `2m`},
  4153  		{d: 2 * time.Hour, s: `2h`},
  4154  		{d: 2 * 24 * time.Hour, s: `2d`},
  4155  		{d: 2 * 7 * 24 * time.Hour, s: `2w`},
  4156  	}
  4157  
  4158  	for i, tt := range tests {
  4159  		s := influxql.FormatDuration(tt.d)
  4160  		if tt.s != s {
  4161  			t.Errorf("%d. %v: mismatch: %s != %s", i, tt.d, tt.s, s)
  4162  		}
  4163  	}
  4164  }
  4165  
  4166  // Ensure a string can be quoted.
  4167  func TestQuote(t *testing.T) {
  4168  	for i, tt := range []struct {
  4169  		in  string
  4170  		out string
  4171  	}{
  4172  		{``, `''`},
  4173  		{`foo`, `'foo'`},
  4174  		{"foo\nbar", `'foo\nbar'`},
  4175  		{`foo bar\\`, `'foo bar\\\\'`},
  4176  		{`'foo'`, `'\'foo\''`},
  4177  	} {
  4178  		if out := influxql.QuoteString(tt.in); tt.out != out {
  4179  			t.Errorf("%d. %s: mismatch: %s != %s", i, tt.in, tt.out, out)
  4180  		}
  4181  	}
  4182  }
  4183  
  4184  // Ensure an identifier's segments can be quoted.
  4185  func TestQuoteIdent(t *testing.T) {
  4186  	for i, tt := range []struct {
  4187  		ident []string
  4188  		s     string
  4189  	}{
  4190  		{[]string{``}, `""`},
  4191  		{[]string{`select`}, `"select"`},
  4192  		{[]string{`in-bytes`}, `"in-bytes"`},
  4193  		{[]string{`foo`, `bar`}, `"foo".bar`},
  4194  		{[]string{`foo`, ``, `bar`}, `"foo"..bar`},
  4195  		{[]string{`foo bar`, `baz`}, `"foo bar".baz`},
  4196  		{[]string{`foo.bar`, `baz`}, `"foo.bar".baz`},
  4197  		{[]string{`foo.bar`, `rp`, `baz`}, `"foo.bar"."rp".baz`},
  4198  		{[]string{`foo.bar`, `rp`, `1baz`}, `"foo.bar"."rp"."1baz"`},
  4199  	} {
  4200  		if s := influxql.QuoteIdent(tt.ident...); tt.s != s {
  4201  			t.Errorf("%d. %s: mismatch: %s != %s", i, tt.ident, tt.s, s)
  4202  		}
  4203  	}
  4204  }
  4205  
  4206  // Ensure DeleteSeriesStatement can convert to a string
  4207  func TestDeleteSeriesStatement_String(t *testing.T) {
  4208  	var tests = []struct {
  4209  		s    string
  4210  		stmt influxql.Statement
  4211  	}{
  4212  		{
  4213  			s:    `DELETE FROM src`,
  4214  			stmt: &influxql.DeleteSeriesStatement{Sources: []influxql.Source{&influxql.Measurement{Name: "src"}}},
  4215  		},
  4216  		{
  4217  			s: `DELETE FROM src WHERE host = 'hosta.influxdb.org'`,
  4218  			stmt: &influxql.DeleteSeriesStatement{
  4219  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  4220  				Condition: &influxql.BinaryExpr{
  4221  					Op:  influxql.EQ,
  4222  					LHS: &influxql.VarRef{Val: "host"},
  4223  					RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  4224  				},
  4225  			},
  4226  		},
  4227  		{
  4228  			s: `DELETE FROM src WHERE host = 'hosta.influxdb.org'`,
  4229  			stmt: &influxql.DeleteSeriesStatement{
  4230  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  4231  				Condition: &influxql.BinaryExpr{
  4232  					Op:  influxql.EQ,
  4233  					LHS: &influxql.VarRef{Val: "host"},
  4234  					RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  4235  				},
  4236  			},
  4237  		},
  4238  		{
  4239  			s: `DELETE WHERE host = 'hosta.influxdb.org'`,
  4240  			stmt: &influxql.DeleteSeriesStatement{
  4241  				Condition: &influxql.BinaryExpr{
  4242  					Op:  influxql.EQ,
  4243  					LHS: &influxql.VarRef{Val: "host"},
  4244  					RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  4245  				},
  4246  			},
  4247  		},
  4248  	}
  4249  
  4250  	for _, test := range tests {
  4251  		s := test.stmt.String()
  4252  		if s != test.s {
  4253  			t.Errorf("error rendering string. expected %s, actual: %s", test.s, s)
  4254  		}
  4255  	}
  4256  }
  4257  
  4258  // Ensure DropSeriesStatement can convert to a string
  4259  func TestDropSeriesStatement_String(t *testing.T) {
  4260  	var tests = []struct {
  4261  		s    string
  4262  		stmt influxql.Statement
  4263  	}{
  4264  		{
  4265  			s:    `DROP SERIES FROM src`,
  4266  			stmt: &influxql.DropSeriesStatement{Sources: []influxql.Source{&influxql.Measurement{Name: "src"}}},
  4267  		},
  4268  		{
  4269  			s: `DROP SERIES FROM src WHERE host = 'hosta.influxdb.org'`,
  4270  			stmt: &influxql.DropSeriesStatement{
  4271  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  4272  				Condition: &influxql.BinaryExpr{
  4273  					Op:  influxql.EQ,
  4274  					LHS: &influxql.VarRef{Val: "host"},
  4275  					RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  4276  				},
  4277  			},
  4278  		},
  4279  		{
  4280  			s: `DROP SERIES FROM src WHERE host = 'hosta.influxdb.org'`,
  4281  			stmt: &influxql.DropSeriesStatement{
  4282  				Sources: []influxql.Source{&influxql.Measurement{Name: "src"}},
  4283  				Condition: &influxql.BinaryExpr{
  4284  					Op:  influxql.EQ,
  4285  					LHS: &influxql.VarRef{Val: "host"},
  4286  					RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  4287  				},
  4288  			},
  4289  		},
  4290  		{
  4291  			s: `DROP SERIES WHERE host = 'hosta.influxdb.org'`,
  4292  			stmt: &influxql.DropSeriesStatement{
  4293  				Condition: &influxql.BinaryExpr{
  4294  					Op:  influxql.EQ,
  4295  					LHS: &influxql.VarRef{Val: "host"},
  4296  					RHS: &influxql.StringLiteral{Val: "hosta.influxdb.org"},
  4297  				},
  4298  			},
  4299  		},
  4300  	}
  4301  
  4302  	for _, test := range tests {
  4303  		s := test.stmt.String()
  4304  		if s != test.s {
  4305  			t.Errorf("error rendering string. expected %s, actual: %s", test.s, s)
  4306  		}
  4307  	}
  4308  }
  4309  
  4310  func BenchmarkParserParseStatement(b *testing.B) {
  4311  	b.ReportAllocs()
  4312  	s := `SELECT "field" FROM "series" WHERE value > 10`
  4313  	for i := 0; i < b.N; i++ {
  4314  		if stmt, err := influxql.NewParser(strings.NewReader(s)).ParseStatement(); err != nil {
  4315  			b.Fatalf("unexpected error: %s", err)
  4316  		} else if stmt == nil {
  4317  			b.Fatalf("expected statement: %s", stmt)
  4318  		}
  4319  	}
  4320  	b.SetBytes(int64(len(s)))
  4321  }
  4322  
  4323  // MustParseSelectStatement parses a select statement. Panic on error.
  4324  func MustParseSelectStatement(s string) *influxql.SelectStatement {
  4325  	stmt, err := influxql.NewParser(strings.NewReader(s)).ParseStatement()
  4326  	if err != nil {
  4327  		panic(err)
  4328  	}
  4329  	return stmt.(*influxql.SelectStatement)
  4330  }
  4331  
  4332  // MustParseExpr parses an expression. Panic on error.
  4333  func MustParseExpr(s string) influxql.Expr {
  4334  	expr, err := influxql.NewParser(strings.NewReader(s)).ParseExpr()
  4335  	if err != nil {
  4336  		panic(err)
  4337  	}
  4338  	return expr
  4339  }
  4340  
  4341  // errstring converts an error to its string representation.
  4342  func errstring(err error) string {
  4343  	if err != nil {
  4344  		return err.Error()
  4345  	}
  4346  	return ""
  4347  }
  4348  
  4349  // newAlterRetentionPolicyStatement creates an initialized AlterRetentionPolicyStatement.
  4350  func newAlterRetentionPolicyStatement(name string, DB string, d, sd time.Duration, replication int, dfault bool) *influxql.AlterRetentionPolicyStatement {
  4351  	stmt := &influxql.AlterRetentionPolicyStatement{
  4352  		Name:     name,
  4353  		Database: DB,
  4354  		Default:  dfault,
  4355  	}
  4356  
  4357  	if d > -1 {
  4358  		stmt.Duration = &d
  4359  	}
  4360  
  4361  	if sd > -1 {
  4362  		stmt.ShardGroupDuration = &sd
  4363  	}
  4364  
  4365  	if replication > -1 {
  4366  		stmt.Replication = &replication
  4367  	}
  4368  
  4369  	return stmt
  4370  }
  4371  
  4372  // mustMarshalJSON encodes a value to JSON.
  4373  func mustMarshalJSON(v interface{}) []byte {
  4374  	b, err := json.MarshalIndent(v, "", "  ")
  4375  	if err != nil {
  4376  		panic(err)
  4377  	}
  4378  	return b
  4379  }
  4380  
  4381  func mustParseDuration(s string) time.Duration {
  4382  	d, err := influxql.ParseDuration(s)
  4383  	if err != nil {
  4384  		panic(err)
  4385  	}
  4386  	return d
  4387  }
  4388  
  4389  func mustLoadLocation(s string) *time.Location {
  4390  	l, err := time.LoadLocation(s)
  4391  	if err != nil {
  4392  		panic(err)
  4393  	}
  4394  	return l
  4395  }
  4396  
  4397  var LosAngeles = mustLoadLocation("America/Los_Angeles")
  4398  
  4399  func duration(v time.Duration) *time.Duration {
  4400  	return &v
  4401  }
  4402  
  4403  func intptr(v int) *int {
  4404  	return &v
  4405  }