diff --git a/CHANGELOG.md b/CHANGELOG.md index ae28217e3b6..432192e336b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - [#6334](https://github.com/influxdata/influxdb/pull/6334): Allow environment variables to be set per input type. - [#6394](https://github.com/influxdata/influxdb/pull/6394): Allow time math with integer timestamps. - [#3247](https://github.com/influxdata/influxdb/issues/3247): Implement derivatives across intervals for aggregate queries. +- [#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 3c752e8d4e7..1f4c14e6fe3 100644 --- a/influxql/select_test.go +++ b/influxql/select_test.go @@ -1895,6 +1895,54 @@ 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 := Iterators(itrs).ReadAll(); !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 := Iterators(itrs).ReadAll(); !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) {