Always fill empty groups if the start time is specified.

Prior to this change, empty group filling worked between t1 and t2,
where t1 is the timestamp of the earliest point and t2 is the timestamp
of the last point. This patch change the behavior of the fill() to use
the query start and end time as t1 and t2, respectively. This only
happens if the user specified the start time of the query. Otherwise,
there's a potential of filling millions of millions of groups, since the
default start time of the query is really really early.
pull/426/head
John Shahid 2014-08-06 15:37:29 -04:00
parent e74b941c76
commit 680e6d96bc
5 changed files with 59 additions and 2 deletions

View File

@ -32,6 +32,11 @@ type QueryEngine struct {
where *parser.WhereCondition
fillWithZero bool
// was start time set in the query, e.g. time > now() - 1d
startTimeSpecified bool
startTime int64
endTime int64
// output fields
responseChan chan *protocol.Response
limiter *Limiter
@ -356,6 +361,15 @@ func (self *QueryEngine) executeCountQueryWithGroupBy(query *parser.SelectQuery,
self.fillWithZero = query.GetGroupByClause().FillWithZero
// This is a special case for issue #426. If the start time is
// specified and there's a group by clause and fill with zero, then
// we need to fill the entire range from start time to end time
if query.IsStartTimeSpecified() && self.duration != nil && self.fillWithZero {
self.startTimeSpecified = true
self.startTime = query.GetStartTime().Truncate(*self.duration).UnixNano() / 1000
self.endTime = query.GetEndTime().Truncate(*self.duration).UnixNano() / 1000
}
self.initializeFields()
err = self.distributeQuery(query, func(series *protocol.Series) error {
@ -520,6 +534,9 @@ func (self *QueryEngine) runAggregatesForTable(table string) {
var err error
if self.duration != nil && self.fillWithZero {
timestampRange := state.pointsRange
if self.startTimeSpecified {
timestampRange = &PointRange{startTime: self.startTime, endTime: self.endTime}
}
// TODO: DRY this
if self.query.Ascending {

View File

@ -204,6 +204,33 @@ func (self *DataTestSuite) DifferenceValues(c *C) (Fun, Fun) {
}
}
// issue #426
func (self *DataTestSuite) FilllingEntireRange(c *C) (Fun, Fun) {
return func(client Client) {
data := `
[
{
"name": "test_filling_range",
"columns": ["value"],
"points": [
[1]
]
}
]`
client.WriteJsonData(data, c, influxdb.Millisecond)
}, func(client Client) {
serieses := client.RunQuery("select sum(value) from test_filling_range where time > now() - 1d group by time(1h) fill(0)", c, "m")
c.Assert(serieses, HasLen, 1)
maps := ToMap(serieses[0])
fmt.Printf("lenght: %d\n", len(maps))
c.Assert(maps, HasLen, 25)
c.Assert(maps[0]["sum"], Equals, 1.0)
for i := 1; i < len(maps); i++ {
c.Assert(maps[i]["sum"], Equals, 0.0)
}
}
}
func (self *DataTestSuite) ModeWithInt(c *C) (Fun, Fun) {
return func(client Client) {
data := `

View File

@ -29,8 +29,9 @@ type IntoClause struct {
}
type BasicQuery struct {
startTime time.Time
endTime time.Time
startTime time.Time
endTime time.Time
startTimeSpecified bool
}
type SelectDeleteCommonQuery struct {
@ -681,6 +682,7 @@ func parseSelectDeleteCommonQuery(fromClause *C.from_clause, whereCondition *C.c
if startTime != nil {
goQuery.startTime = *startTime
goQuery.startTimeSpecified = true
}
return goQuery, nil

View File

@ -101,6 +101,13 @@ func (self *QueryParserSuite) TestGetQueryString(c *C) {
c.Assert(actualQuery, HasLen, 1)
expectedQuery[0].QueryString = ""
actualQuery[0].QueryString = ""
if expectedQuery[0].DeleteQuery != nil {
expectedQuery[0].DeleteQuery.startTimeSpecified = false
actualQuery[0].DeleteQuery.startTimeSpecified = false
} else if expectedQuery[0].SelectQuery != nil {
expectedQuery[0].SelectQuery.startTimeSpecified = false
actualQuery[0].SelectQuery.startTimeSpecified = false
}
c.Assert(actualQuery[0], DeepEquals, expectedQuery[0])
}

View File

@ -200,6 +200,10 @@ func (self *BasicQuery) GetStartTime() time.Time {
return self.startTime
}
func (self *BasicQuery) IsStartTimeSpecified() bool {
return self.startTimeSpecified
}
// Returns the start time of the query. Queries can only have
// one condition of the form time > start_time
func (self *BasicQuery) GetEndTime() time.Time {