promql: copy data when short-circuiting (#9552)

* promql: copy data when short-circuiting

Because the range query loop re-uses the output buffer each time round,
we must copy results into the buffer rather than using input as output.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
This commit is contained in:
Bryan Boreham 2021-10-20 15:03:02 +01:00 committed by GitHub
parent 1043d2b594
commit a278ea4b58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 3 deletions

View File

@ -1792,9 +1792,11 @@ func (ev *evaluator) VectorOr(lhs, rhs Vector, matching *parser.VectorMatching,
panic("set operations must only use many-to-many matching")
}
if len(lhs) == 0 { // Short-circuit.
return rhs
enh.Out = append(enh.Out, rhs...)
return enh.Out
} else if len(rhs) == 0 {
return lhs
enh.Out = append(enh.Out, lhs...)
return enh.Out
}
leftSigs := map[string]struct{}{}
@ -1819,7 +1821,8 @@ func (ev *evaluator) VectorUnless(lhs, rhs Vector, matching *parser.VectorMatchi
// Short-circuit: empty rhs means we will return everything in lhs;
// empty lhs means we will return empty - don't need to build a map.
if len(lhs) == 0 || len(rhs) == 0 {
return lhs
enh.Out = append(enh.Out, lhs...)
return enh.Out
}
rightSigs := map[string]struct{}{}

View File

@ -2410,6 +2410,32 @@ func TestRangeQuery(t *testing.T) {
End: time.Unix(120, 0),
Interval: 1 * time.Minute,
},
{
Name: "short-circuit",
Load: `load 30s
foo{job="1"} 1+1x4
bar{job="2"} 1+1x4`,
Query: `foo > 2 or bar`,
Result: Matrix{
Series{
Points: []Point{{V: 1, T: 0}, {V: 3, T: 60000}, {V: 5, T: 120000}},
Metric: labels.Labels{
labels.Label{Name: "__name__", Value: "bar"},
labels.Label{Name: "job", Value: "2"},
},
},
Series{
Points: []Point{{V: 3, T: 60000}, {V: 5, T: 120000}},
Metric: labels.Labels{
labels.Label{Name: "__name__", Value: "foo"},
labels.Label{Name: "job", Value: "1"},
},
},
},
Start: time.Unix(0, 0),
End: time.Unix(120, 0),
Interval: 1 * time.Minute,
},
}
for _, c := range cases {
t.Run(c.Name, func(t *testing.T) {