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.
This commit is contained in:
Fabian Reinartz 2015-06-09 12:52:27 +02:00
parent db4df06414
commit cb10ceac18

View file

@ -279,6 +279,9 @@ func (ng *Engine) NewRangeQuery(qs string, start, end clientmodel.Timestamp, int
if err != nil { if err != nil {
return nil, err 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 := ng.newQuery(expr, start, end, interval)
qry.q = qs qry.q = qs
@ -413,6 +416,7 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
evalTimer.Stop() evalTimer.Stop()
return val, nil return val, nil
} }
numSteps := int(s.End.Sub(s.Start) / s.Interval)
// Range evaluation. // Range evaluation.
sampleStreams := map[clientmodel.Fingerprint]*SampleStream{} sampleStreams := map[clientmodel.Fingerprint]*SampleStream{}
@ -430,26 +434,36 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
if err != nil { if err != nil {
return nil, err 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 { switch v := val.(type) {
samplePair := metric.SamplePair{ case *Scalar:
Value: sample.Value, // As the expression type does not change we can safely default to 0
Timestamp: sample.Timestamp, // 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() ss.Values = append(ss.Values, metric.SamplePair{
if sampleStreams[fp] == nil { Value: v.Value,
sampleStreams[fp] = &SampleStream{ Timestamp: v.Timestamp,
Metric: sample.Metric, })
Values: metric.Values{samplePair}, 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 { ss.Values = append(ss.Values, metric.SamplePair{
sampleStreams[fp].Values = append(sampleStreams[fp].Values, samplePair) Value: sample.Value,
} Timestamp: sample.Timestamp,
})
}
default:
panic(fmt.Errorf("promql.Engine.exec: invalid expression type %q", val.Type()))
} }
} }
evalTimer.Stop() evalTimer.Stop()