Merge pull request #1506 from influxdb/fix-select-where-time

Fix queries that have only time in their where clause
pull/1531/head
Paul Dix 2015-02-08 02:05:03 -05:00
commit 712297cdb5
5 changed files with 90 additions and 3 deletions

View File

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

View File

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

View File

@ -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`)

View File

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

View File

@ -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) {