This commit is contained in:
Aliaksandr Valialkin 2024-05-30 14:37:21 +02:00
parent b7c062ac61
commit a53b5570eb
No known key found for this signature in database
GPG key ID: 52C003EE2BCDB9EB
5 changed files with 55 additions and 3 deletions

View file

@ -19,6 +19,7 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
## tip
* FEATURE: add `default` operator to [`math` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#math-pipe). It allows setting `NaN` result to the given default value.
* FEATURE: allow omitting result name in [`stats` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#stats-pipe). In this case the result name is automatically set to string representation of the corresponding [stats function expression](https://docs.victoriametrics.com/victorialogs/logsql/#stats-pipe-functions). For example, `_time:5m | count(*)` is valid [LogsQL query](https://docs.victoriametrics.com/victorialogs/logsql/) now. It is equivalent to `_time:5m | stats count(*) as "count(*)"`.
* BUGFIX: properly calculate the number of matching rows in `* | field_values x | stats count() rows` and in `* | unroll (x) | stats count() rows` queries.

View file

@ -1608,6 +1608,7 @@ The following mathematical operations are supported by `math` pipe:
- `arg1 / arg2` - divides `arg1` by `arg2`
- `arg1 % arg2` - returns the remainder of the division of `arg1` by `arg2`
- `arg1 ^ arg2` - returns the power of `arg1` by `arg2`
- `arg1 default arg2` - returns `arg2` if `arg1` equals to `NaN`.
- `abs(arg)` - returns an absolute value for the given `arg`
- `max(arg1, ..., argN)` - returns the maximum value among the given `arg1`, ..., `argN`
- `min(arg1, ..., argN)` - returns the minimum value among the given `arg1`, ..., `argN`

View file

@ -161,6 +161,10 @@ var mathBinaryOps = map[string]mathBinaryOp{
priority: 3,
f: mathFuncMinus,
},
"default": {
priority: 10,
f: mathFuncDefault,
},
}
type mathBinaryOp struct {
@ -700,6 +704,18 @@ func mathFuncPow(result []float64, args [][]float64) {
}
}
func mathFuncDefault(result []float64, args [][]float64) {
values := args[0]
defaultValues := args[1]
for i := range result {
f := values[i]
if math.IsNaN(f) {
f = defaultValues[i]
}
result[i] = f
}
}
func mathFuncAbs(result []float64, args [][]float64) {
arg := args[0]
for i := range result {

View file

@ -22,6 +22,7 @@ func TestParsePipeMathSuccess(t *testing.T) {
f(`math min(3, foo, (1 + bar) / baz) as a, max(a, b) as b, (abs(c) + 5) as d`)
f(`math round(foo) as x`)
f(`math round(foo, 0.1) as y`)
f(`math (a / b default 10) as z`)
}
func TestParsePipeMathFailure(t *testing.T) {
@ -63,6 +64,39 @@ func TestPipeMath(t *testing.T) {
},
})
f("math a / b default 10 as c", [][]Field{
{
{"a", "v1"},
{"b", "2"},
{"c", "3"},
},
{
{"a", "0"},
{"b", "0"},
{"c", "3"},
},
{
{"a", "3"},
{"b", "2"},
},
}, [][]Field{
{
{"a", "v1"},
{"b", "2"},
{"c", "10"},
},
{
{"a", "0"},
{"b", "0"},
{"c", "10"},
},
{
{"a", "3"},
{"b", "2"},
{"c", "1.5"},
},
})
f("math 1 as a", [][]Field{
{
{"a", "v1"},

View file

@ -39,8 +39,8 @@ func TestPipeStats(t *testing.T) {
expectPipeResults(t, pipeStr, rows, rowsExpected)
}
// missing 'stats' keyword
f("count(*) as rows", [][]Field{
// missing 'stats' keyword and resutl name
f("count(*)", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
@ -56,7 +56,7 @@ func TestPipeStats(t *testing.T) {
},
}, [][]Field{
{
{"rows", "3"},
{`count(*)`, "3"},
},
})