Merge pull request #1506 from influxdb/fix-select-where-time
Fix queries that have only time in their where clausepull/1531/head
commit
712297cdb5
|
@ -239,6 +239,12 @@ func (m *Measurement) seriesIDsAndFilters(stmt *influxql.SelectStatement) (serie
|
|||
return m.seriesIDs, nil
|
||||
}
|
||||
ids, _, _ := m.walkWhereForSeriesIds(stmt.Condition, seriesIdsToExpr)
|
||||
|
||||
// ids will be empty if all they had was a time in the where clause. so return all measurement series ids
|
||||
if len(ids) == 0 && stmt.OnlyTimeDimensions() {
|
||||
return m.seriesIDs, nil
|
||||
}
|
||||
|
||||
return ids, seriesIdsToExpr
|
||||
}
|
||||
|
||||
|
|
|
@ -655,6 +655,31 @@ func (s *SelectStatement) Aggregated() bool {
|
|||
return v
|
||||
}
|
||||
|
||||
// OnlyTimeDimensions returns true if the statement has a where clause with only time constraints
|
||||
func (s *SelectStatement) OnlyTimeDimensions() bool {
|
||||
return s.walkForTime(s.Condition)
|
||||
}
|
||||
|
||||
// walkForTime is called by the OnlyTimeDimensions method to walk the where clause to determine if
|
||||
// the only things specified are based on time
|
||||
func (s *SelectStatement) walkForTime(node Node) bool {
|
||||
switch n := node.(type) {
|
||||
case *BinaryExpr:
|
||||
if n.Op == AND || n.Op == OR {
|
||||
return s.walkForTime(n.LHS) && s.walkForTime(n.RHS)
|
||||
}
|
||||
if ref, ok := n.LHS.(*VarRef); ok && strings.ToLower(ref.Val) == "time" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
case *ParenExpr:
|
||||
// walk down the tree
|
||||
return s.walkForTime(n.Expr)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
BinaryExpr
|
||||
|
|
|
@ -146,6 +146,46 @@ func TestTimeRange(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure that we see if a where clause has only time limitations
|
||||
func TestSelectStatement_OnlyTimeDimensions(t *testing.T) {
|
||||
var tests = []struct {
|
||||
stmt string
|
||||
exp bool
|
||||
}{
|
||||
{
|
||||
stmt: `SELECT value FROM myseries WHERE value > 1`,
|
||||
exp: false,
|
||||
},
|
||||
{
|
||||
stmt: `SELECT value FROM foo WHERE time >= '2000-01-01T00:00:05'`,
|
||||
exp: true,
|
||||
},
|
||||
{
|
||||
stmt: `SELECT value FROM foo WHERE time >= '2000-01-01T00:00:05' AND time < '2000-01-01T00:00:05'`,
|
||||
exp: true,
|
||||
},
|
||||
{
|
||||
stmt: `SELECT value FROM foo WHERE time >= '2000-01-01T00:00:05' AND asdf = 'bar'`,
|
||||
exp: false,
|
||||
},
|
||||
{
|
||||
stmt: `SELECT value FROM foo WHERE asdf = 'jkl' AND (time >= '2000-01-01T00:00:05' AND time < '2000-01-01T00:00:05')`,
|
||||
exp: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
// Parse statement.
|
||||
stmt, err := influxql.NewParser(strings.NewReader(tt.stmt)).ParseStatement()
|
||||
if err != nil {
|
||||
t.Fatalf("invalid statement: %q: %s", tt.stmt, err)
|
||||
}
|
||||
if stmt.(*influxql.SelectStatement).OnlyTimeDimensions() != tt.exp {
|
||||
t.Fatalf("%d. expected statement to return only time dimension to be %t: %s", i, tt.exp, tt.stmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure an AST node can be rewritten.
|
||||
func TestRewrite(t *testing.T) {
|
||||
expr := MustParseExpr(`time > 1 OR foo = 2`)
|
||||
|
|
|
@ -404,14 +404,14 @@ func (m *Mapper) run(e *Emitter) {
|
|||
bufItr.tmax = tmin + m.interval - 1
|
||||
}
|
||||
|
||||
// Execute the map function.
|
||||
m.fn(bufItr, e, tmin)
|
||||
|
||||
// Exit if there was only one interval or no more data is available.
|
||||
if bufItr.EOF() {
|
||||
break
|
||||
}
|
||||
|
||||
// Execute the map function.
|
||||
m.fn(bufItr, e, tmin)
|
||||
|
||||
// Move the interval forward.
|
||||
tmin += m.interval
|
||||
}
|
||||
|
|
|
@ -808,6 +808,22 @@ func TestServer_ExecuteQuery(t *testing.T) {
|
|||
} else if s := mustMarshalJSON(res); s != `{"rows":[{"name":"cpu","tags":{"region":"us-east"},"columns":["time","sum"],"values":[["2000-01-01T00:00:00Z",20],["2000-01-01T00:00:10Z",30]]},{"name":"cpu","tags":{"region":"us-west"},"columns":["time","sum"],"values":[["2000-01-01T00:00:00Z",100]]}]}` {
|
||||
t.Fatalf("unexpected row(0): %s", s)
|
||||
}
|
||||
|
||||
// Simple non-aggregation.
|
||||
results = s.ExecuteQuery(MustParseQuery(`SELECT value FROM cpu WHERE time >= '2000-01-01 00:00:05'`), "foo", nil)
|
||||
if res := results.Results[0]; res.Err != nil {
|
||||
t.Fatalf("unexpected error during simple SELECT: %s", res.Err)
|
||||
} else if s := mustMarshalJSON(res); s != `{"rows":[{"name":"cpu","columns":["time","value"],"values":[["2000-01-01T00:00:10Z",30]]}]}` {
|
||||
t.Fatalf("unexpected row(0) during simple SELECT: %s", s)
|
||||
}
|
||||
|
||||
// Sum aggregation.
|
||||
results = s.ExecuteQuery(MustParseQuery(`SELECT sum(value) FROM cpu WHERE time >= '2000-01-01 00:00:05' GROUP BY time(10s), region`), "foo", nil)
|
||||
if res := results.Results[0]; res.Err != nil {
|
||||
t.Fatalf("unexpected error during SUM: %s", res.Err)
|
||||
} else if s := mustMarshalJSON(res); s != `{"rows":[{"name":"cpu","tags":{"region":"us-east"},"columns":["time","sum"],"values":[["2000-01-01T00:00:10Z",30]]}]}` {
|
||||
t.Fatalf("unexpected row(0) during SUM: %s", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_CreateShardGroupIfNotExist(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue