Merge pull request #8234 from influxdata/js-8230-fix-window-computation-overflow

Prevent overflowing or underflowing during window computation
pull/8163/head
Jonathan A. Sternberg 2017-03-31 11:09:30 -05:00 committed by GitHub
commit 211e7ea65d
3 changed files with 55 additions and 5 deletions

View File

@ -33,6 +33,7 @@
- [#8175](https://github.com/influxdata/influxdb/issues/8175): Ensure the input for certain functions in the query engine are ordered.
- [#8171](https://github.com/influxdata/influxdb/issues/8171): Significantly improve shutdown speed for high cardinality databases.
- [#8177](https://github.com/influxdata/influxdb/issues/8177): Fix racy integration test.
- [#8230](https://github.com/influxdata/influxdb/issues/8230): Prevent overflowing or underflowing during window computation.
## v1.2.2 [2017-03-14]

View File

@ -858,23 +858,34 @@ func (opt IteratorOptions) Window(t int64) (start, end int64) {
// with the duration.
dt += int64(opt.Interval.Duration)
}
t -= dt
// Find the start time.
if MinTime+dt >= t {
start = MinTime
} else {
start = t - dt
}
// Look for the start offset again because the first time may have been
// after the offset switch. Now that we are at midnight in UTC, we can
// lookup the zone offset again to get the real starting offset.
if opt.Location != nil {
_, adjustedOffset := opt.Zone(t)
_, adjustedOffset := opt.Zone(start)
// Do not adjust the offset if the offset change is greater than or
// equal to the duration.
if o := startOffset - adjustedOffset; o != 0 && abs(o) < int64(opt.Interval.Duration) {
startOffset = adjustedOffset
}
}
start += int64(opt.Interval.Offset) - startOffset
// Apply the offset.
start = t + int64(opt.Interval.Offset) - startOffset
end = start + int64(opt.Interval.Duration)
// Find the end time.
if dt := int64(opt.Interval.Duration) - dt; MaxTime-dt <= t {
end = MaxTime
} else {
end = t + dt
}
end += int64(opt.Interval.Offset) - startOffset
// Retrieve the zone offset for the end time.
if opt.Location != nil {

View File

@ -1067,6 +1067,44 @@ func TestIteratorOptions_Window_Location(t *testing.T) {
}
}
func TestIteratorOptions_Window_MinTime(t *testing.T) {
opt := influxql.IteratorOptions{
StartTime: influxql.MinTime,
EndTime: influxql.MaxTime,
Interval: influxql.Interval{
Duration: time.Hour,
},
}
expected := time.Unix(0, influxql.MinTime).Add(time.Hour).Truncate(time.Hour)
start, end := opt.Window(influxql.MinTime)
if start != influxql.MinTime {
t.Errorf("expected start to be %d, got %d", influxql.MinTime, start)
}
if have, want := end, expected.UnixNano(); have != want {
t.Errorf("expected end to be %d, got %d", want, have)
}
}
func TestIteratorOptions_Window_MaxTime(t *testing.T) {
opt := influxql.IteratorOptions{
StartTime: influxql.MinTime,
EndTime: influxql.MaxTime,
Interval: influxql.Interval{
Duration: time.Hour,
},
}
expected := time.Unix(0, influxql.MaxTime).Truncate(time.Hour)
start, end := opt.Window(influxql.MaxTime)
if have, want := start, expected.UnixNano(); have != want {
t.Errorf("expected start to be %d, got %d", want, have)
}
if end != influxql.MaxTime {
t.Errorf("expected end to be %d, got %d", influxql.MaxTime, end)
}
}
func TestIteratorOptions_SeekTime_Ascending(t *testing.T) {
opt := influxql.IteratorOptions{
StartTime: 30,