From 9b6d5dfd789dd0828ae5d2faf304ac374fd2c40c Mon Sep 17 00:00:00 2001 From: "Jonathan A. Sternberg" Date: Fri, 8 Apr 2016 15:00:47 -0400 Subject: [PATCH] Allow derivative() function to be used with ORDER BY desc The derivative function had an arbitrary limitation that would cause it to set the value to zero if the previous value was after the next value. This caused all `ORDER BY desc` queries with `derivative()` to always return zero values. Fixes #4675. --- CHANGELOG.md | 1 + influxql/functions.go | 12 ++-------- influxql/select_test.go | 52 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94ab569d165..1332d193009 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - [#6444](https://github.com/influxdata/influxdb/pull/6444): Allow setting the config path through an environment variable and default config path. - [#3558](https://github.com/influxdata/influxdb/issues/3558): Support field math inside a WHERE clause. - [#6429](https://github.com/influxdata/influxdb/issues/6429): Log slow queries if they pass a configurable threshold. +- [#4675](https://github.com/influxdata/influxdb/issues/4675): Allow derivative() function to be used with ORDER BY desc. ### Bugfixes diff --git a/influxql/functions.go b/influxql/functions.go index ffd8402bc3e..40661f2f4e8 100644 --- a/influxql/functions.go +++ b/influxql/functions.go @@ -98,11 +98,7 @@ func (r *FloatDerivativeReducer) Emit() []FloatPoint { if !r.ascending { elapsed = -elapsed } - - value := 0.0 - if elapsed > 0 { - value = diff / (float64(elapsed) / float64(r.interval.Duration)) - } + value := diff / (float64(elapsed) / float64(r.interval.Duration)) // Drop negative values for non-negative derivatives. if r.isNonNegative && diff < 0 { @@ -149,11 +145,7 @@ func (r *IntegerDerivativeReducer) Emit() []FloatPoint { if !r.ascending { elapsed = -elapsed } - - value := 0.0 - if elapsed > 0 { - value = diff / (float64(elapsed) / float64(r.interval.Duration)) - } + value := diff / (float64(elapsed) / float64(r.interval.Duration)) // Drop negative values for non-negative derivatives. if r.isNonNegative && diff < 0 { diff --git a/influxql/select_test.go b/influxql/select_test.go index ac632d3589d..b8aa0a277ba 100644 --- a/influxql/select_test.go +++ b/influxql/select_test.go @@ -1975,6 +1975,58 @@ func TestSelect_Derivative_Integer(t *testing.T) { } } +func TestSelect_Derivative_Desc_Float(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return &FloatIterator{Points: []influxql.FloatPoint{ + {Name: "cpu", Time: 12 * Second, Value: 3}, + {Name: "cpu", Time: 8 * Second, Value: 19}, + {Name: "cpu", Time: 4 * Second, Value: 10}, + {Name: "cpu", Time: 0 * Second, Value: 20}, + }}, nil + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT derivative(value, 1s) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-01T00:00:16Z' ORDER BY desc`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Errorf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.FloatPoint{Name: "cpu", Time: 8 * Second, Value: 4}}, + {&influxql.FloatPoint{Name: "cpu", Time: 4 * Second, Value: -2.25}}, + {&influxql.FloatPoint{Name: "cpu", Time: 0 * Second, Value: 2.5}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + +func TestSelect_Derivative_Desc_Integer(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return &IntegerIterator{Points: []influxql.IntegerPoint{ + {Name: "cpu", Time: 12 * Second, Value: 3}, + {Name: "cpu", Time: 8 * Second, Value: 19}, + {Name: "cpu", Time: 4 * Second, Value: 10}, + {Name: "cpu", Time: 0 * Second, Value: 20}, + }}, nil + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT derivative(value, 1s) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-01T00:00:16Z' ORDER BY desc`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Errorf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.FloatPoint{Name: "cpu", Time: 8 * Second, Value: 4}}, + {&influxql.FloatPoint{Name: "cpu", Time: 4 * Second, Value: -2.25}}, + {&influxql.FloatPoint{Name: "cpu", Time: 0 * Second, Value: 2.5}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + func TestSelect_Difference_Float(t *testing.T) { var ic IteratorCreator ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) {