Passed
Push — master ( d5acb0...3b1c57 )
by DEATH
01:22
created

builder.go (20 issues)

Severity
1
package sqlbuilder
2
3
import (
4
    "reflect"
5
    "strconv"
6
)
7
8
type Builder struct {
0 ignored issues
show
exported type Builder should have comment or be unexported
Loading history...
9
    //The query value bindings
10
    bindings
11
    
12
    //The Columns that should be return
13
    columns []string
14
    
15
    //The table which the query is targeting
16
    table string
17
    
18
    //Update columns
19
    update []interface{}
20
    
21
    //Insert columns
22
    insert []string
23
    
24
    //Indicates is delete sql.
25
    delete bool
26
    
27
    //Indicates if the query return district results.
28
    district bool
29
    
30
    //The where constraints for the query.
31
    wheres []*where
32
    
33
    //The groupings for the query.
34
    groups []string
35
    
36
    //The havings constraints for the query.
37
    havings []*where
38
    
39
    //The table joins for the query.
40
    joins []*join
41
    
42
    //The orderings for the query.
43
    orders []*order
44
    
45
    //The maximum number of records to return.
46
    limit string
47
    
48
    //The number of records to skip.
49
    offset string
50
}
51
52
type bindings struct {
53
    selected []string
54
    insert   []string
55
    update   []string
56
    from     []string
57
    join     []string
58
    where    []string
59
    having   []string
60
    order    []string
61
}
62
63
//Expression for raw sql
64
type Expression struct {
65
    Value string
66
}
67
68
type where struct {
69
    column   string
70
    operator string
71
    value    string
72
    boolean  string
73
}
74
75
type join struct {
76
    table     string
77
    condition string
78
    joinType  string // inner left right
79
}
80
81
type order struct {
82
    column    string
83
    direction string
84
}
85
86
//All of the available clause operators.
87
var operators = []string{"=", "<", ">", "<=", ">=", "<>", "!=", "<=>", "like", "like binary", "not like", "ilike",
88
    "&", "|", "^", "<<", ">>", "rlike", "regexp", "not regexp", "~", "~*", "!~", "!~*", "similar to", "not similar to",
89
    "not ilike", "~~*", "!~~*",
90
}
91
92
//Is val in array
93
func in_array(val interface{}, array interface{}) (exists bool, index int) {
0 ignored issues
show
don't use underscores in Go names; func in_array should be inArray
Loading history...
94
    exists = false
95
    index = -1
96
    
97
    switch reflect.TypeOf(array).Kind() {
98
    case reflect.Slice:
99
        s := reflect.ValueOf(array)
100
        
101
        for i := 0; i < s.Len(); i++ {
102
            if reflect.DeepEqual(val, s.Index(i).Interface()) == true {
103
                index = i
104
                exists = true
105
                return
106
            }
107
        }
108
    }
109
    
110
    return
111
}
112
113
func (b *Builder) invalidOperator(operator string) (bool) {
114
    exists, _ := in_array(operator, operators)
115
    return exists
116
}
117
118
func (b *Builder) Select(columns []string) (*Builder) {
0 ignored issues
show
exported method Builder.Select should have comment or be unexported
Loading history...
119
    b.columns = columns
120
    return b
121
}
122
123
func (b *Builder) From(table string) (*Builder) {
0 ignored issues
show
exported method Builder.From should have comment or be unexported
Loading history...
124
    b.table = table
125
    return b
126
}
127
128
/*
0 ignored issues
show
comment on exported method Builder.Where should be of the form "Where ..."
Loading history...
129
Where("column", "1")
130
Where("column", "=","1")
131
Where("column", "=", "1", "or")
132
Where(map[string]string{column1:"1", column2: "2"})
133
 */
134
func (b *Builder) Where(column interface{}, operator string, args ...string) (*Builder) {
135
    switch column.(type) {
136
    case string:
137
        value := ""
138
        booll := "and"
139
        lenArgs := len(args)
140
        if lenArgs == 0 {
141
            value = operator
142
        } else if lenArgs >= 1 {
143
            value = args[0]
144
        } else if lenArgs >= 2 {
145
            booll = args[1]
146
        }
147
        
148
        if !b.invalidOperator(operator) {
149
            operator = "="
150
        }
151
        
152
        condition := &where{column.(string), operator, value, booll}
153
        b.wheres = append(b.wheres, condition)
154
        b.bindings.where = append(b.bindings.where, value)
155
    case map[string]string:
156
        return b.addArrayOfWheres(column.(map[string]string), "and")
157
    }
158
    
159
    return b
160
}
161
162
func (b *Builder) addArrayOfWheres(wheres map[string]string, boolean string) (*Builder) {
163
    for k, v := range wheres {
164
        condition := &where{k, "=", v, boolean}
165
        b.wheres = append(b.wheres, condition)
166
        b.bindings.where = append(b.bindings.where, v)
167
    }
168
    return b
169
}
170
171
/*
0 ignored issues
show
comment on exported method Builder.Join should be of the form "Join ..."
Loading history...
172
Join("tableB", "tableB.id = tableA.bId")
173
 */
174
func (b *Builder) Join(table string, condition string, args ...string) (*Builder) {
175
    joinType := "inner"
176
    lenArgs := len(args)
177
    if lenArgs > 0 {
178
        joinType = args[0]
179
    }
180
    j := &join{table, condition, joinType}
181
    b.joins = append(b.joins, j)
182
    return b
183
}
184
185
func (b *Builder) LeftJoin(table string, condition string) (*Builder) {
0 ignored issues
show
exported method Builder.LeftJoin should have comment or be unexported
Loading history...
186
    
187
    return b.Join(table, condition, "left")
188
}
189
190
func (b *Builder) RightJoin(table string, condition string) (*Builder) {
0 ignored issues
show
exported method Builder.RightJoin should have comment or be unexported
Loading history...
191
    return b.Join(table, condition, "right")
192
}
193
194
func (b *Builder) GroupBy(group interface{}) (*Builder) {
0 ignored issues
show
exported method Builder.GroupBy should have comment or be unexported
Loading history...
195
    switch group.(type) {
196
    case []string:
197
        b.groups = append(b.groups, group.([]string)...)
198
    case string:
199
        b.groups = append(b.groups, group.(string))
200
    }
201
    return b
202
}
203
204
/*
0 ignored issues
show
comment on exported method Builder.Having should be of the form "Having ..."
Loading history...
205
Having("column", "1")
206
Having("column", "=","1")
207
Having("column", "=", "1", "or")
208
Having(map[string]string{column1:"1", column2: "2"})
209
 */
210
func (b *Builder) Having(column interface{}, operator string, args ...string) (*Builder) {
211
    switch column.(type) {
212
    case string:
213
        value := ""
214
        booll := "and"
215
        lenArgs := len(args)
216
        if lenArgs == 0 {
217
            value = operator
218
        } else if lenArgs >= 1 {
219
            value = args[0]
220
        } else if lenArgs >= 2 {
221
            booll = args[1]
222
        }
223
        
224
        if !b.invalidOperator(operator) {
225
            operator = "="
226
        }
227
        
228
        condition := &where{column.(string), operator, value, booll}
229
        b.havings = append(b.havings, condition)
230
        b.bindings.having = append(b.bindings.having, value)
231
    case map[string]string:
232
        return b.addArrayOfHavings(column.(map[string]string), "and")
233
    }
234
    
235
    return b
236
}
237
238
func (b *Builder) addArrayOfHavings(wheres map[string]string, boolean string) (*Builder) {
239
    for k, v := range wheres {
240
        condition := &where{k, "=", v, boolean}
241
        b.havings = append(b.wheres, condition)
242
        b.bindings.having = append(b.bindings.having, v)
243
    }
244
    return b
245
}
246
247
func (b *Builder) OrderBy(column string, direction string) (*Builder) {
0 ignored issues
show
exported method Builder.OrderBy should have comment or be unexported
Loading history...
248
    b.orders = append(b.orders, &order{column, direction})
249
    return b
250
}
251
252
func (b *Builder) OrderByAsc(column string) (*Builder) {
0 ignored issues
show
exported method Builder.OrderByAsc should have comment or be unexported
Loading history...
253
    return b.OrderBy(column, "asc")
254
}
255
256
func (b *Builder) OrderByDesc(column string) (*Builder) {
0 ignored issues
show
exported method Builder.OrderByDesc should have comment or be unexported
Loading history...
257
    return b.OrderBy(column, "desc")
258
}
259
260
func (b *Builder) Offset(offset interface{}) (*Builder) {
0 ignored issues
show
exported method Builder.Offset should have comment or be unexported
Loading history...
261
    switch offset.(type) {
262
    case string:
263
        b.offset = offset.(string)
264
    case int:
265
        b.offset = strconv.Itoa(offset.(int))
266
    }
267
    return b
268
}
269
270
func (b *Builder) Limit(limit interface{}) (*Builder) {
0 ignored issues
show
exported method Builder.Limit should have comment or be unexported
Loading history...
271
    switch limit.(type) {
272
    case string:
273
        b.limit = limit.(string)
274
    case int:
275
        b.limit = strconv.Itoa(limit.(int))
276
    }
277
    return b
278
}
279
280
func (b *Builder) Insert(table string, info map[string]string) (*Builder) {
0 ignored issues
show
exported method Builder.Insert should have comment or be unexported
Loading history...
281
    b.table = table
282
    
283
    for column, value := range info {
284
        b.insert = append(b.insert, column)
285
        b.bindings.insert = append(b.bindings.insert, value)
286
    }
287
    return b
288
}
289
290
func (b *Builder) Update(table string, info map[string]interface{}) (*Builder) {
0 ignored issues
show
exported method Builder.Update should have comment or be unexported
Loading history...
291
    b.table = table
292
    for column, value := range info {
293
        
294
        switch value.(type) {
295
        case string:
296
            b.update = append(b.update, column)
297
            b.bindings.update = append(b.bindings.update, value.(string))
298
        case *Expression:
299
            //表达式: 如 a = a + 1
300
            b.update = append(b.update, value)
301
        }
302
    }
303
    return b
304
}
305
306
func (b *Builder) Delete(table string) (*Builder) {
0 ignored issues
show
exported method Builder.Delete should have comment or be unexported
Loading history...
307
    b.table = table
308
    b.delete = true
309
    return b
310
}
311
312
func (b *Builder) ToSql() (sql string, bindings []string) {
0 ignored issues
show
exported method Builder.ToSql should have comment or be unexported
Loading history...
method ToSql should be ToSQL
Loading history...
313
    if b.delete {
314
        return CompileDelete(b)
315
    } else if len(b.insert) > 0 {
316
        return CompileInsert(b)
317
    } else if len(b.update) > 0 {
318
        return CompileUpdate(b)
319
    } else {
320
        return CompileSelect(b)
321
    }
322
}
323