-
Notifications
You must be signed in to change notification settings - Fork 532
/
filters.go
142 lines (113 loc) · 3.56 KB
/
filters.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
141
142
package postgres
import (
"fmt"
"strconv"
"github.com/lib/pq"
)
const (
FieldEventAttrName = "attribute.name"
FieldEventAttrValue = "attribute.value"
FieldEventTXHash = "event.tx_hash"
FieldEventType = "event.type"
)
const (
filterPlaceholder = "?"
)
// Modifier defines a function that can be used to modify a field name or value.
type Modifier func(field string) string
// CastJSONToText modifier casts a JSON/JSONB field to text.
func CastJSONToText(f string) string {
return fmt.Sprintf("%s::text", f)
}
// CastJSONToNumeric modifier casts a JSON/JSONB field to numeric.
func CastJSONToNumeric(f string) string {
return fmt.Sprintf("%s::numeric", f)
}
// FilterOption defines an option for filters.
type FilterOption func(*Filter)
// WithModifiers assigns one or more field modifier functions to the filter.
// Field modifiers can be used to change the behavior of a filtered field.
func WithModifiers(m ...Modifier) FilterOption {
return func(f *Filter) {
f.modifiers = m
}
}
// NewFilter creates a new generic equality filter.
func NewFilter(field string, value any, options ...FilterOption) Filter {
f := Filter{
field: field,
value: value,
}
for _, o := range options {
o(&f)
}
return f
}
// Filter defines a generic equality filter.
type Filter struct {
field string
value any
modifiers []Modifier
}
func (f Filter) String() string {
return fmt.Sprintf("%s = %s", f.applyModifiers(f.field), filterPlaceholder)
}
func (f Filter) Field() string {
return f.field
}
func (f Filter) Value() any {
return f.value
}
func (f Filter) applyModifiers(field string) string {
// Apply all the field modifiers in order
for _, m := range f.modifiers {
field = m(field)
}
return field
}
// NewStringSliceFilter creates a new string slice equality filter.
func NewStringSliceFilter(field string, values []string) SliceFilter {
return SliceFilter{
Filter: NewFilter(field, pq.Array(values)),
}
}
// NewIntSliceFilter creates a new int64 slice equality filter.
func NewIntSliceFilter(field string, values []int64) SliceFilter {
return SliceFilter{
Filter: NewFilter(field, pq.Array(values)),
}
}
// SliceFilter defines a generic slice/array equality filter.
type SliceFilter struct {
Filter
}
func (f SliceFilter) String() string {
return fmt.Sprintf("%s = ANY(%s)", f.applyModifiers(f.field), filterPlaceholder)
}
func (f SliceFilter) Value() any {
return f.Filter.Value()
}
// FilterByEventType creates a new filter to match events by type.
func FilterByEventType(eventType string) Filter {
return NewFilter(FieldEventType, eventType)
}
// FilterByEventTXs creates a new filter to match events by TX hashes.
func FilterByEventTXs(hashes ...string) SliceFilter {
return NewStringSliceFilter(FieldEventTXHash, hashes)
}
// FilterByEventAttrName creates a new filter to match events by attribute name.
func FilterByEventAttrName(name string) Filter {
return NewFilter(FieldEventAttrName, name)
}
// FilterByEventAttrValue creates a new filter to match events by attribute value.
func FilterByEventAttrValue(v string) Filter {
// The string value must be quoted to match with the JSONB text
v = strconv.Quote(v)
// Use a field modifier to cast the event attribute value JSONB field to text
return NewFilter(FieldEventAttrValue, v, WithModifiers(CastJSONToText))
}
// FilterByEventAttrValueInt creates a new filter to match events by attribute value.
func FilterByEventAttrValueInt(v int64) Filter {
// Use a field modifier to cast the event attribute value JSONB field to numeric
return NewFilter(FieldEventAttrValue, v, WithModifiers(CastJSONToNumeric))
}