From cb10ceac18d9ccbea160533a48c3701e9997c29f Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Tue, 9 Jun 2015 12:52:27 +0200 Subject: [PATCH] promql: allow scalar expressions in range queries, improve errors. These changes allow to do range queries over scalar expressions. Errors on bad types for range queries are now raised on query creation rather than evaluation. --- promql/engine.go | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/promql/engine.go b/promql/engine.go index d9cf43eef..990198cce 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -279,6 +279,9 @@ func (ng *Engine) NewRangeQuery(qs string, start, end clientmodel.Timestamp, int if err != nil { return nil, err } + if expr.Type() != ExprVector && expr.Type() != ExprScalar { + return nil, fmt.Errorf("invalid expression type %q for range query, must be scalar or vector", expr.Type()) + } qry := ng.newQuery(expr, start, end, interval) qry.q = qs @@ -413,6 +416,7 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) ( evalTimer.Stop() return val, nil } + numSteps := int(s.End.Sub(s.Start) / s.Interval) // Range evaluation. sampleStreams := map[clientmodel.Fingerprint]*SampleStream{} @@ -430,26 +434,36 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) ( if err != nil { return nil, err } - vector, ok := val.(Vector) - if !ok { - return nil, fmt.Errorf("value for expression %q must be of type vector but is %s", s.Expr, val.Type()) - } - for _, sample := range vector { - samplePair := metric.SamplePair{ - Value: sample.Value, - Timestamp: sample.Timestamp, + switch v := val.(type) { + case *Scalar: + // As the expression type does not change we can safely default to 0 + // as the fingerprint for scalar expressions. + ss := sampleStreams[0] + if ss == nil { + ss = &SampleStream{Values: make(metric.Values, 0, numSteps)} + sampleStreams[0] = ss } - fp := sample.Metric.Metric.Fingerprint() - if sampleStreams[fp] == nil { - sampleStreams[fp] = &SampleStream{ - Metric: sample.Metric, - Values: metric.Values{samplePair}, + ss.Values = append(ss.Values, metric.SamplePair{ + Value: v.Value, + Timestamp: v.Timestamp, + }) + case Vector: + for _, sample := range v { + fp := sample.Metric.Metric.Fingerprint() + ss := sampleStreams[fp] + if ss == nil { + ss = &SampleStream{Values: make(metric.Values, 0, numSteps)} + sampleStreams[fp] = ss } - } else { - sampleStreams[fp].Values = append(sampleStreams[fp].Values, samplePair) - } + ss.Values = append(ss.Values, metric.SamplePair{ + Value: sample.Value, + Timestamp: sample.Timestamp, + }) + } + default: + panic(fmt.Errorf("promql.Engine.exec: invalid expression type %q", val.Type())) } } evalTimer.Stop()