-
Notifications
You must be signed in to change notification settings - Fork 123
/
whereclause.go
131 lines (105 loc) · 3.29 KB
/
whereclause.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
// Copyright 2018 Huan Du. All rights reserved.
// Licensed under the MIT license that can be found in the LICENSE file.
package sqlbuilder
// WhereClause is a Builder for WHERE clause.
// All builders which support `WHERE` clause have an anonymous `WhereClause` field,
// in which the conditions are stored.
//
// WhereClause can be shared among multiple builders.
// However, it is not thread-safe.
type WhereClause struct {
flavor Flavor
clauses []clause
}
var _ Builder = new(WhereClause)
// NewWhereClause creates a new WhereClause.
func NewWhereClause() *WhereClause {
return &WhereClause{}
}
// CopyWhereClause creates a copy of the whereClause.
func CopyWhereClause(whereClause *WhereClause) *WhereClause {
clauses := make([]clause, len(whereClause.clauses))
copy(clauses, whereClause.clauses)
return &WhereClause{
flavor: whereClause.flavor,
clauses: clauses,
}
}
type clause struct {
args *Args
andExprs []string
}
func (c *clause) Build(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{}) {
buf := newStringBuilder()
buf.WriteStrings(c.andExprs, " AND ")
sql, args = c.args.CompileWithFlavor(buf.String(), flavor, initialArg...)
return
}
// whereClauseProxy is a proxy for WhereClause.
// It's useful when the WhereClause in a build can be changed.
type whereClauseProxy struct {
*WhereClause
}
var _ Builder = new(whereClauseProxy)
// BuildWithFlavor builds a WHERE clause with the specified flavor and initial arguments.
func (wc *WhereClause) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{}) {
if len(wc.clauses) == 0 {
return "", nil
}
buf := newStringBuilder()
buf.WriteLeadingString("WHERE ")
sql, args = wc.clauses[0].Build(flavor, initialArg...)
buf.WriteString(sql)
for _, clause := range wc.clauses[1:] {
buf.WriteString(" AND ")
sql, args = clause.Build(flavor, args...)
buf.WriteString(sql)
}
return buf.String(), args
}
// Build returns compiled WHERE clause string and args.
func (wc *WhereClause) Build() (sql string, args []interface{}) {
return wc.BuildWithFlavor(wc.flavor)
}
// SetFlavor sets the flavor of compiled sql.
// When the WhereClause belongs to a builder, the flavor of the builder will be used when building SQL.
func (wc *WhereClause) SetFlavor(flavor Flavor) (old Flavor) {
old = wc.flavor
wc.flavor = flavor
return
}
// Flavor returns flavor of clause
func (wc *WhereClause) Flavor() Flavor {
return wc.flavor
}
// AddWhereExpr adds an AND expression to WHERE clause with the specified arguments.
func (wc *WhereClause) AddWhereExpr(args *Args, andExpr ...string) *WhereClause {
if len(andExpr) == 0 {
return wc
}
andExprsBytesLen := estimateStringsBytes(andExpr)
if andExprsBytesLen == 0 {
return wc
}
// Merge with last clause if possible.
if len(wc.clauses) > 0 {
lastClause := &wc.clauses[len(wc.clauses)-1]
if lastClause.args == args {
lastClause.andExprs = append(lastClause.andExprs, andExpr...)
return wc
}
}
wc.clauses = append(wc.clauses, clause{
args: args,
andExprs: andExpr,
})
return wc
}
// AddWhereClause adds all clauses in the whereClause to the wc.
func (wc *WhereClause) AddWhereClause(whereClause *WhereClause) *WhereClause {
if whereClause == nil {
return wc
}
wc.clauses = append(wc.clauses, whereClause.clauses...)
return wc
}