-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsql_wrappers.go
141 lines (124 loc) · 3.4 KB
/
sql_wrappers.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
package gorq
import (
"bytes"
"fmt"
"github.com/nelsam/gorq/filters"
)
type functionWrapper struct {
actualValue interface{}
functionName string
}
func (wrapper functionWrapper) ActualValue() interface{} {
return wrapper.actualValue
}
func (wrapper functionWrapper) WrapSql(sqlValue string) string {
return fmt.Sprintf("%s(%s)", wrapper.functionName, sqlValue)
}
// Lower returns a filters.SqlWrapper that wraps the passed in value
// in an sql lower() call. Example:
//
// results, err := dbMap.Query(ref).
// Where().
// Equal(Lower(&ref.Name), Lower(name)).
// Select()
//
// The above would result in a case-insensitive comparison in the
// where clause of the query.
func Lower(value interface{}) filters.SqlWrapper {
return functionWrapper{
actualValue: value,
functionName: "lower",
}
}
// Count returns a filters.SqlWrapper that wraps the passed in value
// in an sql count() call.
func Count(value interface{}) filters.SqlWrapper {
return functionWrapper{
actualValue: value,
functionName: "COUNT",
}
}
// whenValue represents a single "WHEN ... THEN ..." pair in a CASE
// WHEN clause.
type whenValue struct {
when filters.Filter
then interface{}
}
// A Case is a filters.MultiSqlWrapper for CASE WHEN ... THEN
// ... ELSE ... END logic.
type Case interface {
filters.MultiSqlWrapper
When(filters.Filter) Thener
Else(interface{}) filters.MultiSqlWrapper
}
// Thener is a Case that is in a state where a WHEN expression has
// been supplied, so it needs a corresponding THEN expression.
type Thener interface {
Then(interface{}) Case
}
// A CaseWhen is a type to hold details about a CASE WHEN expression.
type CaseWhen struct {
whenValues []whenValue
elseValue interface{}
}
// ActualValues implements filters.MultiSqlWrapper.ActualValues.
func (c *CaseWhen) ActualValues() []interface{} {
values := make([]interface{}, 0, len(c.whenValues)+1)
for _, whenVal := range c.whenValues {
values = append(values, whenVal.when.ActualValues()...)
values = append(values, whenVal.then)
}
if c.elseValue != nil {
values = append(values, c.elseValue)
}
return values
}
// WrapSql implements filters.MultiSqlWrapper.WrapSql.
func (c *CaseWhen) WrapSql(values ...string) string {
buf := bytes.NewBufferString("CASE")
var idx int
for _, whenVal := range c.whenValues {
buf.WriteString(" WHEN ")
end := idx + len(whenVal.when.ActualValues())
buf.WriteString(whenVal.when.Where(values[idx:end]...))
idx = end
buf.WriteString(" THEN ")
buf.WriteString(values[idx])
idx++
}
if c.elseValue != nil {
buf.WriteString(" ELSE ")
buf.WriteString(values[idx])
}
buf.WriteString(" END")
return buf.String()
}
// When implements Case.When.
func (c *CaseWhen) When(filter filters.Filter) Thener {
c.whenValues = append(c.whenValues, whenValue{
when: filter,
})
return c
}
// Then implements Thener.Then.
func (c *CaseWhen) Then(value interface{}) Case {
c.whenValues[len(c.whenValues)-1].then = value
return c
}
// Else implements Case.Then.
func (c *CaseWhen) Else(value interface{}) filters.MultiSqlWrapper {
c.elseValue = value
return c
}
// When constructs a Case starting with a WHEN expression of the
// passed in filter, and returns the corresponding Thener.
//
// Example usage:
//
// gorq.When(filters.Null(&foo.Bar)).Then(0).Else(&foo.Bar)
//
func When(comparison filters.Filter) Thener {
return &CaseWhen{
whenValues: []whenValue{{when: comparison}},
}
}