1
0
mirror of https://github.com/MontFerret/ferret.git synced 2024-12-16 11:37:36 +02:00
ferret/pkg/runtime/expressions/clauses/sort.go
2018-10-28 01:45:26 -04:00

90 lines
2.0 KiB
Go

package clauses
import (
"context"
"github.com/MontFerret/ferret/pkg/runtime/collections"
"github.com/MontFerret/ferret/pkg/runtime/core"
)
type (
SorterExpression struct {
expression core.Expression
direction collections.SortDirection
}
SortClause struct {
src core.SourceMap
dataSource collections.Iterable
sorters []*SorterExpression
}
)
func NewSorterExpression(expression core.Expression, direction collections.SortDirection) (*SorterExpression, error) {
if expression == nil {
return nil, core.Error(core.ErrMissedArgument, "reducer")
}
if !collections.IsValidSortDirection(direction) {
return nil, core.Error(core.ErrInvalidArgument, "direction")
}
return &SorterExpression{expression, direction}, nil
}
func NewSortClause(
src core.SourceMap,
dataSource collections.Iterable,
sorters ...*SorterExpression,
) (collections.Iterable, error) {
if dataSource == nil {
return nil, core.Error(core.ErrMissedArgument, "dataSource source")
}
if len(sorters) == 0 {
return nil, core.Error(core.ErrMissedArgument, "sorters")
}
return &SortClause{src, dataSource, sorters}, nil
}
func (clause *SortClause) Iterate(ctx context.Context, scope *core.Scope) (collections.Iterator, error) {
src, err := clause.dataSource.Iterate(ctx, scope)
if err != nil {
return nil, err
}
sorters := make([]*collections.Sorter, len(clause.sorters))
// converting sorter reducer into collections.Sorter
for idx, srt := range clause.sorters {
sorter, err := newSorter(srt)
if err != nil {
return nil, err
}
sorters[idx] = sorter
}
return collections.NewSortIterator(src, sorters...)
}
func newSorter(srt *SorterExpression) (*collections.Sorter, error) {
return collections.NewSorter(func(ctx context.Context, first, second *core.Scope) (int, error) {
f, err := srt.expression.Exec(ctx, first)
if err != nil {
return -1, err
}
s, err := srt.expression.Exec(ctx, second)
if err != nil {
return -1, err
}
return f.Compare(s), nil
}, srt.direction)
}