github.com/MontFerret/ferret@v0.18.0/pkg/runtime/expressions/clauses/limit.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  	"github.com/MontFerret/ferret/pkg/runtime/values/types"
     9  )
    10  
    11  type LimitClause struct {
    12  	src        core.SourceMap
    13  	dataSource collections.Iterable
    14  	count      core.Expression
    15  	offset     core.Expression
    16  }
    17  
    18  func NewLimitClause(
    19  	src core.SourceMap,
    20  	dataSource collections.Iterable,
    21  	count core.Expression,
    22  	offset core.Expression,
    23  ) (collections.Iterable, error) {
    24  	if dataSource == nil {
    25  		return nil, core.Error(core.ErrMissedArgument, "dataSource source")
    26  	}
    27  
    28  	return &LimitClause{src, dataSource, count, offset}, nil
    29  }
    30  
    31  func (clause *LimitClause) Iterate(ctx context.Context, scope *core.Scope) (collections.Iterator, error) {
    32  	src, err := clause.dataSource.Iterate(ctx, scope)
    33  
    34  	if err != nil {
    35  		return nil, core.SourceError(clause.src, err)
    36  	}
    37  
    38  	count, err := clause.count.Exec(ctx, scope)
    39  
    40  	if err != nil {
    41  		return nil, core.SourceError(clause.src, err)
    42  	}
    43  
    44  	offset, err := clause.offset.Exec(ctx, scope)
    45  
    46  	if err != nil {
    47  		return nil, core.SourceError(clause.src, err)
    48  	}
    49  
    50  	countInt, err := clause.parseValue(count)
    51  
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	offsetInt, err := clause.parseValue(offset)
    57  
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	iterator, err := collections.NewLimitIterator(src, countInt, offsetInt)
    63  
    64  	if err != nil {
    65  		return nil, core.SourceError(clause.src, err)
    66  	}
    67  
    68  	return iterator, nil
    69  }
    70  
    71  func (clause *LimitClause) parseValue(val core.Value) (int, error) {
    72  	if val.Type() == types.Int {
    73  		return val.Unwrap().(int), nil
    74  	}
    75  
    76  	if val.Type() == types.Float {
    77  		return int(val.Unwrap().(float64)), nil
    78  	}
    79  
    80  	return -1, core.TypeError(val.Type(), types.Int, types.Float)
    81  }