From d1a9fac8942bb80c74404c43149bb49f7cf7dfdc Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Thu, 21 Apr 2022 14:55:35 +0300 Subject: [PATCH] app/vmselect/promql: fix comparison to nan The comparison to nan has been broken in d335cc886c62480934cf237efbce54400bda1ae0 Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/150 --- app/vmselect/promql/binary_op.go | 12 ++++++++---- app/vmselect/promql/exec_test.go | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/vmselect/promql/binary_op.go b/app/vmselect/promql/binary_op.go index e24f6dba13..db1f729ca9 100644 --- a/app/vmselect/promql/binary_op.go +++ b/app/vmselect/promql/binary_op.go @@ -84,18 +84,22 @@ func newBinaryOpFunc(bf func(left, right float64, isBool bool) float64) binaryOp return func(bfa *binaryOpFuncArg) ([]*timeseries, error) { left := bfa.left right := bfa.right - switch bfa.be.Op { - case "ifnot": + op := bfa.be.Op + switch true { + case op == "ifnot": left = removeEmptySeries(left) // Do not remove empty series on the right side, // so the left-side series could be matched against them. - case "default": + case op == "default": // Do not remove empty series on the left and the right side, - // since this may result in missing result: + // since this may lead to missing result: // - if empty time series are removed on the left side, // then they won't be substituted by time series from the right side. // - if empty time series are removed on the right side, // then this may result in missing time series from the left side. + case metricsql.IsBinaryOpCmp(op): + // Do not remove empty series for comparison operations, + // since this may lead to missing result. default: left = removeEmptySeries(left) right = removeEmptySeries(right) diff --git a/app/vmselect/promql/exec_test.go b/app/vmselect/promql/exec_test.go index 25114e394e..06f0388a94 100644 --- a/app/vmselect/promql/exec_test.go +++ b/app/vmselect/promql/exec_test.go @@ -2625,6 +2625,23 @@ func TestExecSuccess(t *testing.T) { resultExpected := []netstorage.Result{} f(q, resultExpected) }) + t.Run(`compare_to_nan_right`, func(t *testing.T) { + t.Parallel() + q := `1 != nan` + r := netstorage.Result{ + MetricName: metricNameExpected, + Values: []float64{1, 1, 1, 1, 1, 1}, + Timestamps: timestampsExpected, + } + resultExpected := []netstorage.Result{r} + f(q, resultExpected) + }) + t.Run(`compare_to_nan_left`, func(t *testing.T) { + t.Parallel() + q := `nan != 1` + resultExpected := []netstorage.Result{} + f(q, resultExpected) + }) t.Run(`-1 < 2`, func(t *testing.T) { t.Parallel() q := `-1 < 2`