This repository was archived by the owner on Nov 8, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilters.go
102 lines (87 loc) · 2.08 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
package chem
import (
"fmt"
"strings"
)
type Filter interface {
binds() []interface{}
toBooleanExpression(withTableNames bool) string
}
const (
equalsOperator = "="
notEqualsOperator = "!="
lessThanOperator = "<"
lessThanOrEqualOperator = "<="
greaterThanOperator = ">"
greaterThanOrEqualOperator = ">="
likeOperator = "LIKE"
)
type ValueFilter struct {
column Column
operator string
value interface{}
}
func (f ValueFilter) toBooleanExpression(withTableNames bool) string {
return fmt.Sprintf("%v %v ?", f.column.toColumnExpression(withTableNames), f.operator)
}
func (f ValueFilter) binds() []interface{} {
return []interface{}{f.value}
}
type ColumnFilter struct {
left Column
operator string
right Column
}
func (f ColumnFilter) toBooleanExpression(withTableNames bool) string {
return fmt.Sprintf(
"%v %v %v",
f.left.toColumnExpression(withTableNames),
f.operator,
f.right.toColumnExpression(withTableNames),
)
}
func (f ColumnFilter) binds() []interface{} {
return []interface{}{}
}
type BooleanOperatorFilter struct {
operator string
filters []Filter
}
func (f BooleanOperatorFilter) toBooleanExpression(withTableNames bool) string {
expressionList := make([]string, len(f.filters))
for i, filter := range f.filters {
expressionList[i] = filter.toBooleanExpression(withTableNames)
}
expression := strings.Join(
expressionList,
fmt.Sprintf(" %v ", f.operator),
)
if expression == "" {
return expression
}
// wrap the expression to make sure precedence is what user expects
return fmt.Sprintf("( %v )", expression)
}
func (f BooleanOperatorFilter) binds() []interface{} {
out := make([]interface{}, 0, len(f.filters))
for _, filter := range f.filters {
out = append(out, filter.binds()...)
}
return out
}
const (
andOperator = "AND"
orOperator = "OR"
)
func AND(filters ...Filter) Filter {
return BooleanOperatorFilter{
operator: andOperator,
filters: filters,
}
}
func OR(filters ...Filter) Filter {
return BooleanOperatorFilter{
operator: orOperator,
filters: filters,
}
}