forked from Masterminds/squirrel
-
Notifications
You must be signed in to change notification settings - Fork 38
/
case.go
107 lines (85 loc) · 2.36 KB
/
case.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
package sqrl
import (
"bytes"
"errors"
)
// sqlizerBuffer is a helper that allows to write many Sqlizers one by one
// without constant checks for errors that may come from Sqlizer
type sqlizerBuffer struct {
bytes.Buffer
args []interface{}
err error
}
// WriteSql converts Sqlizer to SQL strings and writes it to buffer
func (b *sqlizerBuffer) WriteSql(item Sqlizer) {
if b.err != nil {
return
}
var str string
var args []interface{}
str, args, b.err = item.ToSql()
if b.err != nil {
return
}
b.WriteString(str)
b.WriteByte(' ')
b.args = append(b.args, args...)
}
func (b *sqlizerBuffer) ToSql() (string, []interface{}, error) {
return b.String(), b.args, b.err
}
// whenPart is a helper structure to describe SQLs "WHEN ... THEN ..." expression
type whenPart struct {
when Sqlizer
then Sqlizer
}
func newWhenPart(when interface{}, then interface{}) whenPart {
return whenPart{newPart(when), newPart(then)}
}
// CaseBuilder builds SQL CASE construct which could be used as parts of queries.
type CaseBuilder struct {
whatPart Sqlizer
whenParts []whenPart
elsePart Sqlizer
}
// ToSql implements Sqlizer
func (b *CaseBuilder) ToSql() (sqlStr string, args []interface{}, err error) {
if len(b.whenParts) == 0 {
err = errors.New("case expression must contain at lease one WHEN clause")
return
}
sql := sqlizerBuffer{}
sql.WriteString("CASE ")
if b.whatPart != nil {
sql.WriteSql(b.whatPart)
}
for _, p := range b.whenParts {
sql.WriteString("WHEN ")
sql.WriteSql(p.when)
sql.WriteString("THEN ")
sql.WriteSql(p.then)
}
if b.elsePart != nil {
sql.WriteString("ELSE ")
sql.WriteSql(b.elsePart)
}
sql.WriteString("END")
return sql.ToSql()
}
// what sets optional value for CASE construct "CASE [value] ..."
func (b *CaseBuilder) what(expr interface{}) *CaseBuilder {
b.whatPart = newPart(expr)
return b
}
// When adds "WHEN ... THEN ..." part to CASE construct
func (b *CaseBuilder) When(when interface{}, then interface{}) *CaseBuilder {
// TODO: performance hint: replace slice of WhenPart with just slice of parts
// where even indices of the slice belong to "when"s and odd indices belong to "then"s
b.whenParts = append(b.whenParts, newWhenPart(when, then))
return b
}
// Else sets optional "ELSE ..." part for CASE construct
func (b *CaseBuilder) Else(expr interface{}) *CaseBuilder {
b.elsePart = newPart(expr)
return b
}