This repository has been archived by the owner on Nov 27, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rushia.go
219 lines (179 loc) · 3.63 KB
/
rushia.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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
package rushia
import (
"fmt"
"reflect"
"strings"
)
// Expr
type Expr struct {
rawQuery string
params []interface{}
}
// H
type H map[string]interface{}
const (
queryTypeUnknown queryType = iota
queryTypeInsert
queryTypeReplace
queryTypeUpdate
queryTypeSelect
queryTypePatch
queryTypeExists
queryTypeInsertSelect
queryTypeRawQuery
queryTypeSubQuery
queryTypeDelete
)
type queryType int
const (
connectorTypeAnd connectorType = iota
connectorTypeOr
)
type connectorType int
func (t connectorType) toQuery() string {
switch t {
case connectorTypeOr:
return "OR"
default:
return "AND"
}
}
const (
joinTypeLeft joinType = iota
joinTypeRight
joinTypeInner
joinTypeNatural
joinTypeCross
)
type joinType int
func (t joinType) toQuery() string {
switch t {
case joinTypeRight:
return "RIGHT JOIN"
case joinTypeInner:
return "INNER JOIN"
case joinTypeNatural:
return "NATURAL JOIN"
case joinTypeCross:
return "CROSS JOIN"
default:
return "LEFT JOIN"
}
}
const (
insertTypeInsert insertType = iota
insertTypeReplace
)
type insertType int
func (t insertType) toQuery() string {
switch t {
case insertTypeReplace:
return "REPLACE"
default:
return "INSERT"
}
}
type condition struct {
query string
args []interface{}
connector connectorType
}
type join struct {
table string
subQuery *Query
typ joinType
conditions []condition
}
type limit struct {
from int
count int
}
type offset struct {
count int
offset int
}
type order struct {
field string
values []interface{}
column string
// sort orderSortType
}
type exclude struct {
kinds []reflect.Kind
fields []string
}
type union struct {
all bool
query *Query
}
// Query
type Query struct {
alias string
typ queryType
subQuery *Query
table interface{}
wheres []condition
havings []condition
queryOptions []string
unions []union
data interface{}
selects []interface{}
joins []join
duplicate H
limit limit
offset offset
orders []order
groups []string
rawQuery string
params []interface{}
omits []string
exclude exclude
}
// NewQuery creates a Query based on a table name or a sub query.
func NewQuery(table interface{}) *Query {
q := &Query{
table: table,
}
return q
}
// NewRawQuery creates a Query based on the passed in raw query and the parameters.
func NewRawQuery(q string, params ...interface{}) *Query {
if strings.Contains(q, "??") {
panic("rushia: raw query doesn't support escape ?? sign yet")
}
return &Query{
typ: queryTypeRawQuery,
rawQuery: q,
params: params,
}
}
// NewExpr creates an Expression that accepts raw query and the parameters. Could be useful as the value if you are representing a complex query.
func NewExpr(query string, params ...interface{}) *Expr {
return &Expr{
rawQuery: query,
params: params,
}
}
// NewAlias creates an alias for a table.
func NewAlias(table string, alias string) string {
return fmt.Sprintf("`%s` AS %s", table, alias)
}
// Build builds the Query.
func Build(q *Query) (query string, params []interface{}) {
query += q.padSpace(q.buildQuery())
if q.typ == queryTypeRawQuery || q.typ == queryTypeExists {
return q.trim(query), q.params
}
query += q.padSpace(q.buildAs())
query += q.padSpace(q.buildDuplicate())
query += q.padSpace(q.buildUnion())
query += q.padSpace(q.buildJoin())
query += q.padSpace(q.buildWhere())
query += q.padSpace(q.buildHaving())
query += q.padSpace(q.buildOrderBy())
query += q.padSpace(q.buildGroupBy())
query += q.padSpace(q.buildLimit())
query += q.padSpace(q.buildOffset())
query += q.padSpace(q.buildAfterQueryOptions())
return q.trim(query), q.params
}