diff --git a/promql/functions.go b/promql/functions.go index 2ff25c3acf..2602c25c1d 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -1709,15 +1709,19 @@ func funcHistogramQuantile(vectorVals []Vector, _ Matrix, args parser.Expression // pickFirstSampleIndex returns the index of the last sample before // or at the range start, or 0 if none exist before the range start. -// If the vector selector is not anchored, it always returns 0. -func pickFirstSampleIndex(floats []FPoint, args parser.Expressions, enh *EvalNodeHelper) int { +// If the vector selector is not anchored, it always returns 0, true. +// The second return value is false if there are no samples in range (for anchored selectors). +func pickFirstSampleIndex(floats []FPoint, args parser.Expressions, enh *EvalNodeHelper) (int, bool) { ms := args[0].(*parser.MatrixSelector) vs := ms.VectorSelector.(*parser.VectorSelector) if !vs.Anchored { - return 0 + return 0, true } rangeStart := enh.Ts - durationMilliseconds(ms.Range+vs.Offset) - return max(0, sort.Search(len(floats)-1, func(i int) bool { return floats[i].T > rangeStart })-1) + if len(floats) == 0 || floats[len(floats)-1].T <= rangeStart { + return 0, false + } + return max(0, sort.Search(len(floats)-1, func(i int) bool { return floats[i].T > rangeStart })-1), true } // === resets(Matrix parser.ValueTypeMatrix) (Vector, Annotations) === @@ -1730,7 +1734,10 @@ func funcResets(_ []Vector, matrixVal Matrix, args parser.Expressions, enh *Eval } var prevSample, curSample Sample - firstSampleIndex := pickFirstSampleIndex(floats, args, enh) + firstSampleIndex, found := pickFirstSampleIndex(floats, args, enh) + if !found { + return enh.Out, nil + } for iFloat, iHistogram := firstSampleIndex, 0; iFloat < len(floats) || iHistogram < len(histograms); { switch { // Process a float sample if no histogram sample remains or its timestamp is earlier. @@ -1776,7 +1783,10 @@ func funcChanges(_ []Vector, matrixVal Matrix, args parser.Expressions, enh *Eva } var prevSample, curSample Sample - firstSampleIndex := pickFirstSampleIndex(floats, args, enh) + firstSampleIndex, found := pickFirstSampleIndex(floats, args, enh) + if !found { + return enh.Out, nil + } for iFloat, iHistogram := firstSampleIndex, 0; iFloat < len(floats) || iHistogram < len(histograms); { switch { // Process a float sample if no histogram sample remains or its timestamp is earlier. diff --git a/promql/promqltest/testdata/extended_vectors.test b/promql/promqltest/testdata/extended_vectors.test index 8e116b1ac5..8f431dcfd3 100644 --- a/promql/promqltest/testdata/extended_vectors.test +++ b/promql/promqltest/testdata/extended_vectors.test @@ -319,7 +319,6 @@ eval instant at 2m changes(metric[1m] anchored) {id="2"} 1 eval instant at 3m changes(metric[1m] anchored) - {id="1"} 1 {id="2"} 1 eval instant at 8m changes(metric[1m] anchored) @@ -342,7 +341,6 @@ eval instant at 2m resets(metric[1m] anchored) {id="2"} 1 eval instant at 3m resets(metric[1m] anchored) - {id="1"} 1 {id="2"} 1 eval instant at 8m resets(metric[1m] anchored)