pkg/query/aggregation/aggregation.go (81 lines of code) (raw):
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// Package aggregation implements aggregation functions to statistic a range of values.
package aggregation
import (
"math"
"github.com/pkg/errors"
modelv1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v1"
)
var (
errUnknownFunc = errors.New("unknown aggregation function")
errUnSupportedFieldType = errors.New("unsupported field type")
)
// Func supports aggregation operations.
type Func[N Number] interface {
In(N)
Val() N
Reset()
}
// Number denotes the supported number types.
type Number interface {
~int64 | ~float64
}
// NewFunc returns a aggregation function based on function type.
func NewFunc[N Number](af modelv1.AggregationFunction) (Func[N], error) {
var result Func[N]
switch af {
case modelv1.AggregationFunction_AGGREGATION_FUNCTION_MEAN:
result = &meanFunc[N]{zero: zero[N]()}
case modelv1.AggregationFunction_AGGREGATION_FUNCTION_COUNT:
result = &countFunc[N]{zero: zero[N]()}
case modelv1.AggregationFunction_AGGREGATION_FUNCTION_MAX:
result = &maxFunc[N]{min: minOf[N]()}
case modelv1.AggregationFunction_AGGREGATION_FUNCTION_MIN:
result = &minFunc[N]{max: maxOf[N]()}
case modelv1.AggregationFunction_AGGREGATION_FUNCTION_SUM:
result = &sumFunc[N]{zero: zero[N]()}
default:
return nil, errors.WithMessagef(errUnknownFunc, "unknown function:%s", modelv1.AggregationFunction_name[int32(af)])
}
result.Reset()
return result, nil
}
// FromFieldValue transforms modelv1.FieldValue to Number.
func FromFieldValue[N Number](fieldValue *modelv1.FieldValue) (N, error) {
switch fieldValue.GetValue().(type) {
case *modelv1.FieldValue_Int:
return N(fieldValue.GetInt().Value), nil
case *modelv1.FieldValue_Float:
return N(fieldValue.GetFloat().Value), nil
}
return zero[N](), errUnSupportedFieldType
}
// ToFieldValue transforms Number to modelv1.FieldValue.
func ToFieldValue[N Number](value N) (*modelv1.FieldValue, error) {
switch any(value).(type) {
case int64:
return &modelv1.FieldValue{Value: &modelv1.FieldValue_Int{Int: &modelv1.Int{Value: int64(value)}}}, nil
case float64:
return &modelv1.FieldValue{Value: &modelv1.FieldValue_Float{Float: &modelv1.Float{Value: float64(value)}}}, nil
}
return nil, errUnSupportedFieldType
}
func minOf[N Number]() (r N) {
switch x := any(&r).(type) {
case *int64:
*x = math.MinInt64
case *float64:
*x = -math.MaxFloat64
default:
panic("unreachable")
}
return
}
func maxOf[N Number]() (r N) {
switch x := any(&r).(type) {
case *int64:
*x = math.MaxInt64
case *float64:
*x = math.MaxFloat64
default:
panic("unreachable")
}
return
}
func zero[N Number]() N {
var z N
return z
}