Merge pull request #3610 from influxdb/jw-derivative

Fix panic when running derivative on non-numeric values
pull/3612/head
Jason Wilder 2015-08-10 13:04:21 -06:00
commit 2b33302d07
3 changed files with 128 additions and 4 deletions

View File

@ -27,6 +27,7 @@
- [#3580](https://github.com/influxdb/influxdb/issues/3580): Do not allow wildcards with fields in select statements
- [#3530](https://github.com/influxdb/influxdb/pull/3530): Aliasing a column no longer works
- [#3436](https://github.com/influxdb/influxdb/issues/3436): Fix panic in hinted handoff queue processor
- [#3401](https://github.com/influxdb/influxdb/issues/3401): Derivative on non-numeric fields panics db
## v0.9.2 [2015-07-24]

View File

@ -757,14 +757,31 @@ type RawQueryDerivativeProcessor struct {
DerivativeInterval time.Duration
}
func (rqdp *RawQueryDerivativeProcessor) canProcess(input []*MapperValue) bool {
// If we only have 1 value, then the value did not change, so return
// a single row with 0.0
if len(input) == 1 {
return false
}
// See if the field value is numeric, if it's not, we can't process the derivative
validType := false
switch input[0].Value.(type) {
case int64:
validType = true
case float64:
validType = true
}
return validType
}
func (rqdp *RawQueryDerivativeProcessor) Process(input []*MapperValue) []*MapperValue {
if len(input) == 0 {
return input
}
// If we only have 1 value, then the value did not change, so return
// a single row with 0.0
if len(input) == 1 {
if !rqdp.canProcess(input) {
return []*MapperValue{
&MapperValue{
Time: input[0].Time,
@ -858,6 +875,22 @@ func ProcessAggregateDerivative(results [][]interface{}, isNonNegative bool, int
}
}
// Check the value's type to ensure it's an numeric, if not, return a 0 result. We only check the first value
// because derivatives cannot be combined with other aggregates currently.
validType := false
switch results[0][1].(type) {
case int64:
validType = true
case float64:
validType = true
}
if !validType {
return [][]interface{}{
[]interface{}{results[0][0], 0.0},
}
}
// Otherwise calculate the derivatives as the difference between consecutive
// points divided by the elapsed time. Then normalize to the requested
// interval.

View File

@ -579,7 +579,7 @@ func TestProcessAggregateDerivative(t *testing.T) {
},
},
{
name: "float derivatives",
name: "integer derivatives",
fn: "derivative",
interval: 24 * time.Hour,
in: [][]interface{}{
@ -608,6 +608,30 @@ func TestProcessAggregateDerivative(t *testing.T) {
},
},
},
{
name: "string derivatives",
fn: "derivative",
interval: 24 * time.Hour,
in: [][]interface{}{
[]interface{}{
time.Unix(0, 0), "1.0",
},
[]interface{}{
time.Unix(0, 0).Add(24 * time.Hour), "2.0",
},
[]interface{}{
time.Unix(0, 0).Add(48 * time.Hour), "3.0",
},
[]interface{}{
time.Unix(0, 0).Add(72 * time.Hour), "4.0",
},
},
exp: [][]interface{}{
[]interface{}{
time.Unix(0, 0), 0.0,
},
},
},
}
for _, test := range tests {
@ -697,6 +721,43 @@ func TestProcessRawQueryDerivative(t *testing.T) {
},
},
},
{
name: "integer derivative",
fn: "derivative",
interval: 24 * time.Hour,
in: []*tsdb.MapperValue{
{
Time: time.Unix(0, 0).Unix(),
Value: int64(0),
},
{
Time: time.Unix(0, 0).Add(24 * time.Hour).UnixNano(),
Value: int64(3),
},
{
Time: time.Unix(0, 0).Add(48 * time.Hour).UnixNano(),
Value: int64(5),
},
{
Time: time.Unix(0, 0).Add(72 * time.Hour).UnixNano(),
Value: int64(9),
},
},
exp: []*tsdb.MapperValue{
{
Time: time.Unix(0, 0).Add(24 * time.Hour).UnixNano(),
Value: 3.0,
},
{
Time: time.Unix(0, 0).Add(48 * time.Hour).UnixNano(),
Value: 2.0,
},
{
Time: time.Unix(0, 0).Add(72 * time.Hour).UnixNano(),
Value: 4.0,
},
},
},
{
name: "12h interval",
fn: "derivative",
@ -806,6 +867,35 @@ func TestProcessRawQueryDerivative(t *testing.T) {
},
},
},
{
name: "string derivatives",
fn: "derivative",
interval: 24 * time.Hour,
in: []*tsdb.MapperValue{
{
Time: time.Unix(0, 0).Unix(),
Value: "1.0",
},
{
Time: time.Unix(0, 0).Add(24 * time.Hour).UnixNano(),
Value: "2.0",
},
{
Time: time.Unix(0, 0).Add(48 * time.Hour).UnixNano(),
Value: "3.0",
},
{
Time: time.Unix(0, 0).Add(72 * time.Hour).UnixNano(),
Value: "4.0",
},
},
exp: []*tsdb.MapperValue{
{
Time: time.Unix(0, 0).Unix(),
Value: 0.0,
},
},
},
}
for _, test := range tests {