Repository navigation
Expand file tree
/
Copy pathcase.go
More file actions
116 lines (94 loc) · 2.53 KB
/
Copy pathcase.go
File metadata and controls
116 lines (94 loc) · 2.53 KB
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
package pgq
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 []any
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 []any
str, args, b.err = nestedSQL(item)
if b.err != nil {
return
}
b.WriteString(str)
b.WriteByte(' ')
b.args = append(b.args, args...)
}
func (b *sqlizerBuffer) SQL() (string, []any, 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 any, then any) whenPart {
return whenPart{newPart(when), newPart(then)}
}
// CaseBuilder builds SQL CASE construct which could be used as parts of queries.
type CaseBuilder struct {
whatParts SQLizer
whenParts []whenPart
elseParts SQLizer
}
// SQL builds the query into a SQL string and bound args.
func (b CaseBuilder) SQL() (sqlStr string, args []any, 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.whatParts != nil {
sql.WriteSQL(b.whatParts)
}
for _, p := range b.whenParts {
sql.WriteString("WHEN ")
sql.WriteSQL(p.when)
sql.WriteString("THEN ")
sql.WriteSQL(p.then)
}
if b.elseParts != nil {
sql.WriteString("ELSE ")
sql.WriteSQL(b.elseParts)
}
sql.WriteString("END")
return sql.SQL()
}
// MustSQL builds the query into a SQL string and bound args.
// It panics if there are any errors.
func (b CaseBuilder) MustSQL() (string, []any) {
sql, args, err := b.SQL()
if err != nil {
panic(err)
}
return sql, args
}
// what sets optional value for CASE construct "CASE [value] ..."
func (b CaseBuilder) what(expr any) CaseBuilder {
b.whatParts = newPart(expr)
return b
}
// When adds "WHEN ... THEN ..." part to CASE construct
func (b CaseBuilder) When(when any, then any) 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
}
// What sets optional "ELSE ..." part for CASE construct
func (b CaseBuilder) Else(expr any) CaseBuilder {
b.elseParts = newPart(expr)
return b
}