github.com/MontFerret/ferret@v0.18.0/pkg/runtime/expressions/clauses/collect.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  	Collect struct {
    12  		group     *CollectGroup
    13  		count     *CollectCount
    14  		aggregate *CollectAggregate
    15  	}
    16  
    17  	CollectGroup struct {
    18  		selectors  []*CollectSelector
    19  		projection *CollectProjection
    20  		count      *CollectCount
    21  		aggregate  *CollectAggregate
    22  	}
    23  
    24  	CollectCount struct {
    25  		variable string
    26  	}
    27  
    28  	CollectProjection struct {
    29  		selector *CollectSelector
    30  	}
    31  
    32  	CollectAggregate struct {
    33  		selectors []*CollectAggregateSelector
    34  	}
    35  
    36  	CollectClause struct {
    37  		src        core.SourceMap
    38  		dataSource collections.Iterable
    39  		params     *Collect
    40  	}
    41  )
    42  
    43  func NewCollect(
    44  	selectors []*CollectSelector,
    45  	projection *CollectProjection,
    46  	count *CollectCount,
    47  	aggregate *CollectAggregate,
    48  ) (*Collect, error) {
    49  	collect := new(Collect)
    50  
    51  	// grouping
    52  	if selectors != nil {
    53  		collect.group = new(CollectGroup)
    54  		collect.group.selectors = selectors
    55  
    56  		if projection == nil && count == nil && aggregate == nil {
    57  			return collect, nil
    58  		}
    59  
    60  		switch {
    61  		case projection != nil && count == nil && aggregate == nil:
    62  			collect.group.projection = projection
    63  		case projection == nil && count != nil && aggregate == nil:
    64  			collect.group.count = count
    65  		case projection == nil && count == nil && aggregate != nil:
    66  			collect.group.aggregate = aggregate
    67  		default:
    68  			return nil, core.Error(core.ErrInvalidOperation, "projection, count and aggregate cannot be used together")
    69  		}
    70  
    71  		return collect, nil
    72  	}
    73  
    74  	switch {
    75  	case count == nil && aggregate != nil:
    76  		collect.aggregate = aggregate
    77  	case count != nil && aggregate == nil:
    78  		collect.count = count
    79  	default:
    80  		return nil, core.Error(core.ErrInvalidOperation, "count and aggregate cannot be used together")
    81  	}
    82  
    83  	return collect, nil
    84  }
    85  
    86  func NewCollectCount(variable string) (*CollectCount, error) {
    87  	if variable == "" {
    88  		return nil, core.Error(core.ErrMissedArgument, "count variable")
    89  	}
    90  
    91  	return &CollectCount{variable}, nil
    92  }
    93  
    94  func NewCollectProjection(selector *CollectSelector) (*CollectProjection, error) {
    95  	if selector == nil {
    96  		return nil, core.Error(core.ErrMissedArgument, "projection selector")
    97  	}
    98  
    99  	return &CollectProjection{selector}, nil
   100  }
   101  
   102  func NewCollectAggregate(selectors []*CollectAggregateSelector) (*CollectAggregate, error) {
   103  	if selectors == nil {
   104  		return nil, core.Error(core.ErrMissedArgument, "aggregate selectors")
   105  	}
   106  
   107  	return &CollectAggregate{selectors}, nil
   108  }
   109  
   110  func NewCollectClause(
   111  	src core.SourceMap,
   112  	dataSource collections.Iterable,
   113  	params *Collect,
   114  ) (collections.Iterable, error) {
   115  	if dataSource == nil {
   116  		return nil, core.Error(core.ErrMissedArgument, "dataSource source")
   117  	}
   118  
   119  	return &CollectClause{src, dataSource, params}, nil
   120  }
   121  
   122  func (clause *CollectClause) Iterate(ctx context.Context, scope *core.Scope) (collections.Iterator, error) {
   123  	srcIterator, err := clause.dataSource.Iterate(ctx, scope)
   124  
   125  	if err != nil {
   126  		return nil, core.SourceError(clause.src, err)
   127  	}
   128  
   129  	return NewCollectIterator(
   130  		clause.src,
   131  		clause.params,
   132  		srcIterator,
   133  	)
   134  }