@@ -27,7 +27,6 @@ import (
27
27
"github.com/thanos-io/promql-engine/execution/model"
28
28
"github.com/thanos-io/promql-engine/execution/parse"
29
29
"github.com/thanos-io/promql-engine/execution/warnings"
30
- "github.com/thanos-io/promql-engine/extlabels"
31
30
"github.com/thanos-io/promql-engine/logicalplan"
32
31
"github.com/thanos-io/promql-engine/query"
33
32
)
@@ -404,22 +403,42 @@ loop:
404
403
}
405
404
406
405
// For range Query we expect always a Matrix value type.
406
+ // Note: We have to zip together series that have the same label but
407
+ // appear at different timestamps.
408
+ // The engine already guarantees that we dont have a label conflict
409
+ // in the same timestamp and prometheus accepts series with the same
410
+ // labels that are populated at different timestamps just fine.
407
411
if q .t == RangeQuery {
408
412
matrix := make (promql.Matrix , 0 , len (series ))
409
- for _ , s := range series {
413
+ seenAt := make (map [uint64 ]int , len (series ))
414
+ for i , s := range series {
410
415
if len (s .Floats )+ len (s .Histograms ) == 0 {
411
416
continue
412
417
}
413
- matrix = append (matrix , s )
418
+ h := s .Metric .Hash ()
419
+ if j , ok := seenAt [h ]; ok {
420
+ matrix [j ].Floats = append (matrix [j ].Floats , s .Floats ... )
421
+ matrix [j ].Histograms = append (matrix [j ].Histograms , s .Histograms ... )
422
+ } else {
423
+ matrix = append (matrix , s )
424
+ seenAt [h ] = i
425
+ }
414
426
}
415
427
sort .Sort (matrix )
416
- if matrix .ContainsSameLabelset () {
417
- return newErrResult (ret , extlabels .ErrDuplicateLabelSet )
428
+ if len (seenAt ) < len (series ) {
429
+ // If we had collisions, we need to resort by timestamp, since we might have added
430
+ // samples from the later collision pair first.
431
+ for _ , s := range matrix {
432
+ sort .Slice (s .Floats , func (i , j int ) bool { return s .Floats [i ].T < s .Floats [j ].T })
433
+ sort .Slice (s .Histograms , func (i , j int ) bool { return s .Histograms [i ].T < s .Histograms [j ].T })
434
+ }
418
435
}
419
436
ret .Value = matrix
420
437
return ret
421
438
}
422
439
440
+ // We dont need to zip together results for instant queries since
441
+ // they only have results for one timestamp.
423
442
var result parser.Value
424
443
switch q .expr .Type () {
425
444
case parser .ValueTypeMatrix :
0 commit comments