-
Notifications
You must be signed in to change notification settings - Fork 1
/
filter.go
140 lines (126 loc) · 3.59 KB
/
filter.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
132
133
134
135
136
137
138
139
140
package query
import (
"fmt"
"github.com/xichen2020/eventdb/document/field"
"github.com/xichen2020/eventdb/filter"
"github.com/xichen2020/eventdb/generated/proto/servicepb"
)
// RawFilterLists is a list of raw filter list.
type RawFilterLists []RawFilterList
// ToProto converts a list of raw filter lists to a list of filter lists protobuf messages.
func (rl RawFilterLists) ToProto() ([]servicepb.FilterList, error) {
if len(rl) == 0 {
return nil, nil
}
res := make([]servicepb.FilterList, 0, len(rl))
for _, l := range rl {
pbFilterList, err := l.ToProto()
if err != nil {
return nil, err
}
res = append(res, pbFilterList)
}
return res, nil
}
// RawFilterList is a list of raw filters.
type RawFilterList struct {
Filters RawFilters `json:"filters"`
FilterCombinator *filter.Combinator `json:"filter_combinator"`
}
// ToProto converts the raw filter list to a filter list protobuf message.
func (l *RawFilterList) ToProto() (servicepb.FilterList, error) {
filters, err := l.Filters.ToProto()
if err != nil {
return servicepb.FilterList{}, err
}
filterCombinator, err := l.FilterCombinator.ToProto()
if err != nil {
return servicepb.FilterList{}, err
}
return servicepb.FilterList{
Filters: filters,
FilterCombinator: filterCombinator,
}, nil
}
// RawFilters is a list of raw filters
type RawFilters []RawFilter
// ToProto converts a list of raw filters to a list of raw filter protobuf messages.
func (rf RawFilters) ToProto() ([]servicepb.Filter, error) {
if len(rf) == 0 {
return nil, nil
}
res := make([]servicepb.Filter, 0, len(rf))
for _, f := range rf {
pbFilter, err := f.ToProto()
if err != nil {
return nil, err
}
res = append(res, pbFilter)
}
return res, nil
}
// RawFilter represents a raw query filter.
type RawFilter struct {
Field string `json:"field"`
Op filter.Op `json:"op"`
Value interface{} `json:"value"`
}
// ToProto converts the raw filter to a filter protobuf message.
func (l *RawFilter) ToProto() (servicepb.Filter, error) {
pbOp, err := l.Op.ToProto()
if err != nil {
return servicepb.Filter{}, err
}
pbFilterValue, err := toOptionalFilterValue(l.Value)
if err != nil {
return servicepb.Filter{}, err
}
return servicepb.Filter{
Field: l.Field,
Op: pbOp,
Value: pbFilterValue,
}, nil
}
// FilterList is a list of parsed filters.
type FilterList struct {
Filters []Filter
FilterCombinator filter.Combinator
}
// Filter is a parsed filter.
// TODO(xichen): Handle range query.
type Filter struct {
FieldPath []string
Op filter.Op
Value *field.ValueUnion
}
// AllowedFieldTypes returns a list of allowed field types given the filter
// operator and the RHS value if applicable.
func (f Filter) AllowedFieldTypes() (field.ValueTypeSet, error) {
return f.Op.AllowedTypes(f.Value)
}
func toOptionalFilterValue(value interface{}) (servicepb.OptionalFilterValue, error) {
if value == nil {
noValue := &servicepb.OptionalFilterValue_NoValue{NoValue: true}
return servicepb.OptionalFilterValue{Value: noValue}, nil
}
v := &servicepb.FilterValue{}
switch value := value.(type) {
case bool:
v.Type = servicepb.FilterValue_BOOL
v.BoolVal = value
case int:
v.Type = servicepb.FilterValue_NUMBER
v.NumberVal = float64(value)
case float64:
v.Type = servicepb.FilterValue_NUMBER
v.NumberVal = value
case string:
v.Type = servicepb.FilterValue_STRING
v.StringVal = value
default:
return servicepb.OptionalFilterValue{}, fmt.Errorf("invalid filter value %v", value)
}
return servicepb.OptionalFilterValue{
Value: &servicepb.OptionalFilterValue_Data{Data: v},
}, nil
}