-
Notifications
You must be signed in to change notification settings - Fork 0
/
select.go
161 lines (138 loc) · 3.6 KB
/
select.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package influxql
import (
"bytes"
"fmt"
)
// SelectBuilder represents a SELECT statement.
type SelectBuilder struct {
measurement Builder
fields []Builder
where []Builder
groupBy []Builder
orderBy []Builder
limit int
offset int
slimit int
soffset int
fill interface{}
}
// SelectFrom creates a SELECT query.
func From(measurement string) *SelectBuilder {
s := &SelectBuilder{measurement: &literal{measurement}}
return s
}
// Select creates a SELECT query.
func Select(fields ...interface{}) *SelectBuilder {
s := &SelectBuilder{}
for i := range fields {
s.fields = append(s.fields, &literal{fields[i]})
}
return s
}
// Fill represents FILL(x).
func (s *SelectBuilder) Fill(v interface{}) *SelectBuilder {
if v == nil {
s.fill = nullValue{}
return s
}
s.fill = v
return s
}
// Select adds fields to select from.
func (s *SelectBuilder) Select(fields ...interface{}) *SelectBuilder {
for i := range fields {
s.fields = append(s.fields, &literal{fields[i]})
}
return s
}
// From represents the FROM in SELECT x FROM.
func (s *SelectBuilder) From(measurement string) *SelectBuilder {
s.measurement = &literal{measurement}
return s
}
// GroupBy represents GROUP BY field.
func (s *SelectBuilder) GroupBy(fields ...interface{}) *SelectBuilder {
for i := range fields {
s.groupBy = append(s.groupBy, &literal{fields[i]})
}
return s
}
// OrderBy represents ORDER BY field.
func (s *SelectBuilder) OrderBy(fields ...interface{}) *SelectBuilder {
for i := range fields {
s.orderBy = append(s.orderBy, &literal{fields[i]})
}
return s
}
// Where replaces the current conditions.
func (s *SelectBuilder) Where(expr string, values ...interface{}) *SelectBuilder {
s.where = make([]Builder, 0, 1)
s.where = append(s.where, &Expr{expr: expr, values: values})
return s
}
// And adds a conjunction to the list of conditions.
func (s *SelectBuilder) And(expr string, values ...interface{}) *SelectBuilder {
if len(s.where) > 0 {
s.where = append(s.where, andKeyword, &Expr{expr: expr, values: values})
} else {
s.where = append(s.where, &Expr{expr: expr, values: values})
}
return s
}
// Or adds a disjunction to the list of conditions.
func (s *SelectBuilder) Or(expr string, values ...interface{}) *SelectBuilder {
s.where = append(s.where, orKeyword, &Expr{expr: expr, values: values})
return s
}
// Offset represents OFFSET n.
func (s *SelectBuilder) Offset(offset int) *SelectBuilder {
s.offset = offset
return s
}
// Limit represents LIMIT n.
func (s *SelectBuilder) Limit(limit int) *SelectBuilder {
s.limit = limit
return s
}
// SOffset represents SOFFSET n.
func (s *SelectBuilder) SOffset(soffset int) *SelectBuilder {
s.soffset = soffset
return s
}
// SLimit represents SLIMIT n.
func (s *SelectBuilder) SLimit(slimit int) *SelectBuilder {
s.slimit = slimit
return s
}
// Build satisfies Builder.
func (s *SelectBuilder) Build() (string, error) {
data := selectTemplateValues{}
if err := compileInto(s.measurement, &data.Measurement); err != nil {
return "", err
}
if err := compileArrayInto(s.fields, &data.Fields); err != nil {
return "", err
}
if err := compileArrayInto(s.where, &data.Where); err != nil {
return "", err
}
if err := compileArrayInto(s.groupBy, &data.GroupBy); err != nil {
return "", err
}
if s.fill != nil {
switch v := s.fill.(type) {
case nullValue:
data.Fill = "null"
case string:
data.Fill = fmt.Sprintf("%v", v)
default:
data.Fill = fmt.Sprintf("%v", v)
}
}
buf := bytes.NewBuffer(nil)
err := selectTemplate.Execute(buf, data)
if err != nil {
return "", err
}
return buf.String(), nil
}