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 }