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
parent
e74b941c76
commit
680e6d96bc
|
@ -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 {
|
||||
|
|
|
@ -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 := `
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue