Browse Source

promql: make scalar public

pull/2643/head
Fabian Reinartz 8 years ago
parent
commit
09666e2e2a
  1. 2
      promql/ast.go
  2. 58
      promql/engine.go
  3. 36
      promql/functions.go
  4. 12
      promql/parse.go
  5. 4
      promql/test.go
  6. 5
      template/template.go

2
promql/ast.go

@ -156,7 +156,7 @@ type StringLiteral struct {
}
// UnaryExpr represents a unary operation on another expression.
// Currently unary operations are only supported for scalars.
// Currently unary operations are only supported for Scalars.
type UnaryExpr struct {
Op itemType
Expr Expr

58
promql/engine.go

@ -52,7 +52,7 @@ type Value interface {
func (Matrix) Type() ValueType { return ValueTypeMatrix }
func (Vector) Type() ValueType { return ValueTypeVector }
func (scalar) Type() ValueType { return ValueTypeScalar }
func (Scalar) Type() ValueType { return ValueTypeScalar }
func (stringVal) Type() ValueType { return ValueTypeString }
// ValueType describes a type of a value.
@ -62,7 +62,7 @@ type ValueType string
const (
ValueTypeNone = "none"
ValueTypeVector = "Vector"
ValueTypeScalar = "scalar"
ValueTypeScalar = "Scalar"
ValueTypeMatrix = "Matrix"
ValueTypeString = "string"
)
@ -76,12 +76,12 @@ func (s stringVal) String() string {
return s.s
}
type scalar struct {
type Scalar struct {
t int64
v float64
}
func (s scalar) String() string {
func (s Scalar) String() string {
return ""
}
@ -175,15 +175,15 @@ func (r *Result) Matrix() (Matrix, error) {
return v, nil
}
// Scalar returns a scalar value. An error is returned if
// the result was an error or the result value is not a scalar.
func (r *Result) Scalar() (scalar, error) {
// Scalar returns a Scalar value. An error is returned if
// the result was an error or the result value is not a Scalar.
func (r *Result) Scalar() (Scalar, error) {
if r.Err != nil {
return scalar{}, r.Err
return Scalar{}, r.Err
}
v, ok := r.Value.(scalar)
v, ok := r.Value.(Scalar)
if !ok {
return scalar{}, fmt.Errorf("query result is not a scalar")
return Scalar{}, fmt.Errorf("query result is not a Scalar")
}
return v, nil
}
@ -336,7 +336,7 @@ func (ng *Engine) NewRangeQuery(qs string, start, end time.Time, interval time.D
return nil, err
}
if expr.Type() != ValueTypeVector && expr.Type() != ValueTypeScalar {
return nil, fmt.Errorf("invalid expression type %q for range query, must be scalar or instant Vector", documentedType(expr.Type()))
return nil, fmt.Errorf("invalid expression type %q for range query, must be Scalar or instant Vector", documentedType(expr.Type()))
}
qry := ng.newQuery(expr, start, end, interval)
qry.q = qs
@ -470,9 +470,9 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
}
switch v := val.(type) {
case scalar:
case Scalar:
// As the expression type does not change we can safely default to 0
// as the fingerprint for scalar expressions.
// as the fingerprint for Scalar expressions.
ss, ok := sampleStreams[0]
if !ok {
ss = sampleStream{Values: make([]samplePair, 0, numSteps)}
@ -633,12 +633,12 @@ func (ev *evaluator) recover(errp *error) {
}
}
// evalScalar attempts to evaluate e to a scalar value and errors otherwise.
func (ev *evaluator) evalScalar(e Expr) scalar {
// evalScalar attempts to evaluate e to a Scalar value and errors otherwise.
func (ev *evaluator) evalScalar(e Expr) Scalar {
val := ev.eval(e)
sv, ok := val.(scalar)
sv, ok := val.(Scalar)
if !ok {
ev.errorf("expected scalar but got %s", documentedType(val.Type()))
ev.errorf("expected Scalar but got %s", documentedType(val.Type()))
}
return sv
}
@ -657,7 +657,7 @@ func (ev *evaluator) evalVector(e Expr) Vector {
func (ev *evaluator) evalInt(e Expr) int64 {
sc := ev.evalScalar(e)
if !convertibleToInt64(sc.v) {
ev.errorf("scalar value %v overflows int64", sc.v)
ev.errorf("Scalar value %v overflows int64", sc.v)
}
return int64(sc.v)
}
@ -723,8 +723,8 @@ func (ev *evaluator) eval(expr Expr) Value {
switch lt, rt := lhs.Type(), rhs.Type(); {
case lt == ValueTypeScalar && rt == ValueTypeScalar:
return scalar{
v: scalarBinop(e.Op, lhs.(scalar).v, rhs.(scalar).v),
return Scalar{
v: ScalarBinop(e.Op, lhs.(Scalar).v, rhs.(Scalar).v),
t: ev.Timestamp,
}
@ -740,10 +740,10 @@ func (ev *evaluator) eval(expr Expr) Value {
return ev.VectorBinop(e.Op, lhs.(Vector), rhs.(Vector), e.VectorMatching, e.ReturnBool)
}
case lt == ValueTypeVector && rt == ValueTypeScalar:
return ev.VectorScalarBinop(e.Op, lhs.(Vector), rhs.(scalar), false, e.ReturnBool)
return ev.VectorScalarBinop(e.Op, lhs.(Vector), rhs.(Scalar), false, e.ReturnBool)
case lt == ValueTypeScalar && rt == ValueTypeVector:
return ev.VectorScalarBinop(e.Op, rhs.(Vector), lhs.(scalar), true, e.ReturnBool)
return ev.VectorScalarBinop(e.Op, rhs.(Vector), lhs.(Scalar), true, e.ReturnBool)
}
case *Call:
@ -753,7 +753,7 @@ func (ev *evaluator) eval(expr Expr) Value {
return ev.MatrixSelector(e)
case *NumberLiteral:
return scalar{v: e.Val, t: ev.Timestamp}
return Scalar{v: e.Val, t: ev.Timestamp}
case *ParenExpr:
return ev.eval(e.Expr)
@ -766,7 +766,7 @@ func (ev *evaluator) eval(expr Expr) Value {
// Only + and - are possible operators.
if e.Op == itemSUB {
switch v := se.(type) {
case scalar:
case Scalar:
v.v = -v.v
case Vector:
for i, sv := range v {
@ -1116,8 +1116,8 @@ Outer:
return res
}
// VectorScalarBinop evaluates a binary operation between a Vector and a scalar.
func (ev *evaluator) VectorScalarBinop(op itemType, lhs Vector, rhs scalar, swap, returnBool bool) Vector {
// VectorScalarBinop evaluates a binary operation between a Vector and a Scalar.
func (ev *evaluator) VectorScalarBinop(op itemType, lhs Vector, rhs Scalar, swap, returnBool bool) Vector {
vec := make(Vector, 0, len(lhs))
for _, lhsSample := range lhs {
@ -1161,8 +1161,8 @@ func copyLabels(metric labels.Labels, withName bool) labels.Labels {
return cm
}
// scalarBinop evaluates a binary operation between two scalars.
func scalarBinop(op itemType, lhs, rhs float64) float64 {
// ScalarBinop evaluates a binary operation between two Scalars.
func ScalarBinop(op itemType, lhs, rhs float64) float64 {
switch op {
case itemADD:
return lhs + rhs
@ -1189,7 +1189,7 @@ func scalarBinop(op itemType, lhs, rhs float64) float64 {
case itemLTE:
return btos(lhs <= rhs)
}
panic(fmt.Errorf("operator %q not allowed for scalar operations", op))
panic(fmt.Errorf("operator %q not allowed for Scalar operations", op))
}
// VectorElemBinop evaluates a binary operation between two Vector elements.

36
promql/functions.go

@ -36,7 +36,7 @@ type Function struct {
// === time() float64 ===
func funcTime(ev *evaluator, args Expressions) Value {
return scalar{
return Scalar{
v: float64(ev.Timestamp / 1000),
t: ev.Timestamp,
}
@ -384,24 +384,24 @@ func funcRound(ev *evaluator, args Expressions) Value {
return vec
}
// === scalar(node ValueTypeVector) Scalar ===
// === Scalar(node ValueTypeVector) Scalar ===
func funcScalar(ev *evaluator, args Expressions) Value {
v := ev.evalVector(args[0])
if len(v) != 1 {
return scalar{
return Scalar{
v: math.NaN(),
t: ev.Timestamp,
}
}
return scalar{
return Scalar{
v: v[0].Value,
t: ev.Timestamp,
}
}
// === count_scalar(Vector ValueTypeVector) float64 ===
// === count_Scalar(Vector ValueTypeVector) float64 ===
func funcCountScalar(ev *evaluator, args Expressions) Value {
return scalar{
return Scalar{
v: float64(len(ev.evalVector(args[0]))),
t: ev.Timestamp,
}
@ -840,7 +840,7 @@ func funcLabelReplace(ev *evaluator, args Expressions) Value {
return Vector
}
// === Vector(s scalar) Vector ===
// === Vector(s Scalar) Vector ===
func funcVector(ev *evaluator, args Expressions) Value {
return Vector{
sample{
@ -872,49 +872,49 @@ func dateWrapper(ev *evaluator, args Expressions, f func(time.Time) float64) Val
return v
}
// === days_in_month(v Vector) scalar ===
// === days_in_month(v Vector) Scalar ===
func funcDaysInMonth(ev *evaluator, args Expressions) Value {
return dateWrapper(ev, args, func(t time.Time) float64 {
return float64(32 - time.Date(t.Year(), t.Month(), 32, 0, 0, 0, 0, time.UTC).Day())
})
}
// === day_of_month(v Vector) scalar ===
// === day_of_month(v Vector) Scalar ===
func funcDayOfMonth(ev *evaluator, args Expressions) Value {
return dateWrapper(ev, args, func(t time.Time) float64 {
return float64(t.Day())
})
}
// === day_of_week(v Vector) scalar ===
// === day_of_week(v Vector) Scalar ===
func funcDayOfWeek(ev *evaluator, args Expressions) Value {
return dateWrapper(ev, args, func(t time.Time) float64 {
return float64(t.Weekday())
})
}
// === hour(v Vector) scalar ===
// === hour(v Vector) Scalar ===
func funcHour(ev *evaluator, args Expressions) Value {
return dateWrapper(ev, args, func(t time.Time) float64 {
return float64(t.Hour())
})
}
// === minute(v Vector) scalar ===
// === minute(v Vector) Scalar ===
func funcMinute(ev *evaluator, args Expressions) Value {
return dateWrapper(ev, args, func(t time.Time) float64 {
return float64(t.Minute())
})
}
// === month(v Vector) scalar ===
// === month(v Vector) Scalar ===
func funcMonth(ev *evaluator, args Expressions) Value {
return dateWrapper(ev, args, func(t time.Time) float64 {
return float64(t.Month())
})
}
// === year(v Vector) scalar ===
// === year(v Vector) Scalar ===
func funcYear(ev *evaluator, args Expressions) Value {
return dateWrapper(ev, args, func(t time.Time) float64 {
return float64(t.Year())
@ -970,8 +970,8 @@ var functions = map[string]*Function{
ReturnType: ValueTypeVector,
Call: funcCountOverTime,
},
"count_scalar": {
Name: "count_scalar",
"count_Scalar": {
Name: "count_Scalar",
ArgTypes: []ValueType{ValueTypeVector},
ReturnType: ValueTypeScalar,
Call: funcCountScalar,
@ -1145,8 +1145,8 @@ var functions = map[string]*Function{
ReturnType: ValueTypeVector,
Call: funcRound,
},
"scalar": {
Name: "scalar",
"Scalar": {
Name: "Scalar",
ArgTypes: []ValueType{ValueTypeVector},
ReturnType: ValueTypeScalar,
Call: funcScalar,

12
promql/parse.go

@ -506,7 +506,7 @@ func (p *parser) balance(lhs Expr, op itemType, rhs Expr, vecMatching *VectorMat
if (precd < 0) || (precd == 0 && op.isRightAssociative()) {
balanced := p.balance(lhsBE.RHS, op, rhs, vecMatching, returnBool)
if lhsBE.Op.isComparisonOperator() && !lhsBE.ReturnBool && balanced.Type() == ValueTypeScalar && lhsBE.LHS.Type() == ValueTypeScalar {
p.errorf("comparisons between scalars must use BOOL modifier")
p.errorf("comparisons between Scalars must use BOOL modifier")
}
return &BinaryExpr{
Op: lhsBE.Op,
@ -518,7 +518,7 @@ func (p *parser) balance(lhs Expr, op itemType, rhs Expr, vecMatching *VectorMat
}
}
if op.isComparisonOperator() && !returnBool && rhs.Type() == ValueTypeScalar && lhs.Type() == ValueTypeScalar {
p.errorf("comparisons between scalars must use BOOL modifier")
p.errorf("comparisons between Scalars must use BOOL modifier")
}
return &BinaryExpr{
Op: op,
@ -1028,7 +1028,7 @@ func (p *parser) checkType(node Node) (typ ValueType) {
case *RecordStmt:
ty := p.checkType(n.Expr)
if ty != ValueTypeVector && ty != ValueTypeScalar {
p.errorf("record statement must have a valid expression of type instant Vector or scalar but got %s", documentedType(ty))
p.errorf("record statement must have a valid expression of type instant Vector or Scalar but got %s", documentedType(ty))
}
case Expressions:
@ -1058,7 +1058,7 @@ func (p *parser) checkType(node Node) (typ ValueType) {
p.errorf("binary expression does not support operator %q", n.Op)
}
if (lt != ValueTypeScalar && lt != ValueTypeVector) || (rt != ValueTypeScalar && rt != ValueTypeVector) {
p.errorf("binary expression must contain only scalar and instant Vector types")
p.errorf("binary expression must contain only Scalar and instant Vector types")
}
if (lt != ValueTypeVector || rt != ValueTypeVector) && n.VectorMatching != nil {
@ -1079,7 +1079,7 @@ func (p *parser) checkType(node Node) (typ ValueType) {
}
if (lt == ValueTypeScalar || rt == ValueTypeScalar) && n.Op.isSetOperator() {
p.errorf("set operator %q not allowed in binary scalar expression", n.Op)
p.errorf("set operator %q not allowed in binary Scalar expression", n.Op)
}
case *Call:
@ -1102,7 +1102,7 @@ func (p *parser) checkType(node Node) (typ ValueType) {
p.errorf("only + and - operators allowed for unary expressions")
}
if t := p.checkType(n.Expr); t != ValueTypeScalar && t != ValueTypeVector {
p.errorf("unary expression only allowed on expressions of type scalar or instant Vector, got %q", documentedType(t))
p.errorf("unary expression only allowed on expressions of type Scalar or instant Vector, got %q", documentedType(t))
}
case *NumberLiteral, *MatrixSelector, *StringLiteral, *VectorSelector:

4
promql/test.go

@ -404,9 +404,9 @@ func (ev *evalCmd) compareResult(result Value) error {
}
}
case scalar:
case Scalar:
if !almostEqual(ev.expected[0].vals[0].value, val.v) {
return fmt.Errorf("expected scalar %v but got %v", val.v, ev.expected[0].vals[0].value)
return fmt.Errorf("expected Scalar %v but got %v", val.v, ev.expected[0].vals[0].value)
}
default:

5
template/template.go

@ -21,6 +21,7 @@ import (
"regexp"
"sort"
"strings"
"time"
html_template "html/template"
text_template "text/template"
@ -56,8 +57,8 @@ func (q queryResultByLabelSorter) Swap(i, j int) {
q.results[i], q.results[j] = q.results[j], q.results[i]
}
func query(ctx context.Context, q string, timestamp model.Time, queryEngine *promql.Engine) (queryResult, error) {
query, err := queryEngine.NewInstantQuery(q, timestamp)
func query(ctx context.Context, q string, ts time.Time, queryEngine *promql.Engine) (queryResult, error) {
query, err := queryEngine.NewInstantQuery(q, ts)
if err != nil {
return nil, err
}

Loading…
Cancel
Save