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