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

     1  package expressions
     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/expressions/clauses"
     9  	"github.com/MontFerret/ferret/pkg/runtime/values"
    10  )
    11  
    12  type ForExpression struct {
    13  	src         core.SourceMap
    14  	dataSource  collections.Iterable
    15  	predicate   core.Expression
    16  	distinct    bool
    17  	spread      bool
    18  	passThrough bool
    19  }
    20  
    21  func NewForExpression(
    22  	src core.SourceMap,
    23  	dataSource collections.Iterable,
    24  	predicate core.Expression,
    25  	distinct,
    26  	spread,
    27  	passThrough bool,
    28  ) (*ForExpression, error) {
    29  	if dataSource == nil {
    30  		return nil, core.Error(core.ErrMissedArgument, "missed source expression")
    31  	}
    32  
    33  	if predicate == nil {
    34  		return nil, core.Error(core.ErrMissedArgument, "missed return expression")
    35  	}
    36  
    37  	exp := new(ForExpression)
    38  	exp.src = src
    39  	exp.dataSource = dataSource
    40  	exp.predicate = predicate
    41  	exp.distinct = distinct
    42  	exp.spread = spread
    43  	exp.passThrough = passThrough
    44  
    45  	return exp, nil
    46  }
    47  
    48  func (e *ForExpression) AddLimit(src core.SourceMap, size, count core.Expression) error {
    49  	limit, err := clauses.NewLimitClause(src, e.dataSource, size, count)
    50  
    51  	if err != nil {
    52  		return err
    53  	}
    54  
    55  	e.dataSource = limit
    56  
    57  	return nil
    58  }
    59  
    60  func (e *ForExpression) AddFilter(src core.SourceMap, exp core.Expression) error {
    61  	filter, err := clauses.NewFilterClause(src, e.dataSource, exp)
    62  
    63  	if err != nil {
    64  		return err
    65  	}
    66  
    67  	e.dataSource = filter
    68  
    69  	return nil
    70  }
    71  
    72  func (e *ForExpression) AddSort(src core.SourceMap, sorters ...*clauses.SorterExpression) error {
    73  	sort, err := clauses.NewSortClause(src, e.dataSource, sorters...)
    74  
    75  	if err != nil {
    76  		return err
    77  	}
    78  
    79  	e.dataSource = sort
    80  
    81  	return nil
    82  }
    83  
    84  func (e *ForExpression) AddCollect(src core.SourceMap, params *clauses.Collect) error {
    85  	collect, err := clauses.NewCollectClause(src, e.dataSource, params)
    86  
    87  	if err != nil {
    88  		return err
    89  	}
    90  
    91  	e.dataSource = collect
    92  
    93  	return nil
    94  }
    95  
    96  func (e *ForExpression) AddStatement(stmt core.Expression) error {
    97  	tap, ok := e.dataSource.(*BlockExpression)
    98  
    99  	if !ok {
   100  		t, err := NewBlockExpression(e.dataSource)
   101  
   102  		if err != nil {
   103  			return err
   104  		}
   105  
   106  		tap = t
   107  		e.dataSource = tap
   108  	}
   109  
   110  	tap.Add(stmt)
   111  
   112  	return nil
   113  }
   114  
   115  func (e *ForExpression) Exec(ctx context.Context, scope *core.Scope) (core.Value, error) {
   116  	select {
   117  	case <-ctx.Done():
   118  		return values.None, core.ErrTerminated
   119  	default:
   120  		iterator, err := e.dataSource.Iterate(ctx, scope)
   121  
   122  		if err != nil {
   123  			return values.None, err
   124  		}
   125  
   126  		res := NewForResult(10).
   127  			Distinct(e.distinct).
   128  			Spread(e.spread).
   129  			PassThrough(e.passThrough)
   130  
   131  		for {
   132  			nextScope, err := iterator.Next(ctx, scope)
   133  
   134  			if err != nil {
   135  				if core.IsNoMoreData(err) {
   136  					break
   137  				}
   138  
   139  				return values.None, core.SourceError(e.src, err)
   140  			}
   141  
   142  			out, err := e.predicate.Exec(ctx, nextScope)
   143  
   144  			if err != nil {
   145  				return values.None, err
   146  			}
   147  
   148  			res.Push(out)
   149  		}
   150  
   151  		return res.ToArray(), nil
   152  	}
   153  }