Skip to content

Commit

Permalink
Add sort and sort_desc (#1104)
Browse files Browse the repository at this point in the history
  • Loading branch information
benraskin92 authored Oct 18, 2018
1 parent 7b2fdac commit f327667
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 16 deletions.
32 changes: 32 additions & 0 deletions src/query/functions/linear/sort.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package linear

const (
// NB: Because Prometheus's sort and sort_desc only look at the last value,
// these functions are essentially noops in M3 as we don't support instant queries.

// SortType returns timeseries elements sorted by their values, in ascending order.
SortType = "sort"

// SortDescType is the same as sort, but sorts in descending order.
SortDescType = "sort_desc"
)
6 changes: 5 additions & 1 deletion src/query/parser/promql/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,15 @@ func (p *parseState) walk(node pql.Node) error {
}
}

op, err := NewFunctionExpr(n.Func.Name, argValues, stringValues)
op, ok, err := NewFunctionExpr(n.Func.Name, argValues, stringValues)
if err != nil {
return err
}

if !ok {
return nil
}

opTransform := parser.NewTransformFromOperation(op, p.transformLen())
if op.OpType() != scalar.TimeType {
p.edges = append(p.edges, parser.Edge{
Expand Down
24 changes: 24 additions & 0 deletions src/query/parser/promql/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,30 @@ func TestLinearParses(t *testing.T) {
}
}

var sortTests = []struct {
q string
expectedType string
}{
{"sort(up)", linear.SortType},
{"sort_desc(up)", linear.SortDescType},
}

func TestSort(t *testing.T) {
for _, tt := range sortTests {
t.Run(tt.q, func(t *testing.T) {
q := tt.q
p, err := Parse(q, models.NewTagOptions())
require.NoError(t, err)
transforms, edges, err := p.DAG()
require.NoError(t, err)
assert.Len(t, transforms, 1)
assert.Equal(t, transforms[0].Op.OpType(), functions.FetchType)
assert.Equal(t, transforms[0].ID, parser.NodeID("0"))
assert.Len(t, edges, 0)
})
}
}

func TestTimeTypeParse(t *testing.T) {
q := "time()"
p, err := Parse(q, models.NewTagOptions())
Expand Down
49 changes: 34 additions & 15 deletions src/query/parser/promql/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,55 +171,74 @@ func NewFunctionExpr(
name string,
argValues []interface{},
stringValues []string,
) (parser.Params, error) {
) (parser.Params, bool, error) {
var p parser.Params
var err error

switch name {
case linear.AbsType, linear.CeilType, linear.ExpType, linear.FloorType, linear.LnType,
linear.Log10Type, linear.Log2Type, linear.SqrtType:
return linear.NewMathOp(name)
p, err = linear.NewMathOp(name)
return p, true, err

case linear.AbsentType:
return linear.NewAbsentOp(), nil
p = linear.NewAbsentOp()
return p, true, err

case linear.ClampMinType, linear.ClampMaxType:
return linear.NewClampOp(argValues, name)
p, err = linear.NewClampOp(argValues, name)
return p, true, err

case linear.RoundType:
return linear.NewRoundOp(argValues)
p, err = linear.NewRoundOp(argValues)
return p, true, err

case linear.DayOfMonthType, linear.DayOfWeekType, linear.DaysInMonthType, linear.HourType,
linear.MinuteType, linear.MonthType, linear.YearType:
return linear.NewDateOp(name)
p, err = linear.NewDateOp(name)
return p, true, err

case tag.TagJoinType, tag.TagReplaceType:
return tag.NewTagOp(name, stringValues)
p, err = tag.NewTagOp(name, stringValues)
return p, true, err

case temporal.AvgType, temporal.CountType, temporal.MinType,
temporal.MaxType, temporal.SumType, temporal.StdDevType,
temporal.StdVarType:
return temporal.NewAggOp(argValues, name)
p, err = temporal.NewAggOp(argValues, name)
return p, true, err

case temporal.HoltWintersType:
return temporal.NewHoltWintersOp(argValues)
p, err = temporal.NewHoltWintersOp(argValues)
return p, true, err

case temporal.IRateType, temporal.IDeltaType, temporal.RateType, temporal.IncreaseType,
temporal.DeltaType:
return temporal.NewRateOp(argValues, name)
p, err = temporal.NewRateOp(argValues, name)
return p, true, err

case temporal.PredictLinearType, temporal.DerivType:
return temporal.NewLinearRegressionOp(argValues, name)
p, err = temporal.NewLinearRegressionOp(argValues, name)
return p, true, err

case temporal.ResetsType, temporal.ChangesType:
return temporal.NewFunctionOp(argValues, name)
p, err = temporal.NewFunctionOp(argValues, name)
return p, true, err

case linear.SortType, linear.SortDescType:
return nil, false, err

case unconsolidated.TimestampType:
return unconsolidated.NewTimestampOp(name)
p, err = unconsolidated.NewTimestampOp(name)
return p, true, err

case scalar.TimeType:
return scalar.NewScalarOp(func(t time.Time) float64 { return float64(t.Unix()) }, scalar.TimeType)
p, err = scalar.NewScalarOp(func(t time.Time) float64 { return float64(t.Unix()) }, scalar.TimeType)
return p, true, err

default:
// TODO: handle other types
return nil, fmt.Errorf("function not supported: %s", name)
return nil, false, fmt.Errorf("function not supported: %s", name)
}
}

Expand Down

0 comments on commit f327667

Please sign in to comment.