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

     1  package influxql_test
     2  
     3  import (
     4  	"fmt"
     5  	"go/importer"
     6  	"math"
     7  	"reflect"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/influxdata/influxql"
    13  )
    14  
    15  func BenchmarkQuery_String(b *testing.B) {
    16  	p := influxql.NewParser(strings.NewReader(`SELECT foo AS zoo, a AS b FROM bar WHERE value > 10 AND q = 'hello'`))
    17  	q, _ := p.ParseStatement()
    18  	for i := 0; i < b.N; i++ {
    19  		_ = q.String()
    20  	}
    21  }
    22  
    23  // Ensure a value's data type can be retrieved.
    24  func TestInspectDataType(t *testing.T) {
    25  	for i, tt := range []struct {
    26  		v   interface{}
    27  		typ influxql.DataType
    28  	}{
    29  		{float64(100), influxql.Float},
    30  		{int64(100), influxql.Integer},
    31  		{int32(100), influxql.Integer},
    32  		{100, influxql.Integer},
    33  		{true, influxql.Boolean},
    34  		{"string", influxql.String},
    35  		{time.Now(), influxql.Time},
    36  		{time.Second, influxql.Duration},
    37  		{nil, influxql.Unknown},
    38  	} {
    39  		if typ := influxql.InspectDataType(tt.v); tt.typ != typ {
    40  			t.Errorf("%d. %v (%s): unexpected type: %s", i, tt.v, tt.typ, typ)
    41  			continue
    42  		}
    43  	}
    44  }
    45  
    46  func TestDataTypeFromString(t *testing.T) {
    47  	for i, tt := range []struct {
    48  		s   string
    49  		typ influxql.DataType
    50  	}{
    51  		{s: "float", typ: influxql.Float},
    52  		{s: "integer", typ: influxql.Integer},
    53  		{s: "unsigned", typ: influxql.Unsigned},
    54  		{s: "string", typ: influxql.String},
    55  		{s: "boolean", typ: influxql.Boolean},
    56  		{s: "time", typ: influxql.Time},
    57  		{s: "duration", typ: influxql.Duration},
    58  		{s: "tag", typ: influxql.Tag},
    59  		{s: "field", typ: influxql.AnyField},
    60  		{s: "foobar", typ: influxql.Unknown},
    61  	} {
    62  		if typ := influxql.DataTypeFromString(tt.s); tt.typ != typ {
    63  			t.Errorf("%d. %s: unexpected type: %s != %s", i, tt.s, tt.typ, typ)
    64  		}
    65  	}
    66  }
    67  
    68  func TestDataType_String(t *testing.T) {
    69  	for i, tt := range []struct {
    70  		typ influxql.DataType
    71  		v   string
    72  	}{
    73  		{influxql.Float, "float"},
    74  		{influxql.Integer, "integer"},
    75  		{influxql.Boolean, "boolean"},
    76  		{influxql.String, "string"},
    77  		{influxql.Time, "time"},
    78  		{influxql.Duration, "duration"},
    79  		{influxql.Tag, "tag"},
    80  		{influxql.Unknown, "unknown"},
    81  	} {
    82  		if v := tt.typ.String(); tt.v != v {
    83  			t.Errorf("%d. %v (%s): unexpected string: %s", i, tt.typ, tt.v, v)
    84  		}
    85  	}
    86  }
    87  
    88  func TestDataType_LessThan(t *testing.T) {
    89  	for i, tt := range []struct {
    90  		typ   influxql.DataType
    91  		other influxql.DataType
    92  		exp   bool
    93  	}{
    94  		{typ: influxql.Unknown, other: influxql.Unknown, exp: true},
    95  		{typ: influxql.Unknown, other: influxql.Float, exp: true},
    96  		{typ: influxql.Unknown, other: influxql.Integer, exp: true},
    97  		{typ: influxql.Unknown, other: influxql.Unsigned, exp: true},
    98  		{typ: influxql.Unknown, other: influxql.String, exp: true},
    99  		{typ: influxql.Unknown, other: influxql.Boolean, exp: true},
   100  		{typ: influxql.Unknown, other: influxql.Tag, exp: true},
   101  		{typ: influxql.Float, other: influxql.Unknown, exp: false},
   102  		{typ: influxql.Integer, other: influxql.Unknown, exp: false},
   103  		{typ: influxql.Unsigned, other: influxql.Unknown, exp: false},
   104  		{typ: influxql.String, other: influxql.Unknown, exp: false},
   105  		{typ: influxql.Boolean, other: influxql.Unknown, exp: false},
   106  		{typ: influxql.Tag, other: influxql.Unknown, exp: false},
   107  		{typ: influxql.Float, other: influxql.Float, exp: false},
   108  		{typ: influxql.Float, other: influxql.Integer, exp: false},
   109  		{typ: influxql.Float, other: influxql.Unsigned, exp: false},
   110  		{typ: influxql.Float, other: influxql.String, exp: false},
   111  		{typ: influxql.Float, other: influxql.Boolean, exp: false},
   112  		{typ: influxql.Float, other: influxql.Tag, exp: false},
   113  		{typ: influxql.Integer, other: influxql.Float, exp: true},
   114  		{typ: influxql.Integer, other: influxql.Integer, exp: false},
   115  		{typ: influxql.Integer, other: influxql.Unsigned, exp: false},
   116  		{typ: influxql.Integer, other: influxql.String, exp: false},
   117  		{typ: influxql.Integer, other: influxql.Boolean, exp: false},
   118  		{typ: influxql.Integer, other: influxql.Tag, exp: false},
   119  		{typ: influxql.Unsigned, other: influxql.Float, exp: true},
   120  		{typ: influxql.Unsigned, other: influxql.Integer, exp: true},
   121  		{typ: influxql.Unsigned, other: influxql.Unsigned, exp: false},
   122  		{typ: influxql.Unsigned, other: influxql.String, exp: false},
   123  		{typ: influxql.Unsigned, other: influxql.Boolean, exp: false},
   124  		{typ: influxql.Unsigned, other: influxql.Tag, exp: false},
   125  		{typ: influxql.String, other: influxql.Float, exp: true},
   126  		{typ: influxql.String, other: influxql.Integer, exp: true},
   127  		{typ: influxql.String, other: influxql.Unsigned, exp: true},
   128  		{typ: influxql.String, other: influxql.String, exp: false},
   129  		{typ: influxql.String, other: influxql.Boolean, exp: false},
   130  		{typ: influxql.String, other: influxql.Tag, exp: false},
   131  		{typ: influxql.Boolean, other: influxql.Float, exp: true},
   132  		{typ: influxql.Boolean, other: influxql.Integer, exp: true},
   133  		{typ: influxql.Boolean, other: influxql.Unsigned, exp: true},
   134  		{typ: influxql.Boolean, other: influxql.String, exp: true},
   135  		{typ: influxql.Boolean, other: influxql.Boolean, exp: false},
   136  		{typ: influxql.Boolean, other: influxql.Tag, exp: false},
   137  		{typ: influxql.Tag, other: influxql.Float, exp: true},
   138  		{typ: influxql.Tag, other: influxql.Integer, exp: true},
   139  		{typ: influxql.Tag, other: influxql.Unsigned, exp: true},
   140  		{typ: influxql.Tag, other: influxql.String, exp: true},
   141  		{typ: influxql.Tag, other: influxql.Boolean, exp: true},
   142  		{typ: influxql.Tag, other: influxql.Tag, exp: false},
   143  	} {
   144  		if got, exp := tt.typ.LessThan(tt.other), tt.exp; got != exp {
   145  			t.Errorf("%d. %q.LessThan(%q) = %v; exp = %v", i, tt.typ, tt.other, got, exp)
   146  		}
   147  	}
   148  }
   149  
   150  // Ensure the SELECT statement can extract GROUP BY interval.
   151  func TestSelectStatement_GroupByInterval(t *testing.T) {
   152  	q := "SELECT sum(value) from foo  where time < now() GROUP BY time(10m)"
   153  	stmt, err := influxql.NewParser(strings.NewReader(q)).ParseStatement()
   154  	if err != nil {
   155  		t.Fatalf("invalid statement: %q: %s", stmt, err)
   156  	}
   157  
   158  	s := stmt.(*influxql.SelectStatement)
   159  	d, err := s.GroupByInterval()
   160  	if d != 10*time.Minute {
   161  		t.Fatalf("group by interval not equal:\nexp=%s\ngot=%s", 10*time.Minute, d)
   162  	}
   163  	if err != nil {
   164  		t.Fatalf("error parsing group by interval: %s", err.Error())
   165  	}
   166  }
   167  
   168  // Ensure the SELECT statement can have its start and end time set
   169  func TestSelectStatement_SetTimeRange(t *testing.T) {
   170  	q := "SELECT sum(value) from foo where time < now() GROUP BY time(10m)"
   171  	stmt, err := influxql.NewParser(strings.NewReader(q)).ParseStatement()
   172  	if err != nil {
   173  		t.Fatalf("invalid statement: %q: %s", stmt, err)
   174  	}
   175  
   176  	s := stmt.(*influxql.SelectStatement)
   177  	start := time.Now().Add(-20 * time.Hour).Round(time.Second).UTC()
   178  	end := time.Now().Add(10 * time.Hour).Round(time.Second).UTC()
   179  	s.SetTimeRange(start, end)
   180  	min, max := MustTimeRange(s.Condition)
   181  
   182  	if min != start {
   183  		t.Fatalf("start time wasn't set properly.\n  exp: %s\n  got: %s", start, min)
   184  	}
   185  	// the end range is actually one nanosecond before the given one since end is exclusive
   186  	end = end.Add(-time.Nanosecond)
   187  	if max != end {
   188  		t.Fatalf("end time wasn't set properly.\n  exp: %s\n  got: %s", end, max)
   189  	}
   190  
   191  	// ensure we can set a time on a select that already has one set
   192  	start = time.Now().Add(-20 * time.Hour).Round(time.Second).UTC()
   193  	end = time.Now().Add(10 * time.Hour).Round(time.Second).UTC()
   194  	q = fmt.Sprintf("SELECT sum(value) from foo WHERE time >= %ds and time <= %ds GROUP BY time(10m)", start.Unix(), end.Unix())
   195  	stmt, err = influxql.NewParser(strings.NewReader(q)).ParseStatement()
   196  	if err != nil {
   197  		t.Fatalf("invalid statement: %q: %s", stmt, err)
   198  	}
   199  
   200  	s = stmt.(*influxql.SelectStatement)
   201  	min, max = MustTimeRange(s.Condition)
   202  	if start != min || end != max {
   203  		t.Fatalf("start and end times weren't equal:\n  exp: %s\n  got: %s\n  exp: %s\n  got:%s\n", start, min, end, max)
   204  	}
   205  
   206  	// update and ensure it saves it
   207  	start = time.Now().Add(-40 * time.Hour).Round(time.Second).UTC()
   208  	end = time.Now().Add(20 * time.Hour).Round(time.Second).UTC()
   209  	s.SetTimeRange(start, end)
   210  	min, max = MustTimeRange(s.Condition)
   211  
   212  	// TODO: right now the SetTimeRange can't override the start time if it's more recent than what they're trying to set it to.
   213  	//       shouldn't matter for our purposes with continuous queries, but fix this later
   214  
   215  	if min != start {
   216  		t.Fatalf("start time wasn't set properly.\n  exp: %s\n  got: %s", start, min)
   217  	}
   218  	// the end range is actually one nanosecond before the given one since end is exclusive
   219  	end = end.Add(-time.Nanosecond)
   220  	if max != end {
   221  		t.Fatalf("end time wasn't set properly.\n  exp: %s\n  got: %s", end, max)
   222  	}
   223  
   224  	// ensure that when we set a time range other where clause conditions are still there
   225  	q = "SELECT sum(value) from foo WHERE foo = 'bar' and time < now() GROUP BY time(10m)"
   226  	stmt, err = influxql.NewParser(strings.NewReader(q)).ParseStatement()
   227  	if err != nil {
   228  		t.Fatalf("invalid statement: %q: %s", stmt, err)
   229  	}
   230  
   231  	s = stmt.(*influxql.SelectStatement)
   232  
   233  	// update and ensure it saves it
   234  	start = time.Now().Add(-40 * time.Hour).Round(time.Second).UTC()
   235  	end = time.Now().Add(20 * time.Hour).Round(time.Second).UTC()
   236  	s.SetTimeRange(start, end)
   237  	min, max = MustTimeRange(s.Condition)
   238  
   239  	if min != start {
   240  		t.Fatalf("start time wasn't set properly.\n  exp: %s\n  got: %s", start, min)
   241  	}
   242  	// the end range is actually one nanosecond before the given one since end is exclusive
   243  	end = end.Add(-time.Nanosecond)
   244  	if max != end {
   245  		t.Fatalf("end time wasn't set properly.\n  exp: %s\n  got: %s", end, max)
   246  	}
   247  
   248  	// ensure the where clause is there
   249  	hasWhere := false
   250  	influxql.WalkFunc(s.Condition, func(n influxql.Node) {
   251  		if ex, ok := n.(*influxql.BinaryExpr); ok {
   252  			if lhs, ok := ex.LHS.(*influxql.VarRef); ok {
   253  				if lhs.Val == "foo" {
   254  					if rhs, ok := ex.RHS.(*influxql.StringLiteral); ok {
   255  						if rhs.Val == "bar" {
   256  							hasWhere = true
   257  						}
   258  					}
   259  				}
   260  			}
   261  		}
   262  	})
   263  	if !hasWhere {
   264  		t.Fatal("set time range cleared out the where clause")
   265  	}
   266  }
   267  
   268  func TestSelectStatement_HasWildcard(t *testing.T) {
   269  	var tests = []struct {
   270  		stmt     string
   271  		wildcard bool
   272  	}{
   273  		// No wildcards
   274  		{
   275  			stmt:     `SELECT value FROM cpu`,
   276  			wildcard: false,
   277  		},
   278  
   279  		// Query wildcard
   280  		{
   281  			stmt:     `SELECT * FROM cpu`,
   282  			wildcard: true,
   283  		},
   284  
   285  		// No GROUP BY wildcards
   286  		{
   287  			stmt:     `SELECT value FROM cpu GROUP BY host`,
   288  			wildcard: false,
   289  		},
   290  
   291  		// No GROUP BY wildcards, time only
   292  		{
   293  			stmt:     `SELECT mean(value) FROM cpu where time < now() GROUP BY time(5ms)`,
   294  			wildcard: false,
   295  		},
   296  
   297  		// GROUP BY wildcard
   298  		{
   299  			stmt:     `SELECT value FROM cpu GROUP BY *`,
   300  			wildcard: true,
   301  		},
   302  
   303  		// GROUP BY wildcard with time
   304  		{
   305  			stmt:     `SELECT mean(value) FROM cpu where time < now() GROUP BY *,time(1m)`,
   306  			wildcard: true,
   307  		},
   308  
   309  		// GROUP BY wildcard with explicit
   310  		{
   311  			stmt:     `SELECT value FROM cpu GROUP BY *,host`,
   312  			wildcard: true,
   313  		},
   314  
   315  		// GROUP BY multiple wildcards
   316  		{
   317  			stmt:     `SELECT value FROM cpu GROUP BY *,*`,
   318  			wildcard: true,
   319  		},
   320  
   321  		// Combo
   322  		{
   323  			stmt:     `SELECT * FROM cpu GROUP BY *`,
   324  			wildcard: true,
   325  		},
   326  	}
   327  
   328  	for i, tt := range tests {
   329  		// Parse statement.
   330  		stmt, err := influxql.NewParser(strings.NewReader(tt.stmt)).ParseStatement()
   331  		if err != nil {
   332  			t.Fatalf("invalid statement: %q: %s", tt.stmt, err)
   333  		}
   334  
   335  		// Test wildcard detection.
   336  		if w := stmt.(*influxql.SelectStatement).HasWildcard(); tt.wildcard != w {
   337  			t.Errorf("%d. %q: unexpected wildcard detection:\n\nexp=%v\n\ngot=%v\n\n", i, tt.stmt, tt.wildcard, w)
   338  			continue
   339  		}
   340  	}
   341  }
   342  
   343  // Test SELECT statement field rewrite.
   344  func TestSelectStatement_RewriteFields(t *testing.T) {
   345  	var tests = []struct {
   346  		stmt    string
   347  		rewrite string
   348  		err     string
   349  	}{
   350  		// No wildcards
   351  		{
   352  			stmt:    `SELECT value FROM cpu`,
   353  			rewrite: `SELECT value FROM cpu`,
   354  		},
   355  
   356  		// Query wildcard
   357  		{
   358  			stmt:    `SELECT * FROM cpu`,
   359  			rewrite: `SELECT host::tag, region::tag, value1::float, value2::integer FROM cpu`,
   360  		},
   361  
   362  		// Parser fundamentally prohibits multiple query sources
   363  
   364  		// Query wildcard with explicit
   365  		{
   366  			stmt:    `SELECT *,value1 FROM cpu`,
   367  			rewrite: `SELECT host::tag, region::tag, value1::float, value2::integer, value1::float FROM cpu`,
   368  		},
   369  
   370  		// Query multiple wildcards
   371  		{
   372  			stmt:    `SELECT *,* FROM cpu`,
   373  			rewrite: `SELECT host::tag, region::tag, value1::float, value2::integer, host::tag, region::tag, value1::float, value2::integer FROM cpu`,
   374  		},
   375  
   376  		// Query wildcards with group by
   377  		{
   378  			stmt:    `SELECT * FROM cpu GROUP BY host`,
   379  			rewrite: `SELECT region::tag, value1::float, value2::integer FROM cpu GROUP BY host`,
   380  		},
   381  
   382  		// No GROUP BY wildcards
   383  		{
   384  			stmt:    `SELECT value FROM cpu GROUP BY host`,
   385  			rewrite: `SELECT value FROM cpu GROUP BY host`,
   386  		},
   387  
   388  		// No GROUP BY wildcards, time only
   389  		{
   390  			stmt:    `SELECT mean(value) FROM cpu where time < now() GROUP BY time(5ms)`,
   391  			rewrite: `SELECT mean(value) FROM cpu WHERE time < now() GROUP BY time(5ms)`,
   392  		},
   393  
   394  		// GROUP BY wildcard
   395  		{
   396  			stmt:    `SELECT value FROM cpu GROUP BY *`,
   397  			rewrite: `SELECT value FROM cpu GROUP BY host, region`,
   398  		},
   399  
   400  		// GROUP BY wildcard with time
   401  		{
   402  			stmt:    `SELECT mean(value) FROM cpu where time < now() GROUP BY *,time(1m)`,
   403  			rewrite: `SELECT mean(value) FROM cpu WHERE time < now() GROUP BY host, region, time(1m)`,
   404  		},
   405  
   406  		// GROUP BY wildcard with fill
   407  		{
   408  			stmt:    `SELECT mean(value) FROM cpu where time < now() GROUP BY *,time(1m) fill(0)`,
   409  			rewrite: `SELECT mean(value) FROM cpu WHERE time < now() GROUP BY host, region, time(1m) fill(0)`,
   410  		},
   411  
   412  		// GROUP BY wildcard with explicit
   413  		{
   414  			stmt:    `SELECT value FROM cpu GROUP BY *,host`,
   415  			rewrite: `SELECT value FROM cpu GROUP BY host, region, host`,
   416  		},
   417  
   418  		// GROUP BY multiple wildcards
   419  		{
   420  			stmt:    `SELECT value FROM cpu GROUP BY *,*`,
   421  			rewrite: `SELECT value FROM cpu GROUP BY host, region, host, region`,
   422  		},
   423  
   424  		// Combo
   425  		{
   426  			stmt:    `SELECT * FROM cpu GROUP BY *`,
   427  			rewrite: `SELECT value1::float, value2::integer FROM cpu GROUP BY host, region`,
   428  		},
   429  
   430  		// Wildcard function with all fields.
   431  		{
   432  			stmt:    `SELECT mean(*) FROM cpu`,
   433  			rewrite: `SELECT mean(value1::float) AS mean_value1, mean(value2::integer) AS mean_value2 FROM cpu`,
   434  		},
   435  
   436  		{
   437  			stmt:    `SELECT distinct(*) FROM strings`,
   438  			rewrite: `SELECT distinct(string::string) AS distinct_string, distinct(value::float) AS distinct_value FROM strings`,
   439  		},
   440  
   441  		{
   442  			stmt:    `SELECT distinct(*) FROM bools`,
   443  			rewrite: `SELECT distinct(bool::boolean) AS distinct_bool, distinct(value::float) AS distinct_value FROM bools`,
   444  		},
   445  
   446  		// Wildcard function with some fields excluded.
   447  		{
   448  			stmt:    `SELECT mean(*) FROM strings`,
   449  			rewrite: `SELECT mean(value::float) AS mean_value FROM strings`,
   450  		},
   451  
   452  		{
   453  			stmt:    `SELECT mean(*) FROM bools`,
   454  			rewrite: `SELECT mean(value::float) AS mean_value FROM bools`,
   455  		},
   456  
   457  		// Wildcard function with an alias.
   458  		{
   459  			stmt:    `SELECT mean(*) AS alias FROM cpu`,
   460  			rewrite: `SELECT mean(value1::float) AS alias_value1, mean(value2::integer) AS alias_value2 FROM cpu`,
   461  		},
   462  
   463  		// Query regex
   464  		{
   465  			stmt:    `SELECT /1/ FROM cpu`,
   466  			rewrite: `SELECT value1::float FROM cpu`,
   467  		},
   468  
   469  		{
   470  			stmt:    `SELECT value1 FROM cpu GROUP BY /h/`,
   471  			rewrite: `SELECT value1::float FROM cpu GROUP BY host`,
   472  		},
   473  
   474  		// Query regex
   475  		{
   476  			stmt:    `SELECT mean(/1/) FROM cpu`,
   477  			rewrite: `SELECT mean(value1::float) AS mean_value1 FROM cpu`,
   478  		},
   479  		// Rewrite subquery
   480  		{
   481  			stmt:    `SELECT * FROM (SELECT mean(value1) FROM cpu GROUP BY host) GROUP BY *`,
   482  			rewrite: `SELECT mean::float FROM (SELECT mean(value1::float) FROM cpu GROUP BY host) GROUP BY host`,
   483  		},
   484  
   485  		// Invalid queries that can't be rewritten should return an error (to
   486  		// avoid a panic in the query engine)
   487  		{
   488  			stmt: `SELECT count(*) / 2 FROM cpu`,
   489  			err:  `unsupported expression with wildcard: count(*) / 2`,
   490  		},
   491  
   492  		{
   493  			stmt: `SELECT * / 2 FROM (SELECT count(*) FROM cpu)`,
   494  			err:  `unsupported expression with wildcard: * / 2`,
   495  		},
   496  
   497  		{
   498  			stmt: `SELECT count(/value/) / 2 FROM cpu`,
   499  			err:  `unsupported expression with regex field: count(/value/) / 2`,
   500  		},
   501  
   502  		// This one should be possible though since there's no wildcard in the
   503  		// binary expression.
   504  		{
   505  			stmt:    `SELECT value1 + value2, * FROM cpu`,
   506  			rewrite: `SELECT value1::float + value2::integer, host::tag, region::tag, value1::float, value2::integer FROM cpu`,
   507  		},
   508  
   509  		{
   510  			stmt:    `SELECT value1 + value2, /value/ FROM cpu`,
   511  			rewrite: `SELECT value1::float + value2::integer, value1::float, value2::integer FROM cpu`,
   512  		},
   513  	}
   514  
   515  	for i, tt := range tests {
   516  		// Parse statement.
   517  		stmt, err := influxql.NewParser(strings.NewReader(tt.stmt)).ParseStatement()
   518  		if err != nil {
   519  			t.Fatalf("invalid statement: %q: %s", tt.stmt, err)
   520  		}
   521  
   522  		var mapper FieldMapper
   523  		mapper.FieldDimensionsFn = func(m *influxql.Measurement) (fields map[string]influxql.DataType, dimensions map[string]struct{}, err error) {
   524  			switch m.Name {
   525  			case "cpu":
   526  				fields = map[string]influxql.DataType{
   527  					"value1": influxql.Float,
   528  					"value2": influxql.Integer,
   529  				}
   530  			case "strings":
   531  				fields = map[string]influxql.DataType{
   532  					"value":  influxql.Float,
   533  					"string": influxql.String,
   534  				}
   535  			case "bools":
   536  				fields = map[string]influxql.DataType{
   537  					"value": influxql.Float,
   538  					"bool":  influxql.Boolean,
   539  				}
   540  			}
   541  			dimensions = map[string]struct{}{"host": struct{}{}, "region": struct{}{}}
   542  			return
   543  		}
   544  
   545  		// Rewrite statement.
   546  		rw, err := stmt.(*influxql.SelectStatement).RewriteFields(&mapper)
   547  		if tt.err != "" {
   548  			if err != nil && err.Error() != tt.err {
   549  				t.Errorf("%d. %q: unexpected error: %s != %s", i, tt.stmt, err.Error(), tt.err)
   550  			} else if err == nil {
   551  				t.Errorf("%d. %q: expected error", i, tt.stmt)
   552  			}
   553  		} else {
   554  			if err != nil {
   555  				t.Errorf("%d. %q: error: %s", i, tt.stmt, err)
   556  			} else if rw == nil && tt.err == "" {
   557  				t.Errorf("%d. %q: unexpected nil statement", i, tt.stmt)
   558  			} else if rw := rw.String(); tt.rewrite != rw {
   559  				t.Errorf("%d. %q: unexpected rewrite:\n\nexp=%s\n\ngot=%s\n\n", i, tt.stmt, tt.rewrite, rw)
   560  			}
   561  		}
   562  	}
   563  }
   564  
   565  // Test SELECT statement regex conditions rewrite.
   566  func TestSelectStatement_RewriteRegexConditions(t *testing.T) {
   567  	var tests = []struct {
   568  		in  string
   569  		out string
   570  	}{
   571  		{in: `SELECT value FROM cpu`, out: `SELECT value FROM cpu`},
   572  		{in: `SELECT value FROM cpu WHERE host = 'server-1'`, out: `SELECT value FROM cpu WHERE host = 'server-1'`},
   573  		{in: `SELECT value FROM cpu WHERE host = 'server-1'`, out: `SELECT value FROM cpu WHERE host = 'server-1'`},
   574  		{in: `SELECT value FROM cpu WHERE host != 'server-1'`, out: `SELECT value FROM cpu WHERE host != 'server-1'`},
   575  
   576  		// Non matching regex
   577  		{in: `SELECT value FROM cpu WHERE host =~ /server-1|server-2|server-3/`, out: `SELECT value FROM cpu WHERE host =~ /server-1|server-2|server-3/`},
   578  		{in: `SELECT value FROM cpu WHERE host =~ /server-1/`, out: `SELECT value FROM cpu WHERE host =~ /server-1/`},
   579  		{in: `SELECT value FROM cpu WHERE host !~ /server-1/`, out: `SELECT value FROM cpu WHERE host !~ /server-1/`},
   580  		{in: `SELECT value FROM cpu WHERE host =~ /^server-1/`, out: `SELECT value FROM cpu WHERE host =~ /^server-1/`},
   581  		{in: `SELECT value FROM cpu WHERE host =~ /server-1$/`, out: `SELECT value FROM cpu WHERE host =~ /server-1$/`},
   582  		{in: `SELECT value FROM cpu WHERE host !~ /\^server-1$/`, out: `SELECT value FROM cpu WHERE host !~ /\^server-1$/`},
   583  		{in: `SELECT value FROM cpu WHERE host !~ /\^$/`, out: `SELECT value FROM cpu WHERE host !~ /\^$/`},
   584  		{in: `SELECT value FROM cpu WHERE host !~ /^server-1\$/`, out: `SELECT value FROM cpu WHERE host !~ /^server-1\$/`},
   585  		{in: `SELECT value FROM cpu WHERE host =~ /^\$/`, out: `SELECT value FROM cpu WHERE host =~ /^\$/`},
   586  		{in: `SELECT value FROM cpu WHERE host !~ /^a/`, out: `SELECT value FROM cpu WHERE host !~ /^a/`},
   587  
   588  		// These regexes are not supported due to the presence of escaped or meta characters.
   589  		{in: `SELECT value FROM cpu WHERE host !~ /^?a$/`, out: `SELECT value FROM cpu WHERE host !~ /^?a$/`},
   590  		{in: `SELECT value FROM cpu WHERE host !~ /^a*$/`, out: `SELECT value FROM cpu WHERE host !~ /^a*$/`},
   591  		{in: `SELECT value FROM cpu WHERE host !~ /^a.b$/`, out: `SELECT value FROM cpu WHERE host !~ /^a.b$/`},
   592  		{in: `SELECT value FROM cpu WHERE host !~ /^ab+$/`, out: `SELECT value FROM cpu WHERE host !~ /^ab+$/`},
   593  
   594  		// These regexes are not supported due to the presence of unsupported regex flags.
   595  		{in: `SELECT value FROM cpu WHERE host =~ /(?i)^SeRvEr01$/`, out: `SELECT value FROM cpu WHERE host =~ /(?i)^SeRvEr01$/`},
   596  
   597  		// These regexes are not supported due to large character class(es).
   598  		{in: `SELECT value FROM cpu WHERE host =~ /^[^abcd]$/`, out: `SELECT value FROM cpu WHERE host =~ /^[^abcd]$/`},
   599  
   600  		// These regexes all match and will be rewritten.
   601  		{in: `SELECT value FROM cpu WHERE host !~ /^a[2]$/`, out: `SELECT value FROM cpu WHERE host != 'a2'`},
   602  		{in: `SELECT value FROM cpu WHERE host =~ /^server-1$/`, out: `SELECT value FROM cpu WHERE host = 'server-1'`},
   603  		{in: `SELECT value FROM cpu WHERE host !~ /^server-1$/`, out: `SELECT value FROM cpu WHERE host != 'server-1'`},
   604  		{in: `SELECT value FROM cpu WHERE host =~ /^server 1$/`, out: `SELECT value FROM cpu WHERE host = 'server 1'`},
   605  		{in: `SELECT value FROM cpu WHERE host =~ /^$/`, out: `SELECT value FROM cpu WHERE host = ''`},
   606  		{in: `SELECT value FROM cpu WHERE host !~ /^$/`, out: `SELECT value FROM cpu WHERE host != ''`},
   607  		{in: `SELECT value FROM cpu WHERE host =~ /^server-1$/ OR host =~ /^server-2$/`, out: `SELECT value FROM cpu WHERE host = 'server-1' OR host = 'server-2'`},
   608  		{in: `SELECT value FROM cpu WHERE host =~ /^server-1$/ OR host =~ /^server]a$/`, out: `SELECT value FROM cpu WHERE host = 'server-1' OR host = 'server]a'`},
   609  		{in: `SELECT value FROM cpu WHERE host =~ /^hello\?$/`, out: `SELECT value FROM cpu WHERE host = 'hello?'`},
   610  		{in: `SELECT value FROM cpu WHERE host !~ /^\\$/`, out: `SELECT value FROM cpu WHERE host != '\\'`},
   611  		{in: `SELECT value FROM cpu WHERE host !~ /^\\\$$/`, out: `SELECT value FROM cpu WHERE host != '\\$'`},
   612  		// This is supported, but annoying to write and the below queries satisfy this condition.
   613  		//{in: `SELECT value FROM cpu WHERE host =~ /^hello\world$/`, out: `SELECT value FROM cpu WHERE host =~ /^hello\world$/`},
   614  		{in: `SELECT value FROM cpu WHERE host =~ /^(server-1|server-2|server-3)$/`, out: `SELECT value FROM cpu WHERE host = 'server-1' OR host = 'server-2' OR host = 'server-3'`},
   615  		{in: `SELECT value FROM cpu WHERE host !~ /^(foo|bar)$/`, out: `SELECT value FROM cpu WHERE host != 'foo' AND host != 'bar'`},
   616  		{in: `SELECT value FROM cpu WHERE host !~ /^\d$/`, out: `SELECT value FROM cpu WHERE host != '0' AND host != '1' AND host != '2' AND host != '3' AND host != '4' AND host != '5' AND host != '6' AND host != '7' AND host != '8' AND host != '9'`},
   617  		{in: `SELECT value FROM cpu WHERE host !~ /^[a-z]$/`, out: `SELECT value FROM cpu WHERE host != 'a' AND host != 'b' AND host != 'c' AND host != 'd' AND host != 'e' AND host != 'f' AND host != 'g' AND host != 'h' AND host != 'i' AND host != 'j' AND host != 'k' AND host != 'l' AND host != 'm' AND host != 'n' AND host != 'o' AND host != 'p' AND host != 'q' AND host != 'r' AND host != 's' AND host != 't' AND host != 'u' AND host != 'v' AND host != 'w' AND host != 'x' AND host != 'y' AND host != 'z'`},
   618  
   619  		{in: `SELECT value FROM cpu WHERE host =~ /^[ab]{3}$/`, out: `SELECT value FROM cpu WHERE host = 'aaa' OR host = 'aab' OR host = 'aba' OR host = 'abb' OR host = 'baa' OR host = 'bab' OR host = 'bba' OR host = 'bbb'`},
   620  	}
   621  
   622  	for i, test := range tests {
   623  		stmt, err := influxql.NewParser(strings.NewReader(test.in)).ParseStatement()
   624  		if err != nil {
   625  			t.Fatalf("[Example %d], %v", i, err)
   626  		}
   627  
   628  		// Rewrite any supported regex conditions.
   629  		stmt.(*influxql.SelectStatement).RewriteRegexConditions()
   630  
   631  		// Get the expected rewritten statement.
   632  		expStmt, err := influxql.NewParser(strings.NewReader(test.out)).ParseStatement()
   633  		if err != nil {
   634  			t.Fatalf("[Example %d], %v", i, err)
   635  		}
   636  
   637  		// Compare the (potentially) rewritten AST to the expected AST.
   638  		if got, exp := stmt, expStmt; !reflect.DeepEqual(got, exp) {
   639  			t.Errorf("[Example %d]\nattempting %v\ngot %v\n%s\n\nexpected %v\n%s\n", i+1, test.in, got, mustMarshalJSON(got), exp, mustMarshalJSON(exp))
   640  		}
   641  	}
   642  }
   643  
   644  // Test SELECT statement time field rewrite.
   645  func TestSelectStatement_RewriteTimeFields(t *testing.T) {
   646  	var tests = []struct {
   647  		s    string
   648  		stmt influxql.Statement
   649  	}{
   650  		{
   651  			s: `SELECT time, field1 FROM cpu`,
   652  			stmt: &influxql.SelectStatement{
   653  				IsRawQuery: true,
   654  				Fields: []*influxql.Field{
   655  					{Expr: &influxql.VarRef{Val: "field1"}},
   656  				},
   657  				Sources: []influxql.Source{
   658  					&influxql.Measurement{Name: "cpu"},
   659  				},
   660  			},
   661  		},
   662  		{
   663  			s: `SELECT time AS timestamp, field1 FROM cpu`,
   664  			stmt: &influxql.SelectStatement{
   665  				IsRawQuery: true,
   666  				Fields: []*influxql.Field{
   667  					{Expr: &influxql.VarRef{Val: "field1"}},
   668  				},
   669  				Sources: []influxql.Source{
   670  					&influxql.Measurement{Name: "cpu"},
   671  				},
   672  				TimeAlias: "timestamp",
   673  			},
   674  		},
   675  	}
   676  
   677  	for i, tt := range tests {
   678  		// Parse statement.
   679  		stmt, err := influxql.NewParser(strings.NewReader(tt.s)).ParseStatement()
   680  		if err != nil {
   681  			t.Fatalf("invalid statement: %q: %s", tt.s, err)
   682  		}
   683  
   684  		// Rewrite statement.
   685  		stmt.(*influxql.SelectStatement).RewriteTimeFields()
   686  		if !reflect.DeepEqual(tt.stmt, stmt) {
   687  			t.Logf("\n# %s\nexp=%s\ngot=%s\n", tt.s, mustMarshalJSON(tt.stmt), mustMarshalJSON(stmt))
   688  			t.Logf("\nSQL exp=%s\nSQL got=%s\n", tt.stmt.String(), stmt.String())
   689  			t.Errorf("%d. %q\n\nstmt mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.stmt, stmt)
   690  		}
   691  	}
   692  }
   693  
   694  // Ensure that the IsRawQuery flag gets set properly
   695  func TestSelectStatement_IsRawQuerySet(t *testing.T) {
   696  	var tests = []struct {
   697  		stmt  string
   698  		isRaw bool
   699  	}{
   700  		{
   701  			stmt:  "select * from foo",
   702  			isRaw: true,
   703  		},
   704  		{
   705  			stmt:  "select value1,value2 from foo",
   706  			isRaw: true,
   707  		},
   708  		{
   709  			stmt:  "select value1,value2 from foo, time(10m)",
   710  			isRaw: true,
   711  		},
   712  		{
   713  			stmt:  "select mean(value) from foo where time < now() group by time(5m)",
   714  			isRaw: false,
   715  		},
   716  		{
   717  			stmt:  "select mean(value) from foo group by bar",
   718  			isRaw: false,
   719  		},
   720  		{
   721  			stmt:  "select mean(value) from foo group by *",
   722  			isRaw: false,
   723  		},
   724  		{
   725  			stmt:  "select mean(value) from foo group by *",
   726  			isRaw: false,
   727  		},
   728  	}
   729  
   730  	for _, tt := range tests {
   731  		s := MustParseSelectStatement(tt.stmt)
   732  		if s.IsRawQuery != tt.isRaw {
   733  			t.Errorf("'%s', IsRawQuery should be %v", tt.stmt, tt.isRaw)
   734  		}
   735  	}
   736  }
   737  
   738  // Ensure binary expression names can be evaluated.
   739  func TestBinaryExprName(t *testing.T) {
   740  	for i, tt := range []struct {
   741  		expr string
   742  		name string
   743  	}{
   744  		{expr: `value + 1`, name: `value`},
   745  		{expr: `"user" / total`, name: `user_total`},
   746  		{expr: `("user" + total) / total`, name: `user_total_total`},
   747  	} {
   748  		expr := influxql.MustParseExpr(tt.expr)
   749  		switch expr := expr.(type) {
   750  		case *influxql.BinaryExpr:
   751  			name := influxql.BinaryExprName(expr)
   752  			if name != tt.name {
   753  				t.Errorf("%d. unexpected name %s, got %s", i, name, tt.name)
   754  			}
   755  		default:
   756  			t.Errorf("%d. unexpected expr type: %T", i, expr)
   757  		}
   758  	}
   759  }
   760  
   761  func TestConditionExpr(t *testing.T) {
   762  	mustParseTime := func(value string) time.Time {
   763  		ts, err := time.Parse(time.RFC3339, value)
   764  		if err != nil {
   765  			t.Fatalf("unable to parse time: %s", err)
   766  		}
   767  		return ts
   768  	}
   769  	now := mustParseTime("2000-01-01T00:00:00Z")
   770  	valuer := influxql.NowValuer{Now: now}
   771  
   772  	for _, tt := range []struct {
   773  		s        string
   774  		cond     string
   775  		min, max time.Time
   776  		err      string
   777  	}{
   778  		{s: `host = 'server01'`, cond: `host = 'server01'`},
   779  		{s: `time >= '2000-01-01T00:00:00Z' AND time < '2000-01-01T01:00:00Z'`,
   780  			min: mustParseTime("2000-01-01T00:00:00Z"),
   781  			max: mustParseTime("2000-01-01T01:00:00Z").Add(-1)},
   782  		{s: `host = 'server01' AND (region = 'uswest' AND time >= now() - 10m)`,
   783  			cond: `host = 'server01' AND (region = 'uswest')`,
   784  			min:  mustParseTime("1999-12-31T23:50:00Z")},
   785  		{s: `(host = 'server01' AND region = 'uswest') AND time >= now() - 10m`,
   786  			cond: `host = 'server01' AND region = 'uswest'`,
   787  			min:  mustParseTime("1999-12-31T23:50:00Z")},
   788  		{s: `host = 'server01' AND (time >= '2000-01-01T00:00:00Z' AND time < '2000-01-01T01:00:00Z')`,
   789  			cond: `host = 'server01'`,
   790  			min:  mustParseTime("2000-01-01T00:00:00Z"),
   791  			max:  mustParseTime("2000-01-01T01:00:00Z").Add(-1)},
   792  		{s: `(time >= '2000-01-01T00:00:00Z' AND time < '2000-01-01T01:00:00Z') AND host = 'server01'`,
   793  			cond: `host = 'server01'`,
   794  			min:  mustParseTime("2000-01-01T00:00:00Z"),
   795  			max:  mustParseTime("2000-01-01T01:00:00Z").Add(-1)},
   796  		{s: `'2000-01-01T00:00:00Z' <= time AND '2000-01-01T01:00:00Z' > time`,
   797  			min: mustParseTime("2000-01-01T00:00:00Z"),
   798  			max: mustParseTime("2000-01-01T01:00:00Z").Add(-1)},
   799  		{s: `'2000-01-01T00:00:00Z' < time AND '2000-01-01T01:00:00Z' >= time`,
   800  			min: mustParseTime("2000-01-01T00:00:00Z").Add(1),
   801  			max: mustParseTime("2000-01-01T01:00:00Z")},
   802  		{s: `time = '2000-01-01T00:00:00Z'`,
   803  			min: mustParseTime("2000-01-01T00:00:00Z"),
   804  			max: mustParseTime("2000-01-01T00:00:00Z")},
   805  		{s: `time >= 10s`, min: mustParseTime("1970-01-01T00:00:10Z")},
   806  		{s: `time >= 10000000000`, min: mustParseTime("1970-01-01T00:00:10Z")},
   807  		{s: `time >= 10000000000.0`, min: mustParseTime("1970-01-01T00:00:10Z")},
   808  		{s: `time > now()`, min: now.Add(1)},
   809  		{s: `value`, err: `invalid condition expression: value`},
   810  		{s: `4`, err: `invalid condition expression: 4`},
   811  		{s: `time >= 'today'`, err: `invalid operation: time and *influxql.StringLiteral are not compatible`},
   812  		{s: `time != '2000-01-01T00:00:00Z'`, err: `invalid time comparison operator: !=`},
   813  		// This query makes no logical sense, but it's common enough that we pretend
   814  		// it does. Technically, this should be illegal because the AND has higher precedence
   815  		// than the OR so the AND only applies to the server02 tag, but a person's intention
   816  		// is to have it apply to both and previous versions worked that way.
   817  		{s: `host = 'server01' OR host = 'server02' AND time >= now() - 10m`,
   818  			cond: `host = 'server01' OR host = 'server02'`,
   819  			min:  mustParseTime("1999-12-31T23:50:00Z")},
   820  		// TODO(jsternberg): This should be an error, but we can't because the above query
   821  		// needs to work. Until we can work a way for the above to work or at least get
   822  		// a warning message for people to transition to a correct syntax, the bad behavior
   823  		// stays.
   824  		//{s: `host = 'server01' OR (time >= now() - 10m AND host = 'server02')`, err: `cannot use OR with time conditions`},
   825  		{s: `value AND host = 'server01'`, err: `invalid condition expression: value`},
   826  		{s: `host = 'server01' OR (value)`, err: `invalid condition expression: value`},
   827  		{s: `time > '2262-04-11 23:47:17'`, err: `time 2262-04-11T23:47:17Z overflows time literal`},
   828  		{s: `time > '1677-09-20 19:12:43'`, err: `time 1677-09-20T19:12:43Z underflows time literal`},
   829  		{s: `true AND (false OR product = 'xyz')`,
   830  			cond: `product = 'xyz'`,
   831  		},
   832  		{s: `'a' = 'a'`, cond: ``},
   833  		{s: `value > 0 OR true`, cond: ``},
   834  		{s: `host = 'server01' AND false`, cond: `false`},
   835  		{s: `TIME >= '2000-01-01T00:00:00Z'`, min: mustParseTime("2000-01-01T00:00:00Z")},
   836  		{s: `'2000-01-01T00:00:00Z' <= TIME`, min: mustParseTime("2000-01-01T00:00:00Z")},
   837  		// Remove enclosing parentheses
   838  		{s: `(host = 'server01')`, cond: `host = 'server01'`},
   839  		// Preserve nested parentheses
   840  		{s: `host = 'server01' AND (region = 'region01' OR region = 'region02')`,
   841  			cond: `host = 'server01' AND (region = 'region01' OR region = 'region02')`,
   842  		},
   843  	} {
   844  		t.Run(tt.s, func(t *testing.T) {
   845  			expr, err := influxql.ParseExpr(tt.s)
   846  			if err != nil {
   847  				t.Fatalf("unexpected error: %s", err)
   848  			}
   849  
   850  			cond, timeRange, err := influxql.ConditionExpr(expr, &valuer)
   851  			if err != nil {
   852  				if tt.err == "" {
   853  					t.Fatalf("unexpected error: %s", err)
   854  				} else if have, want := err.Error(), tt.err; have != want {
   855  					t.Fatalf("unexpected error: %s != %s", have, want)
   856  				}
   857  			}
   858  			if cond != nil {
   859  				if have, want := cond.String(), tt.cond; have != want {
   860  					t.Errorf("unexpected condition:\nhave=%s\nwant=%s", have, want)
   861  				}
   862  			} else {
   863  				if have, want := "", tt.cond; have != want {
   864  					t.Errorf("unexpected condition:\nhave=%s\nwant=%s", have, want)
   865  				}
   866  			}
   867  			if have, want := timeRange.Min, tt.min; !have.Equal(want) {
   868  				t.Errorf("unexpected min time:\nhave=%s\nwant=%s", have, want)
   869  			}
   870  			if have, want := timeRange.Max, tt.max; !have.Equal(want) {
   871  				t.Errorf("unexpected max time:\nhave=%s\nwant=%s", have, want)
   872  			}
   873  		})
   874  	}
   875  }
   876  
   877  // Ensure an AST node can be rewritten.
   878  func TestRewrite(t *testing.T) {
   879  	expr := MustParseExpr(`time > 1 OR foo = 2`)
   880  
   881  	// Flip LHS & RHS in all binary expressions.
   882  	act := influxql.RewriteFunc(expr, func(n influxql.Node) influxql.Node {
   883  		switch n := n.(type) {
   884  		case *influxql.BinaryExpr:
   885  			return &influxql.BinaryExpr{Op: n.Op, LHS: n.RHS, RHS: n.LHS}
   886  		default:
   887  			return n
   888  		}
   889  	})
   890  
   891  	// Verify that everything is flipped.
   892  	if act := act.String(); act != `2 = foo OR 1 > time` {
   893  		t.Fatalf("unexpected result: %s", act)
   894  	}
   895  }
   896  
   897  // Ensure an Expr can be rewritten handling nils.
   898  func TestRewriteExpr(t *testing.T) {
   899  	expr := MustParseExpr(`(time > 1 AND time < 10) OR foo = 2`)
   900  
   901  	// Remove all time expressions.
   902  	act := influxql.RewriteExpr(expr, func(e influxql.Expr) influxql.Expr {
   903  		switch e := e.(type) {
   904  		case *influxql.BinaryExpr:
   905  			if lhs, ok := e.LHS.(*influxql.VarRef); ok && lhs.Val == "time" {
   906  				return nil
   907  			}
   908  		}
   909  		return e
   910  	})
   911  
   912  	// Verify that everything is flipped.
   913  	if act := act.String(); act != `foo = 2` {
   914  		t.Fatalf("unexpected result: %s", act)
   915  	}
   916  }
   917  
   918  // Ensure that the String() value of a statement is parseable
   919  func TestParseString(t *testing.T) {
   920  	var tests = []struct {
   921  		stmt string
   922  	}{
   923  		{
   924  			stmt: `SELECT "cpu load" FROM myseries`,
   925  		},
   926  		{
   927  			stmt: `SELECT "cpu load" FROM "my series"`,
   928  		},
   929  		{
   930  			stmt: `SELECT "cpu\"load" FROM myseries`,
   931  		},
   932  		{
   933  			stmt: `SELECT "cpu'load" FROM myseries`,
   934  		},
   935  		{
   936  			stmt: `SELECT "cpu load" FROM "my\"series"`,
   937  		},
   938  		{
   939  			stmt: `SELECT "field with spaces" FROM "\"ugly\" db"."\"ugly\" rp"."\"ugly\" measurement"`,
   940  		},
   941  		{
   942  			stmt: `SELECT * FROM myseries`,
   943  		},
   944  		{
   945  			stmt: `DROP DATABASE "!"`,
   946  		},
   947  		{
   948  			stmt: `DROP RETENTION POLICY "my rp" ON "a database"`,
   949  		},
   950  		{
   951  			stmt: `CREATE RETENTION POLICY "my rp" ON "a database" DURATION 1d REPLICATION 1`,
   952  		},
   953  		{
   954  			stmt: `ALTER RETENTION POLICY "my rp" ON "a database" DEFAULT`,
   955  		},
   956  		{
   957  			stmt: `SHOW RETENTION POLICIES ON "a database"`,
   958  		},
   959  		{
   960  			stmt: `SHOW TAG VALUES WITH KEY IN ("a long name", short)`,
   961  		},
   962  		{
   963  			stmt: `DROP CONTINUOUS QUERY "my query" ON "my database"`,
   964  		},
   965  		// See issues https://github.com/influxdata/influxdb/issues/1647
   966  		// and https://github.com/influxdata/influxdb/issues/4404
   967  		//{
   968  		//	stmt: `DELETE FROM "my db"."my rp"."my measurement"`,
   969  		//},
   970  		{
   971  			stmt: `DROP SUBSCRIPTION "ugly \"subscription\" name" ON "\"my\" db"."\"my\" rp"`,
   972  		},
   973  		{
   974  			stmt: `CREATE SUBSCRIPTION "ugly \"subscription\" name" ON "\"my\" db"."\"my\" rp" DESTINATIONS ALL 'my host', 'my other host'`,
   975  		},
   976  		{
   977  			stmt: `SHOW MEASUREMENTS WITH MEASUREMENT =~ /foo/`,
   978  		},
   979  		{
   980  			stmt: `SHOW MEASUREMENTS WITH MEASUREMENT = "and/or"`,
   981  		},
   982  		{
   983  			stmt: `DROP USER "user with spaces"`,
   984  		},
   985  		{
   986  			stmt: `GRANT ALL PRIVILEGES ON "db with spaces" TO "user with spaces"`,
   987  		},
   988  		{
   989  			stmt: `GRANT ALL PRIVILEGES TO "user with spaces"`,
   990  		},
   991  		{
   992  			stmt: `SHOW GRANTS FOR "user with spaces"`,
   993  		},
   994  		{
   995  			stmt: `REVOKE ALL PRIVILEGES ON "db with spaces" FROM "user with spaces"`,
   996  		},
   997  		{
   998  			stmt: `REVOKE ALL PRIVILEGES FROM "user with spaces"`,
   999  		},
  1000  		{
  1001  			stmt: `CREATE DATABASE "db with spaces"`,
  1002  		},
  1003  	}
  1004  
  1005  	for _, tt := range tests {
  1006  		// Parse statement.
  1007  		stmt, err := influxql.NewParser(strings.NewReader(tt.stmt)).ParseStatement()
  1008  		if err != nil {
  1009  			t.Fatalf("invalid statement: %q: %s", tt.stmt, err)
  1010  		}
  1011  
  1012  		stmtCopy, err := influxql.NewParser(strings.NewReader(stmt.String())).ParseStatement()
  1013  		if err != nil {
  1014  			t.Fatalf("failed to parse string: %v\norig: %v\ngot: %v", err, tt.stmt, stmt.String())
  1015  		}
  1016  
  1017  		if !reflect.DeepEqual(stmt, stmtCopy) {
  1018  			t.Fatalf("statement changed after stringifying and re-parsing:\noriginal : %v\nre-parsed: %v\n", tt.stmt, stmtCopy.String())
  1019  		}
  1020  	}
  1021  }
  1022  
  1023  // Ensure an expression can be reduced.
  1024  func TestEval(t *testing.T) {
  1025  	for i, tt := range []struct {
  1026  		in   string
  1027  		out  interface{}
  1028  		data map[string]interface{}
  1029  	}{
  1030  		// Number literals.
  1031  		{in: `1 + 2`, out: int64(3)},
  1032  		{in: `(foo*2) + ( (4/2) + (3 * 5) - 0.5 )`, out: float64(26.5), data: map[string]interface{}{"foo": float64(5)}},
  1033  		{in: `foo / 2`, out: float64(2), data: map[string]interface{}{"foo": float64(4)}},
  1034  		{in: `4 = 4`, out: true},
  1035  		{in: `4 <> 4`, out: false},
  1036  		{in: `6 > 4`, out: true},
  1037  		{in: `4 >= 4`, out: true},
  1038  		{in: `4 < 6`, out: true},
  1039  		{in: `4 <= 4`, out: true},
  1040  		{in: `4 AND 5`, out: nil},
  1041  		{in: `0 = 'test'`, out: false},
  1042  		{in: `1.0 = 1`, out: true},
  1043  		{in: `1.2 = 1`, out: false},
  1044  		{in: `-1 = 9223372036854775808`, out: false},
  1045  		{in: `-1 != 9223372036854775808`, out: true},
  1046  		{in: `-1 < 9223372036854775808`, out: true},
  1047  		{in: `-1 <= 9223372036854775808`, out: true},
  1048  		{in: `-1 > 9223372036854775808`, out: false},
  1049  		{in: `-1 >= 9223372036854775808`, out: false},
  1050  		{in: `9223372036854775808 = -1`, out: false},
  1051  		{in: `9223372036854775808 != -1`, out: true},
  1052  		{in: `9223372036854775808 < -1`, out: false},
  1053  		{in: `9223372036854775808 <= -1`, out: false},
  1054  		{in: `9223372036854775808 > -1`, out: true},
  1055  		{in: `9223372036854775808 >= -1`, out: true},
  1056  		{in: `9223372036854775808 = 9223372036854775808`, out: true},
  1057  		{in: `9223372036854775808 != 9223372036854775808`, out: false},
  1058  		{in: `9223372036854775808 < 9223372036854775808`, out: false},
  1059  		{in: `9223372036854775808 <= 9223372036854775808`, out: true},
  1060  		{in: `9223372036854775808 > 9223372036854775808`, out: false},
  1061  		{in: `9223372036854775808 >= 9223372036854775808`, out: true},
  1062  		{in: `9223372036854775809 = 9223372036854775808`, out: false},
  1063  		{in: `9223372036854775809 != 9223372036854775808`, out: true},
  1064  		{in: `9223372036854775809 < 9223372036854775808`, out: false},
  1065  		{in: `9223372036854775809 <= 9223372036854775808`, out: false},
  1066  		{in: `9223372036854775809 > 9223372036854775808`, out: true},
  1067  		{in: `9223372036854775809 >= 9223372036854775808`, out: true},
  1068  		{in: `9223372036854775808 / 0`, out: uint64(0)},
  1069  		{in: `9223372036854775808 + 1`, out: uint64(9223372036854775809)},
  1070  		{in: `9223372036854775808 - 1`, out: uint64(9223372036854775807)},
  1071  		{in: `9223372036854775809 - 9223372036854775808`, out: uint64(1)},
  1072  
  1073  		// Boolean literals.
  1074  		{in: `true AND false`, out: false},
  1075  		{in: `true OR false`, out: true},
  1076  		{in: `false = 4`, out: false},
  1077  
  1078  		// String literals.
  1079  		{in: `'foo' = 'bar'`, out: false},
  1080  		{in: `'foo' = 'foo'`, out: true},
  1081  		{in: `'' = 4`, out: false},
  1082  
  1083  		// Regex literals.
  1084  		{in: `'foo' =~ /f.*/`, out: true},
  1085  		{in: `'foo' =~ /b.*/`, out: false},
  1086  		{in: `'foo' !~ /f.*/`, out: false},
  1087  		{in: `'foo' !~ /b.*/`, out: true},
  1088  
  1089  		// Variable references.
  1090  		{in: `foo`, out: "bar", data: map[string]interface{}{"foo": "bar"}},
  1091  		{in: `foo = 'bar'`, out: true, data: map[string]interface{}{"foo": "bar"}},
  1092  		{in: `foo = 'bar'`, out: false, data: map[string]interface{}{"foo": nil}},
  1093  		{in: `'bar' = foo`, out: false, data: map[string]interface{}{"foo": nil}},
  1094  		{in: `foo <> 'bar'`, out: true, data: map[string]interface{}{"foo": "xxx"}},
  1095  		{in: `foo =~ /b.*/`, out: true, data: map[string]interface{}{"foo": "bar"}},
  1096  		{in: `foo !~ /b.*/`, out: false, data: map[string]interface{}{"foo": "bar"}},
  1097  		{in: `foo > 2 OR bar > 3`, out: true, data: map[string]interface{}{"foo": float64(4)}},
  1098  		{in: `foo > 2 OR bar > 3`, out: true, data: map[string]interface{}{"bar": float64(4)}},
  1099  	} {
  1100  		// Evaluate expression.
  1101  		out := influxql.Eval(MustParseExpr(tt.in), tt.data)
  1102  
  1103  		// Compare with expected output.
  1104  		if !reflect.DeepEqual(tt.out, out) {
  1105  			t.Errorf("%d. %s: unexpected output:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.in, tt.out, out)
  1106  			continue
  1107  		}
  1108  	}
  1109  }
  1110  
  1111  type EvalFixture map[string]map[string]influxql.DataType
  1112  
  1113  func (e EvalFixture) MapType(measurement *influxql.Measurement, field string) influxql.DataType {
  1114  	m := e[measurement.Name]
  1115  	if m == nil {
  1116  		return influxql.Unknown
  1117  	}
  1118  	return m[field]
  1119  }
  1120  
  1121  func (e EvalFixture) CallType(name string, args []influxql.DataType) (influxql.DataType, error) {
  1122  	switch name {
  1123  	case "mean", "median", "integral", "stddev":
  1124  		return influxql.Float, nil
  1125  	case "count":
  1126  		return influxql.Integer, nil
  1127  	case "elapsed":
  1128  		return influxql.Integer, nil
  1129  	default:
  1130  		return args[0], nil
  1131  	}
  1132  }
  1133  
  1134  func TestEvalType(t *testing.T) {
  1135  	for i, tt := range []struct {
  1136  		name string
  1137  		in   string
  1138  		typ  influxql.DataType
  1139  		err  string
  1140  		data EvalFixture
  1141  	}{
  1142  		{
  1143  			name: `a single data type`,
  1144  			in:   `min(value)`,
  1145  			typ:  influxql.Integer,
  1146  			data: EvalFixture{
  1147  				"cpu": map[string]influxql.DataType{
  1148  					"value": influxql.Integer,
  1149  				},
  1150  			},
  1151  		},
  1152  		{
  1153  			name: `multiple data types`,
  1154  			in:   `min(value)`,
  1155  			typ:  influxql.Integer,
  1156  			data: EvalFixture{
  1157  				"cpu": map[string]influxql.DataType{
  1158  					"value": influxql.Integer,
  1159  				},
  1160  				"mem": map[string]influxql.DataType{
  1161  					"value": influxql.String,
  1162  				},
  1163  			},
  1164  		},
  1165  		{
  1166  			name: `count() with a float`,
  1167  			in:   `count(value)`,
  1168  			typ:  influxql.Integer,
  1169  			data: EvalFixture{
  1170  				"cpu": map[string]influxql.DataType{
  1171  					"value": influxql.Float,
  1172  				},
  1173  			},
  1174  		},
  1175  		{
  1176  			name: `mean() with an integer`,
  1177  			in:   `mean(value)`,
  1178  			typ:  influxql.Float,
  1179  			data: EvalFixture{
  1180  				"cpu": map[string]influxql.DataType{
  1181  					"value": influxql.Integer,
  1182  				},
  1183  			},
  1184  		},
  1185  		{
  1186  			name: `stddev() with an integer`,
  1187  			in:   `stddev(value)`,
  1188  			typ:  influxql.Float,
  1189  			data: EvalFixture{
  1190  				"cpu": map[string]influxql.DataType{
  1191  					"value": influxql.Integer,
  1192  				},
  1193  			},
  1194  		},
  1195  		{
  1196  			name: `value inside a parenthesis`,
  1197  			in:   `(value)`,
  1198  			typ:  influxql.Float,
  1199  			data: EvalFixture{
  1200  				"cpu": map[string]influxql.DataType{
  1201  					"value": influxql.Float,
  1202  				},
  1203  			},
  1204  		},
  1205  		{
  1206  			name: `binary expression with a float and integer`,
  1207  			in:   `v1 + v2`,
  1208  			typ:  influxql.Float,
  1209  			data: EvalFixture{
  1210  				"cpu": map[string]influxql.DataType{
  1211  					"v1": influxql.Float,
  1212  					"v2": influxql.Integer,
  1213  				},
  1214  			},
  1215  		},
  1216  		{
  1217  			name: `integer and unsigned literal`,
  1218  			in:   `value + 9223372036854775808`,
  1219  			err:  `type error: value + 9223372036854775808: cannot use + with an integer and unsigned literal`,
  1220  			data: EvalFixture{
  1221  				"cpu": map[string]influxql.DataType{
  1222  					"value": influxql.Integer,
  1223  				},
  1224  			},
  1225  		},
  1226  		{
  1227  			name: `unsigned and integer literal`,
  1228  			in:   `value + 1`,
  1229  			typ:  influxql.Unsigned,
  1230  			data: EvalFixture{
  1231  				"cpu": map[string]influxql.DataType{
  1232  					"value": influxql.Unsigned,
  1233  				},
  1234  			},
  1235  		},
  1236  		{
  1237  			name: `incompatible types`,
  1238  			in:   `v1 + v2`,
  1239  			err:  `type error: v1 + v2: incompatible types: string and integer`,
  1240  			data: EvalFixture{
  1241  				"cpu": map[string]influxql.DataType{
  1242  					"v1": influxql.String,
  1243  					"v2": influxql.Integer,
  1244  				},
  1245  			},
  1246  		},
  1247  	} {
  1248  		sources := make([]influxql.Source, 0, len(tt.data))
  1249  		for src := range tt.data {
  1250  			sources = append(sources, &influxql.Measurement{Name: src})
  1251  		}
  1252  
  1253  		expr := influxql.MustParseExpr(tt.in)
  1254  		valuer := influxql.TypeValuerEval{
  1255  			TypeMapper: tt.data,
  1256  			Sources:    sources,
  1257  		}
  1258  		typ, err := valuer.EvalType(expr)
  1259  		if err != nil {
  1260  			if exp, got := tt.err, err.Error(); exp != got {
  1261  				t.Errorf("%d. %s: unexpected error:\n\nexp=%#v\n\ngot=%v\n\n", i, tt.name, exp, got)
  1262  			}
  1263  		} else if typ != tt.typ {
  1264  			t.Errorf("%d. %s: unexpected type:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.name, tt.typ, typ)
  1265  		}
  1266  	}
  1267  }
  1268  
  1269  // Ensure an expression can be reduced.
  1270  func TestReduce(t *testing.T) {
  1271  	now := mustParseTime("2000-01-01T00:00:00Z")
  1272  
  1273  	for i, tt := range []struct {
  1274  		in   string
  1275  		out  string
  1276  		data influxql.MapValuer
  1277  	}{
  1278  		// Number literals.
  1279  		{in: `1 + 2`, out: `3`},
  1280  		{in: `(foo*2) + ( (4/2) + (3 * 5) - 0.5 )`, out: `(foo * 2) + 16.500`},
  1281  		{in: `foo(bar(2 + 3), 4)`, out: `foo(bar(5), 4)`},
  1282  		{in: `4 / 0`, out: `0.000`},
  1283  		{in: `1 / 2`, out: `0.500`},
  1284  		{in: `2 % 3`, out: `2`},
  1285  		{in: `5 % 2`, out: `1`},
  1286  		{in: `2 % 0`, out: `0`},
  1287  		{in: `2.5 % 0`, out: `NaN`},
  1288  		{in: `254 & 3`, out: `2`},
  1289  		{in: `254 | 3`, out: `255`},
  1290  		{in: `254 ^ 3`, out: `253`},
  1291  		{in: `-3 & 3`, out: `1`},
  1292  		{in: `8 & -3`, out: `8`},
  1293  		{in: `8.5 & -3`, out: `8.500 & -3`},
  1294  		{in: `4 = 4`, out: `true`},
  1295  		{in: `4 <> 4`, out: `false`},
  1296  		{in: `6 > 4`, out: `true`},
  1297  		{in: `4 >= 4`, out: `true`},
  1298  		{in: `4 < 6`, out: `true`},
  1299  		{in: `4 <= 4`, out: `true`},
  1300  		{in: `4 AND 5`, out: `4 AND 5`},
  1301  		{in: `-1 = 9223372036854775808`, out: `false`},
  1302  		{in: `-1 != 9223372036854775808`, out: `true`},
  1303  		{in: `-1 < 9223372036854775808`, out: `true`},
  1304  		{in: `-1 <= 9223372036854775808`, out: `true`},
  1305  		{in: `-1 > 9223372036854775808`, out: `false`},
  1306  		{in: `-1 >= 9223372036854775808`, out: `false`},
  1307  		{in: `9223372036854775808 = -1`, out: `false`},
  1308  		{in: `9223372036854775808 != -1`, out: `true`},
  1309  		{in: `9223372036854775808 < -1`, out: `false`},
  1310  		{in: `9223372036854775808 <= -1`, out: `false`},
  1311  		{in: `9223372036854775808 > -1`, out: `true`},
  1312  		{in: `9223372036854775808 >= -1`, out: `true`},
  1313  		{in: `9223372036854775808 = 9223372036854775808`, out: `true`},
  1314  		{in: `9223372036854775808 != 9223372036854775808`, out: `false`},
  1315  		{in: `9223372036854775808 < 9223372036854775808`, out: `false`},
  1316  		{in: `9223372036854775808 <= 9223372036854775808`, out: `true`},
  1317  		{in: `9223372036854775808 > 9223372036854775808`, out: `false`},
  1318  		{in: `9223372036854775808 >= 9223372036854775808`, out: `true`},
  1319  		{in: `9223372036854775809 = 9223372036854775808`, out: `false`},
  1320  		{in: `9223372036854775809 != 9223372036854775808`, out: `true`},
  1321  		{in: `9223372036854775809 < 9223372036854775808`, out: `false`},
  1322  		{in: `9223372036854775809 <= 9223372036854775808`, out: `false`},
  1323  		{in: `9223372036854775809 > 9223372036854775808`, out: `true`},
  1324  		{in: `9223372036854775809 >= 9223372036854775808`, out: `true`},
  1325  		{in: `9223372036854775808 / 0`, out: `0`},
  1326  		{in: `9223372036854775808 + 1`, out: `9223372036854775809`},
  1327  		{in: `9223372036854775808 - 1`, out: `9223372036854775807`},
  1328  		{in: `9223372036854775809 - 9223372036854775808`, out: `1`},
  1329  
  1330  		// Boolean literals.
  1331  		{in: `true AND false`, out: `false`},
  1332  		{in: `true OR false`, out: `true`},
  1333  		{in: `true OR (foo = bar AND 1 > 2)`, out: `true`},
  1334  		{in: `(foo = bar AND 1 > 2) OR true`, out: `true`},
  1335  		{in: `false OR (foo = bar AND 1 > 2)`, out: `false`},
  1336  		{in: `(foo = bar AND 1 > 2) OR false`, out: `false`},
  1337  		{in: `true = false`, out: `false`},
  1338  		{in: `true <> false`, out: `true`},
  1339  		{in: `true + false`, out: `true + false`},
  1340  
  1341  		// Time literals with now().
  1342  		{in: `now() + 2h`, out: `'2000-01-01T02:00:00Z'`},
  1343  		{in: `now() / 2h`, out: `'2000-01-01T00:00:00Z' / 2h`},
  1344  		{in: `4µ + now()`, out: `'2000-01-01T00:00:00.000004Z'`},
  1345  		{in: `now() + 2000000000`, out: `'2000-01-01T00:00:02Z'`},
  1346  		{in: `2000000000 + now()`, out: `'2000-01-01T00:00:02Z'`},
  1347  		{in: `now() - 2000000000`, out: `'1999-12-31T23:59:58Z'`},
  1348  		{in: `now() = now()`, out: `true`},
  1349  		{in: `now() <> now()`, out: `false`},
  1350  		{in: `now() < now() + 1h`, out: `true`},
  1351  		{in: `now() <= now() + 1h`, out: `true`},
  1352  		{in: `now() >= now() - 1h`, out: `true`},
  1353  		{in: `now() > now() - 1h`, out: `true`},
  1354  		{in: `now() - (now() - 60s)`, out: `1m`},
  1355  		{in: `now() AND now()`, out: `'2000-01-01T00:00:00Z' AND '2000-01-01T00:00:00Z'`},
  1356  		{in: `946684800000000000 + 2h`, out: `'2000-01-01T02:00:00Z'`},
  1357  
  1358  		// Time literals.
  1359  		{in: `'2000-01-01T00:00:00Z' + 2h`, out: `'2000-01-01T02:00:00Z'`},
  1360  		{in: `'2000-01-01T00:00:00Z' / 2h`, out: `'2000-01-01T00:00:00Z' / 2h`},
  1361  		{in: `4µ + '2000-01-01T00:00:00Z'`, out: `'2000-01-01T00:00:00.000004Z'`},
  1362  		{in: `'2000-01-01T00:00:00Z' + 2000000000`, out: `'2000-01-01T00:00:02Z'`},
  1363  		{in: `2000000000 + '2000-01-01T00:00:00Z'`, out: `'2000-01-01T00:00:02Z'`},
  1364  		{in: `'2000-01-01T00:00:00Z' - 2000000000`, out: `'1999-12-31T23:59:58Z'`},
  1365  		{in: `'2000-01-01T00:00:00Z' = '2000-01-01T00:00:00Z'`, out: `true`},
  1366  		{in: `'2000-01-01T00:00:00.000000000Z' = '2000-01-01T00:00:00Z'`, out: `true`},
  1367  		{in: `'2000-01-01T00:00:00Z' <> '2000-01-01T00:00:00Z'`, out: `false`},
  1368  		{in: `'2000-01-01T00:00:00.000000000Z' <> '2000-01-01T00:00:00Z'`, out: `false`},
  1369  		{in: `'2000-01-01T00:00:00Z' < '2000-01-01T00:00:00Z' + 1h`, out: `true`},
  1370  		{in: `'2000-01-01T00:00:00.000000000Z' < '2000-01-01T00:00:00Z' + 1h`, out: `true`},
  1371  		{in: `'2000-01-01T00:00:00Z' <= '2000-01-01T00:00:00Z' + 1h`, out: `true`},
  1372  		{in: `'2000-01-01T00:00:00.000000000Z' <= '2000-01-01T00:00:00Z' + 1h`, out: `true`},
  1373  		{in: `'2000-01-01T00:00:00Z' > '2000-01-01T00:00:00Z' - 1h`, out: `true`},
  1374  		{in: `'2000-01-01T00:00:00.000000000Z' > '2000-01-01T00:00:00Z' - 1h`, out: `true`},
  1375  		{in: `'2000-01-01T00:00:00Z' >= '2000-01-01T00:00:00Z' - 1h`, out: `true`},
  1376  		{in: `'2000-01-01T00:00:00.000000000Z' >= '2000-01-01T00:00:00Z' - 1h`, out: `true`},
  1377  		{in: `'2000-01-01T00:00:00Z' - ('2000-01-01T00:00:00Z' - 60s)`, out: `1m`},
  1378  		{in: `'2000-01-01T00:00:00Z' AND '2000-01-01T00:00:00Z'`, out: `'2000-01-01T00:00:00Z' AND '2000-01-01T00:00:00Z'`},
  1379  
  1380  		// Duration literals.
  1381  		{in: `10m + 1h - 60s`, out: `69m`},
  1382  		{in: `(10m / 2) * 5`, out: `25m`},
  1383  		{in: `60s = 1m`, out: `true`},
  1384  		{in: `60s <> 1m`, out: `false`},
  1385  		{in: `60s < 1h`, out: `true`},
  1386  		{in: `60s <= 1h`, out: `true`},
  1387  		{in: `60s > 12s`, out: `true`},
  1388  		{in: `60s >= 1m`, out: `true`},
  1389  		{in: `60s AND 1m`, out: `1m AND 1m`},
  1390  		{in: `60m / 0`, out: `0s`},
  1391  		{in: `60m + 50`, out: `1h + 50`},
  1392  
  1393  		// String literals.
  1394  		{in: `'foo' + 'bar'`, out: `'foobar'`},
  1395  
  1396  		// Variable references.
  1397  		{in: `foo`, out: `'bar'`, data: map[string]interface{}{"foo": "bar"}},
  1398  		{in: `foo = 'bar'`, out: `true`, data: map[string]interface{}{"foo": "bar"}},
  1399  		{in: `foo = 'bar'`, out: `false`, data: map[string]interface{}{"foo": nil}},
  1400  		{in: `foo <> 'bar'`, out: `false`, data: map[string]interface{}{"foo": nil}},
  1401  	} {
  1402  		// Fold expression.
  1403  		expr := influxql.Reduce(MustParseExpr(tt.in), influxql.MultiValuer(
  1404  			tt.data,
  1405  			&influxql.NowValuer{Now: now},
  1406  		))
  1407  
  1408  		// Compare with expected output.
  1409  		if out := expr.String(); tt.out != out {
  1410  			t.Errorf("%d. %s: unexpected expr:\n\nexp=%s\n\ngot=%s\n\n", i, tt.in, tt.out, out)
  1411  			continue
  1412  		}
  1413  	}
  1414  }
  1415  
  1416  func Test_fieldsNames(t *testing.T) {
  1417  	for _, test := range []struct {
  1418  		in    []string
  1419  		out   []string
  1420  		alias []string
  1421  	}{
  1422  		{ //case: binary expr(valRef)
  1423  			in:    []string{"value+value"},
  1424  			out:   []string{"value", "value"},
  1425  			alias: []string{"value_value"},
  1426  		},
  1427  		{ //case: binary expr + valRef
  1428  			in:    []string{"value+value", "temperature"},
  1429  			out:   []string{"value", "value", "temperature"},
  1430  			alias: []string{"value_value", "temperature"},
  1431  		},
  1432  		{ //case: aggregate expr
  1433  			in:    []string{"mean(value)"},
  1434  			out:   []string{"mean"},
  1435  			alias: []string{"mean"},
  1436  		},
  1437  		{ //case: binary expr(aggregate expr)
  1438  			in:    []string{"mean(value) + max(value)"},
  1439  			out:   []string{"value", "value"},
  1440  			alias: []string{"mean_max"},
  1441  		},
  1442  		{ //case: binary expr(aggregate expr) + valRef
  1443  			in:    []string{"mean(value) + max(value)", "temperature"},
  1444  			out:   []string{"value", "value", "temperature"},
  1445  			alias: []string{"mean_max", "temperature"},
  1446  		},
  1447  		{ //case: mixed aggregate and varRef
  1448  			in:    []string{"mean(value) + temperature"},
  1449  			out:   []string{"value", "temperature"},
  1450  			alias: []string{"mean_temperature"},
  1451  		},
  1452  		{ //case: ParenExpr(varRef)
  1453  			in:    []string{"(value)"},
  1454  			out:   []string{"value"},
  1455  			alias: []string{"value"},
  1456  		},
  1457  		{ //case: ParenExpr(varRef + varRef)
  1458  			in:    []string{"(value + value)"},
  1459  			out:   []string{"value", "value"},
  1460  			alias: []string{"value_value"},
  1461  		},
  1462  		{ //case: ParenExpr(aggregate)
  1463  			in:    []string{"(mean(value))"},
  1464  			out:   []string{"value"},
  1465  			alias: []string{"mean"},
  1466  		},
  1467  		{ //case: ParenExpr(aggregate + aggregate)
  1468  			in:    []string{"(mean(value) + max(value))"},
  1469  			out:   []string{"value", "value"},
  1470  			alias: []string{"mean_max"},
  1471  		},
  1472  	} {
  1473  		fields := influxql.Fields{}
  1474  		for _, s := range test.in {
  1475  			expr := MustParseExpr(s)
  1476  			fields = append(fields, &influxql.Field{Expr: expr})
  1477  		}
  1478  		got := fields.Names()
  1479  		if !reflect.DeepEqual(got, test.out) {
  1480  			t.Errorf("get fields name:\nexp=%v\ngot=%v\n", test.out, got)
  1481  		}
  1482  		alias := fields.AliasNames()
  1483  		if !reflect.DeepEqual(alias, test.alias) {
  1484  			t.Errorf("get fields alias name:\nexp=%v\ngot=%v\n", test.alias, alias)
  1485  		}
  1486  	}
  1487  
  1488  }
  1489  
  1490  func TestSelect_ColumnNames(t *testing.T) {
  1491  	for i, tt := range []struct {
  1492  		stmt    *influxql.SelectStatement
  1493  		columns []string
  1494  	}{
  1495  		{
  1496  			stmt: &influxql.SelectStatement{
  1497  				Fields: influxql.Fields([]*influxql.Field{
  1498  					{Expr: &influxql.VarRef{Val: "value"}},
  1499  				}),
  1500  			},
  1501  			columns: []string{"time", "value"},
  1502  		},
  1503  		{
  1504  			stmt: &influxql.SelectStatement{
  1505  				Fields: influxql.Fields([]*influxql.Field{
  1506  					{Expr: &influxql.VarRef{Val: "value"}},
  1507  					{Expr: &influxql.VarRef{Val: "value"}},
  1508  					{Expr: &influxql.VarRef{Val: "value_1"}},
  1509  				}),
  1510  			},
  1511  			columns: []string{"time", "value", "value_1", "value_1_1"},
  1512  		},
  1513  		{
  1514  			stmt: &influxql.SelectStatement{
  1515  				Fields: influxql.Fields([]*influxql.Field{
  1516  					{Expr: &influxql.VarRef{Val: "value"}},
  1517  					{Expr: &influxql.VarRef{Val: "value_1"}},
  1518  					{Expr: &influxql.VarRef{Val: "value"}},
  1519  				}),
  1520  			},
  1521  			columns: []string{"time", "value", "value_1", "value_2"},
  1522  		},
  1523  		{
  1524  			stmt: &influxql.SelectStatement{
  1525  				Fields: influxql.Fields([]*influxql.Field{
  1526  					{Expr: &influxql.VarRef{Val: "value"}},
  1527  					{Expr: &influxql.VarRef{Val: "total"}, Alias: "value"},
  1528  					{Expr: &influxql.VarRef{Val: "value"}},
  1529  				}),
  1530  			},
  1531  			columns: []string{"time", "value_1", "value", "value_2"},
  1532  		},
  1533  		{
  1534  			stmt: &influxql.SelectStatement{
  1535  				Fields: influxql.Fields([]*influxql.Field{
  1536  					{Expr: &influxql.VarRef{Val: "value"}},
  1537  				}),
  1538  				TimeAlias: "timestamp",
  1539  			},
  1540  			columns: []string{"timestamp", "value"},
  1541  		},
  1542  	} {
  1543  		columns := tt.stmt.ColumnNames()
  1544  		if !reflect.DeepEqual(columns, tt.columns) {
  1545  			t.Errorf("%d. expected %s, got %s", i, tt.columns, columns)
  1546  		}
  1547  	}
  1548  }
  1549  
  1550  func TestSelect_Privileges(t *testing.T) {
  1551  	stmt := &influxql.SelectStatement{
  1552  		Target: &influxql.Target{
  1553  			Measurement: &influxql.Measurement{Database: "db2"},
  1554  		},
  1555  		Sources: []influxql.Source{
  1556  			&influxql.Measurement{Database: "db0"},
  1557  			&influxql.Measurement{Database: "db1"},
  1558  		},
  1559  	}
  1560  
  1561  	exp := influxql.ExecutionPrivileges{
  1562  		influxql.ExecutionPrivilege{Name: "db0", Privilege: influxql.ReadPrivilege},
  1563  		influxql.ExecutionPrivilege{Name: "db1", Privilege: influxql.ReadPrivilege},
  1564  		influxql.ExecutionPrivilege{Name: "db2", Privilege: influxql.WritePrivilege},
  1565  	}
  1566  
  1567  	got, err := stmt.RequiredPrivileges()
  1568  	if err != nil {
  1569  		t.Fatal(err)
  1570  	}
  1571  
  1572  	if !reflect.DeepEqual(exp, got) {
  1573  		t.Errorf("exp: %v, got: %v", exp, got)
  1574  	}
  1575  }
  1576  
  1577  func TestSelect_SubqueryPrivileges(t *testing.T) {
  1578  	stmt := &influxql.SelectStatement{
  1579  		Target: &influxql.Target{
  1580  			Measurement: &influxql.Measurement{Database: "db2"},
  1581  		},
  1582  		Sources: []influxql.Source{
  1583  			&influxql.Measurement{Database: "db0"},
  1584  			&influxql.SubQuery{
  1585  				Statement: &influxql.SelectStatement{
  1586  					Sources: []influxql.Source{
  1587  						&influxql.Measurement{Database: "db1"},
  1588  					},
  1589  				},
  1590  			},
  1591  		},
  1592  	}
  1593  
  1594  	exp := influxql.ExecutionPrivileges{
  1595  		influxql.ExecutionPrivilege{Name: "db0", Privilege: influxql.ReadPrivilege},
  1596  		influxql.ExecutionPrivilege{Name: "db1", Privilege: influxql.ReadPrivilege},
  1597  		influxql.ExecutionPrivilege{Name: "db2", Privilege: influxql.WritePrivilege},
  1598  	}
  1599  
  1600  	got, err := stmt.RequiredPrivileges()
  1601  	if err != nil {
  1602  		t.Fatal(err)
  1603  	}
  1604  
  1605  	if !reflect.DeepEqual(exp, got) {
  1606  		t.Errorf("exp: %v, got: %v", exp, got)
  1607  	}
  1608  }
  1609  
  1610  func TestShow_Privileges(t *testing.T) {
  1611  	for _, c := range []struct {
  1612  		stmt influxql.Statement
  1613  		exp  influxql.ExecutionPrivileges
  1614  	}{
  1615  		{
  1616  			stmt: &influxql.ShowDatabasesStatement{},
  1617  			exp:  influxql.ExecutionPrivileges{{Admin: false, Privilege: influxql.NoPrivileges}},
  1618  		},
  1619  		{
  1620  			stmt: &influxql.ShowFieldKeysStatement{},
  1621  			exp:  influxql.ExecutionPrivileges{{Admin: false, Privilege: influxql.ReadPrivilege}},
  1622  		},
  1623  		{
  1624  			stmt: &influxql.ShowMeasurementsStatement{},
  1625  			exp:  influxql.ExecutionPrivileges{{Admin: false, Privilege: influxql.ReadPrivilege}},
  1626  		},
  1627  		{
  1628  			stmt: &influxql.ShowQueriesStatement{},
  1629  			exp:  influxql.ExecutionPrivileges{{Admin: false, Privilege: influxql.ReadPrivilege}},
  1630  		},
  1631  		{
  1632  			stmt: &influxql.ShowRetentionPoliciesStatement{},
  1633  			exp:  influxql.ExecutionPrivileges{{Admin: false, Privilege: influxql.ReadPrivilege}},
  1634  		},
  1635  		{
  1636  			stmt: &influxql.ShowSeriesStatement{},
  1637  			exp:  influxql.ExecutionPrivileges{{Admin: false, Privilege: influxql.ReadPrivilege}},
  1638  		},
  1639  		{
  1640  			stmt: &influxql.ShowShardGroupsStatement{},
  1641  			exp:  influxql.ExecutionPrivileges{{Admin: true, Privilege: influxql.AllPrivileges}},
  1642  		},
  1643  		{
  1644  			stmt: &influxql.ShowShardsStatement{},
  1645  			exp:  influxql.ExecutionPrivileges{{Admin: true, Privilege: influxql.AllPrivileges}},
  1646  		},
  1647  		{
  1648  			stmt: &influxql.ShowStatsStatement{},
  1649  			exp:  influxql.ExecutionPrivileges{{Admin: true, Privilege: influxql.AllPrivileges}},
  1650  		},
  1651  		{
  1652  			stmt: &influxql.ShowSubscriptionsStatement{},
  1653  			exp:  influxql.ExecutionPrivileges{{Admin: true, Privilege: influxql.AllPrivileges}},
  1654  		},
  1655  		{
  1656  			stmt: &influxql.ShowDiagnosticsStatement{},
  1657  			exp:  influxql.ExecutionPrivileges{{Admin: true, Privilege: influxql.AllPrivileges}},
  1658  		},
  1659  		{
  1660  			stmt: &influxql.ShowTagKeysStatement{},
  1661  			exp:  influxql.ExecutionPrivileges{{Admin: false, Privilege: influxql.ReadPrivilege}},
  1662  		},
  1663  		{
  1664  			stmt: &influxql.ShowTagValuesStatement{},
  1665  			exp:  influxql.ExecutionPrivileges{{Admin: false, Privilege: influxql.ReadPrivilege}},
  1666  		},
  1667  		{
  1668  			stmt: &influxql.ShowUsersStatement{},
  1669  			exp:  influxql.ExecutionPrivileges{{Admin: true, Privilege: influxql.AllPrivileges}},
  1670  		},
  1671  	} {
  1672  		got, err := c.stmt.RequiredPrivileges()
  1673  		if err != nil {
  1674  			t.Fatal(err)
  1675  		}
  1676  
  1677  		if !reflect.DeepEqual(c.exp, got) {
  1678  			t.Errorf("exp: %v, got: %v", c.exp, got)
  1679  		}
  1680  	}
  1681  }
  1682  
  1683  func TestBoundParameter_String(t *testing.T) {
  1684  	stmt := &influxql.SelectStatement{
  1685  		IsRawQuery: true,
  1686  		Fields: []*influxql.Field{{
  1687  			Expr: &influxql.VarRef{Val: "value"}}},
  1688  		Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1689  		Condition: &influxql.BinaryExpr{
  1690  			Op:  influxql.GT,
  1691  			LHS: &influxql.VarRef{Val: "value"},
  1692  			RHS: &influxql.BoundParameter{Name: "value"},
  1693  		},
  1694  	}
  1695  
  1696  	if got, exp := stmt.String(), `SELECT value FROM cpu WHERE value > $value`; got != exp {
  1697  		t.Fatalf("stmt mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", exp, got)
  1698  	}
  1699  
  1700  	stmt = &influxql.SelectStatement{
  1701  		IsRawQuery: true,
  1702  		Fields: []*influxql.Field{{
  1703  			Expr: &influxql.VarRef{Val: "value"}}},
  1704  		Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}},
  1705  		Condition: &influxql.BinaryExpr{
  1706  			Op:  influxql.GT,
  1707  			LHS: &influxql.VarRef{Val: "value"},
  1708  			RHS: &influxql.BoundParameter{Name: "multi-word value"},
  1709  		},
  1710  	}
  1711  
  1712  	if got, exp := stmt.String(), `SELECT value FROM cpu WHERE value > $"multi-word value"`; got != exp {
  1713  		t.Fatalf("stmt mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", exp, got)
  1714  	}
  1715  }
  1716  
  1717  // This test checks to ensure that we have given thought to the database
  1718  // context required for security checks.  If a new statement is added, this
  1719  // test will fail until it is categorized into the correct bucket below.
  1720  func Test_EnforceHasDefaultDatabase(t *testing.T) {
  1721  	pkg, err := importer.Default().Import("github.com/influxdata/influxql")
  1722  	if err != nil {
  1723  		fmt.Printf("error: %s\n", err.Error())
  1724  		return
  1725  	}
  1726  	statements := []string{}
  1727  
  1728  	// this is a list of statements that do not have a database context
  1729  	exemptStatements := []string{
  1730  		"CreateDatabaseStatement",
  1731  		"CreateUserStatement",
  1732  		"DeleteSeriesStatement",
  1733  		"DropDatabaseStatement",
  1734  		"DropMeasurementStatement",
  1735  		"DropSeriesStatement",
  1736  		"DropShardStatement",
  1737  		"DropUserStatement",
  1738  		"ExplainStatement",
  1739  		"GrantAdminStatement",
  1740  		"KillQueryStatement",
  1741  		"RevokeAdminStatement",
  1742  		"SelectStatement",
  1743  		"SetPasswordUserStatement",
  1744  		"ShowContinuousQueriesStatement",
  1745  		"ShowDatabasesStatement",
  1746  		"ShowDiagnosticsStatement",
  1747  		"ShowGrantsForUserStatement",
  1748  		"ShowQueriesStatement",
  1749  		"ShowShardGroupsStatement",
  1750  		"ShowShardsStatement",
  1751  		"ShowStatsStatement",
  1752  		"ShowSubscriptionsStatement",
  1753  		"ShowUsersStatement",
  1754  	}
  1755  
  1756  	exists := func(stmt string) bool {
  1757  		switch stmt {
  1758  		// These are functions with the word statement in them, and can be ignored
  1759  		case "Statement", "MustParseStatement", "ParseStatement", "RewriteStatement":
  1760  			return true
  1761  		default:
  1762  			// check the exempt statements
  1763  			for _, s := range exemptStatements {
  1764  				if s == stmt {
  1765  					return true
  1766  				}
  1767  			}
  1768  			// check the statements that passed the interface test for HasDefaultDatabase
  1769  			for _, s := range statements {
  1770  				if s == stmt {
  1771  					return true
  1772  				}
  1773  			}
  1774  			return false
  1775  		}
  1776  	}
  1777  
  1778  	needsHasDefault := []interface{}{
  1779  		&influxql.AlterRetentionPolicyStatement{},
  1780  		&influxql.CreateContinuousQueryStatement{},
  1781  		&influxql.CreateRetentionPolicyStatement{},
  1782  		&influxql.CreateSubscriptionStatement{},
  1783  		&influxql.DeleteStatement{},
  1784  		&influxql.DropContinuousQueryStatement{},
  1785  		&influxql.DropRetentionPolicyStatement{},
  1786  		&influxql.DropSubscriptionStatement{},
  1787  		&influxql.GrantStatement{},
  1788  		&influxql.RevokeStatement{},
  1789  		&influxql.ShowFieldKeysStatement{},
  1790  		&influxql.ShowFieldKeyCardinalityStatement{},
  1791  		&influxql.ShowMeasurementCardinalityStatement{},
  1792  		&influxql.ShowMeasurementsStatement{},
  1793  		&influxql.ShowRetentionPoliciesStatement{},
  1794  		&influxql.ShowSeriesStatement{},
  1795  		&influxql.ShowSeriesCardinalityStatement{},
  1796  		&influxql.ShowTagKeysStatement{},
  1797  		&influxql.ShowTagKeyCardinalityStatement{},
  1798  		&influxql.ShowTagValuesStatement{},
  1799  		&influxql.ShowTagValuesCardinalityStatement{},
  1800  	}
  1801  
  1802  	for _, stmt := range needsHasDefault {
  1803  		statements = append(statements, strings.TrimPrefix(fmt.Sprintf("%T", stmt), "*influxql."))
  1804  		if _, ok := stmt.(influxql.HasDefaultDatabase); !ok {
  1805  			t.Errorf("%T was expected to declare DefaultDatabase method", stmt)
  1806  		}
  1807  
  1808  	}
  1809  
  1810  	for _, declName := range pkg.Scope().Names() {
  1811  		if strings.HasSuffix(declName, "Statement") {
  1812  			if !exists(declName) {
  1813  				t.Errorf("unchecked statement %s.  please update this test to determine if this statement needs to declare 'DefaultDatabase'", declName)
  1814  			}
  1815  		}
  1816  	}
  1817  }
  1818  
  1819  // MustTimeRange will parse a time range. Panic on error.
  1820  func MustTimeRange(expr influxql.Expr) (min, max time.Time) {
  1821  	_, timeRange, err := influxql.ConditionExpr(expr, nil)
  1822  	if err != nil {
  1823  		panic(err)
  1824  	}
  1825  	return timeRange.Min, timeRange.Max
  1826  }
  1827  
  1828  // mustParseTime parses an IS0-8601 string. Panic on error.
  1829  func mustParseTime(s string) time.Time {
  1830  	t, err := time.Parse(time.RFC3339, s)
  1831  	if err != nil {
  1832  		panic(err.Error())
  1833  	}
  1834  	return t
  1835  }
  1836  
  1837  // FieldMapper is a mockable implementation of influxql.FieldMapper.
  1838  type FieldMapper struct {
  1839  	FieldDimensionsFn func(m *influxql.Measurement) (fields map[string]influxql.DataType, dimensions map[string]struct{}, err error)
  1840  }
  1841  
  1842  func (fm *FieldMapper) FieldDimensions(m *influxql.Measurement) (fields map[string]influxql.DataType, dimensions map[string]struct{}, err error) {
  1843  	return fm.FieldDimensionsFn(m)
  1844  }
  1845  
  1846  func (fm *FieldMapper) MapType(m *influxql.Measurement, field string) influxql.DataType {
  1847  	f, d, err := fm.FieldDimensions(m)
  1848  	if err != nil {
  1849  		return influxql.Unknown
  1850  	}
  1851  
  1852  	if typ, ok := f[field]; ok {
  1853  		return typ
  1854  	}
  1855  	if _, ok := d[field]; ok {
  1856  		return influxql.Tag
  1857  	}
  1858  	return influxql.Unknown
  1859  }
  1860  
  1861  func (fm *FieldMapper) CallType(name string, args []influxql.DataType) (influxql.DataType, error) {
  1862  	switch name {
  1863  	case "mean", "median", "integral", "stddev":
  1864  		return influxql.Float, nil
  1865  	case "count":
  1866  		return influxql.Integer, nil
  1867  	case "elapsed":
  1868  		return influxql.Integer, nil
  1869  	default:
  1870  		return args[0], nil
  1871  	}
  1872  }
  1873  
  1874  // BenchmarkExprNames benchmarks how long it takes to run ExprNames.
  1875  func BenchmarkExprNames(b *testing.B) {
  1876  	exprs := make([]string, 100)
  1877  	for i := range exprs {
  1878  		exprs[i] = fmt.Sprintf("host = 'server%02d'", i)
  1879  	}
  1880  	condition := MustParseExpr(strings.Join(exprs, " OR "))
  1881  
  1882  	b.ResetTimer()
  1883  	b.ReportAllocs()
  1884  
  1885  	for i := 0; i < b.N; i++ {
  1886  		refs := influxql.ExprNames(condition)
  1887  		if have, want := refs, []influxql.VarRef{{Val: "host"}}; !reflect.DeepEqual(have, want) {
  1888  			b.Fatalf("unexpected expression names: have=%s want=%s", have, want)
  1889  		}
  1890  	}
  1891  }
  1892  
  1893  type FunctionValuer struct{}
  1894  
  1895  var _ influxql.CallValuer = FunctionValuer{}
  1896  
  1897  func (FunctionValuer) Value(key string) (interface{}, bool) {
  1898  	return nil, false
  1899  }
  1900  
  1901  func (FunctionValuer) Call(name string, args []interface{}) (interface{}, bool) {
  1902  	switch name {
  1903  	case "abs":
  1904  		arg0 := args[0].(float64)
  1905  		return math.Abs(arg0), true
  1906  	case "pow":
  1907  		arg0, arg1 := args[0].(float64), args[1].(int64)
  1908  		return math.Pow(arg0, float64(arg1)), true
  1909  	default:
  1910  		return nil, false
  1911  	}
  1912  }
  1913  
  1914  // BenchmarkEval benchmarks how long it takes to run Eval.
  1915  func BenchmarkEval(b *testing.B) {
  1916  	expr := MustParseExpr(`f1 + abs(f2) / pow(f3, 3)`)
  1917  	valuer := influxql.ValuerEval{
  1918  		Valuer: influxql.MultiValuer(
  1919  			influxql.MapValuer(map[string]interface{}{
  1920  				"f1": float64(15),
  1921  				"f2": float64(-3),
  1922  				"f3": float64(2),
  1923  			}),
  1924  			FunctionValuer{},
  1925  		),
  1926  	}
  1927  
  1928  	b.ReportAllocs()
  1929  	for i := 0; i < b.N; i++ {
  1930  		valuer.Eval(expr)
  1931  	}
  1932  }