github.com/MontFerret/ferret@v0.18.0/pkg/runtime/expressions/clauses/sort.go (about)

     1  package clauses
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/MontFerret/ferret/pkg/runtime/collections"
     7  	"github.com/MontFerret/ferret/pkg/runtime/core"
     8  )
     9  
    10  type (
    11  	SorterExpression struct {
    12  		expression core.Expression
    13  		direction  collections.SortDirection
    14  	}
    15  
    16  	SortClause struct {
    17  		src        core.SourceMap
    18  		dataSource collections.Iterable
    19  		sorters    []*SorterExpression
    20  	}
    21  )
    22  
    23  func NewSorterExpression(expression core.Expression, direction collections.SortDirection) (*SorterExpression, error) {
    24  	if expression == nil {
    25  		return nil, core.Error(core.ErrMissedArgument, "reducer")
    26  	}
    27  
    28  	if !collections.IsValidSortDirection(direction) {
    29  		return nil, core.Error(core.ErrInvalidArgument, "direction")
    30  	}
    31  
    32  	return &SorterExpression{expression, direction}, nil
    33  }
    34  
    35  func NewSortClause(
    36  	src core.SourceMap,
    37  	dataSource collections.Iterable,
    38  	sorters ...*SorterExpression,
    39  ) (collections.Iterable, error) {
    40  	if dataSource == nil {
    41  		return nil, core.Error(core.ErrMissedArgument, "dataSource source")
    42  	}
    43  
    44  	if len(sorters) == 0 {
    45  		return nil, core.Error(core.ErrMissedArgument, "sorters")
    46  	}
    47  
    48  	return &SortClause{src, dataSource, sorters}, nil
    49  }
    50  
    51  func (clause *SortClause) Iterate(ctx context.Context, scope *core.Scope) (collections.Iterator, error) {
    52  	src, err := clause.dataSource.Iterate(ctx, scope)
    53  
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	sorters := make([]*collections.Sorter, len(clause.sorters))
    59  
    60  	// converting sorter reducer into collections.Sorter
    61  	for idx, srt := range clause.sorters {
    62  		sorter, err := newSorter(srt)
    63  
    64  		if err != nil {
    65  			return nil, err
    66  		}
    67  
    68  		sorters[idx] = sorter
    69  	}
    70  
    71  	return collections.NewSortIterator(src, sorters...)
    72  }
    73  
    74  func newSorter(srt *SorterExpression) (*collections.Sorter, error) {
    75  	return collections.NewSorter(func(ctx context.Context, first, second *core.Scope) (int64, error) {
    76  		f, err := srt.expression.Exec(ctx, first)
    77  
    78  		if err != nil {
    79  			return -1, err
    80  		}
    81  
    82  		s, err := srt.expression.Exec(ctx, second)
    83  
    84  		if err != nil {
    85  			return -1, err
    86  		}
    87  
    88  		return f.Compare(s), nil
    89  	}, srt.direction)
    90  }