forked from doug-martin/goqu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
expressions.go
333 lines (287 loc) · 10.6 KB
/
expressions.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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
package goqu
import (
"github.com/doug-martin/goqu/v9/exp"
)
type (
Expression = exp.Expression
Ex = exp.Ex
ExOr = exp.ExOr
Op = exp.Op
Record = exp.Record
Vals = exp.Vals
// Options to use when generating a TRUNCATE statement
TruncateOptions = exp.TruncateOptions
)
// emptyWindow is an empty WINDOW clause without name
var emptyWindow = exp.NewWindowExpression(nil, nil, nil, nil)
const (
Wait = exp.Wait
NoWait = exp.NoWait
SkipLocked = exp.SkipLocked
)
// Creates a new Casted expression
//
// Cast(I("a"), "NUMERIC") -> CAST("a" AS NUMERIC)
func Cast(e exp.Expression, t string) exp.CastExpression {
return exp.NewCastExpression(e, t)
}
// Creates a conflict struct to be passed to InsertConflict to ignore constraint errors
//
// InsertConflict(DoNothing(),...) -> INSERT INTO ... ON CONFLICT DO NOTHING
func DoNothing() exp.ConflictExpression {
return exp.NewDoNothingConflictExpression()
}
// Creates a ConflictUpdate struct to be passed to InsertConflict
// Represents a ON CONFLICT DO UPDATE portion of an INSERT statement (ON DUPLICATE KEY UPDATE for mysql)
//
// InsertConflict(DoUpdate("target_column", update),...) ->
// INSERT INTO ... ON CONFLICT DO UPDATE SET a=b
// InsertConflict(DoUpdate("target_column", update).Where(Ex{"a": 1},...) ->
// INSERT INTO ... ON CONFLICT DO UPDATE SET a=b WHERE a=1
func DoUpdate(target string, update interface{}) exp.ConflictUpdateExpression {
return exp.NewDoUpdateConflictExpression(target, update)
}
// A list of expressions that should be ORed together
//
// Or(I("a").Eq(10), I("b").Eq(11)) //(("a" = 10) OR ("b" = 11))
func Or(expressions ...exp.Expression) exp.ExpressionList {
return exp.NewExpressionList(exp.OrType, expressions...)
}
// A list of expressions that should be ANDed together
//
// And(I("a").Eq(10), I("b").Eq(11)) //(("a" = 10) AND ("b" = 11))
func And(expressions ...exp.Expression) exp.ExpressionList {
return exp.NewExpressionList(exp.AndType, expressions...)
}
// Creates a new SQLFunctionExpression with the given name and arguments
func Func(name string, args ...interface{}) exp.SQLFunctionExpression {
return exp.NewSQLFunctionExpression(name, args...)
}
// used internally to normalize the column name if passed in as a string it should be turned into an identifier
func newIdentifierFunc(name string, col interface{}) exp.SQLFunctionExpression {
if s, ok := col.(string); ok {
col = I(s)
}
return Func(name, col)
}
// Creates a new DISTINCT sql function
//
// DISTINCT("a") -> DISTINCT("a")
// DISTINCT(I("a")) -> DISTINCT("a")
func DISTINCT(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("DISTINCT", col) }
// Creates a new COUNT sql function
//
// COUNT("a") -> COUNT("a")
// COUNT("*") -> COUNT("*")
// COUNT(I("a")) -> COUNT("a")
func COUNT(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("COUNT", col) }
// Creates a new MIN sql function
//
// MIN("a") -> MIN("a")
// MIN(I("a")) -> MIN("a")
func MIN(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("MIN", col) }
// Creates a new MAX sql function
//
// MAX("a") -> MAX("a")
// MAX(I("a")) -> MAX("a")
func MAX(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("MAX", col) }
// Creates a new AVG sql function
//
// AVG("a") -> AVG("a")
// AVG(I("a")) -> AVG("a")
func AVG(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("AVG", col) }
// Creates a new FIRST sql function
//
// FIRST("a") -> FIRST("a")
// FIRST(I("a")) -> FIRST("a")
func FIRST(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("FIRST", col) }
// Creates a new LAST sql function
//
// LAST("a") -> LAST("a")
// LAST(I("a")) -> LAST("a")
func LAST(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("LAST", col) }
// Creates a new SUM sql function
//
// SUM("a") -> SUM("a")
// SUM(I("a")) -> SUM("a")
func SUM(col interface{}) exp.SQLFunctionExpression { return newIdentifierFunc("SUM", col) }
// Creates a new COALESCE sql function
//
// COALESCE(I("a"), "a") -> COALESCE("a", 'a')
// COALESCE(I("a"), I("b"), nil) -> COALESCE("a", "b", NULL)
func COALESCE(vals ...interface{}) exp.SQLFunctionExpression {
return Func("COALESCE", vals...)
}
//nolint:stylecheck,revive // sql function name
func ROW_NUMBER() exp.SQLFunctionExpression {
return Func("ROW_NUMBER")
}
func RANK() exp.SQLFunctionExpression {
return Func("RANK")
}
//nolint:stylecheck,revive // sql function name
func DENSE_RANK() exp.SQLFunctionExpression {
return Func("DENSE_RANK")
}
//nolint:stylecheck,revive // sql function name
func PERCENT_RANK() exp.SQLFunctionExpression {
return Func("PERCENT_RANK")
}
//nolint:stylecheck,revive //sql function name
func CUME_DIST() exp.SQLFunctionExpression {
return Func("CUME_DIST")
}
func NTILE(n int) exp.SQLFunctionExpression {
return Func("NTILE", n)
}
//nolint:stylecheck,revive //sql function name
func FIRST_VALUE(val interface{}) exp.SQLFunctionExpression {
return newIdentifierFunc("FIRST_VALUE", val)
}
//nolint:stylecheck,revive //sql function name
func LAST_VALUE(val interface{}) exp.SQLFunctionExpression {
return newIdentifierFunc("LAST_VALUE", val)
}
//nolint:stylecheck,revive //sql function name
func NTH_VALUE(val interface{}, nth int) exp.SQLFunctionExpression {
if s, ok := val.(string); ok {
val = I(s)
}
return Func("NTH_VALUE", val, nth)
}
// Creates a new Identifier, the generated sql will use adapter specific quoting or '"' by default, this ensures case
// sensitivity and in certain databases allows for special characters, (e.g. "curr-table", "my table").
//
// The identifier will be split by '.'
//
// Table and Column example
//
// I("table.column") -> "table"."column" //A Column and table
//
// Schema table and column
//
// I("schema.table.column") -> "schema"."table"."column"
//
// Table with star
//
// I("table.*") -> "table".*
func I(ident string) exp.IdentifierExpression {
return exp.ParseIdentifier(ident)
}
// Creates a new Column Identifier, the generated sql will use adapter specific quoting or '"' by default, this ensures case
// sensitivity and in certain databases allows for special characters, (e.g. "curr-table", "my table").
// An Identifier can represent a one or a combination of schema, table, and/or column.
//
// C("column") -> "column" //A Column
// C("column").Table("table") -> "table"."column" //A Column and table
// C("column").Table("table").Schema("schema") //Schema table and column
// C("*") //Also handles the * operator
func C(col string) exp.IdentifierExpression {
return exp.NewIdentifierExpression("", "", col)
}
// Creates a new Schema Identifier, the generated sql will use adapter specific quoting or '"' by default, this ensures case
// sensitivity and in certain databases allows for special characters, (e.g. "curr-schema", "my schema").
//
// S("schema") -> "schema" //A Schema
// S("schema").Table("table") -> "schema"."table" //A Schema and table
// S("schema").Table("table").Col("col") //Schema table and column
// S("schema").Table("table").Col("*") //Schema table and all columns
func S(schema string) exp.IdentifierExpression {
return exp.NewIdentifierExpression(schema, "", "")
}
// Creates a new Table Identifier, the generated sql will use adapter specific quoting or '"' by default, this ensures case
// sensitivity and in certain databases allows for special characters, (e.g. "curr-table", "my table").
//
// T("table") -> "table" //A Column
// T("table").Col("col") -> "table"."column" //A Column and table
// T("table").Schema("schema").Col("col) -> "schema"."table"."column" //Schema table and column
// T("table").Schema("schema").Col("*") -> "schema"."table".* //Also handles the * operator
func T(table string) exp.IdentifierExpression {
return exp.NewIdentifierExpression("", table, "")
}
// Create a new WINDOW clause
//
// W() -> ()
// W().PartitionBy("a") -> (PARTITION BY "a")
// W().PartitionBy("a").OrderBy("b") -> (PARTITION BY "a" ORDER BY "b")
// W().PartitionBy("a").OrderBy("b").Inherit("w1") -> ("w1" PARTITION BY "a" ORDER BY "b")
// W().PartitionBy("a").OrderBy(I("b").Desc()).Inherit("w1") -> ("w1" PARTITION BY "a" ORDER BY "b" DESC)
// W("w") -> "w" AS ()
// W("w", "w1") -> "w" AS ("w1")
// W("w").Inherit("w1") -> "w" AS ("w1")
// W("w").PartitionBy("a") -> "w" AS (PARTITION BY "a")
// W("w", "w1").PartitionBy("a") -> "w" AS ("w1" PARTITION BY "a")
// W("w", "w1").PartitionBy("a").OrderBy("b") -> "w" AS ("w1" PARTITION BY "a" ORDER BY "b")
func W(ws ...string) exp.WindowExpression {
switch len(ws) {
case 0:
return emptyWindow
case 1:
return exp.NewWindowExpression(I(ws[0]), nil, nil, nil)
default:
return exp.NewWindowExpression(I(ws[0]), I(ws[1]), nil, nil)
}
}
// Creates a new ON clause to be used within a join
//
// ds.Join(goqu.T("my_table"), goqu.On(
// goqu.I("my_table.fkey").Eq(goqu.I("other_table.id")),
// ))
func On(expressions ...exp.Expression) exp.JoinCondition {
return exp.NewJoinOnCondition(expressions...)
}
// Creates a new USING clause to be used within a join
//
// ds.Join(goqu.T("my_table"), goqu.Using("fkey"))
func Using(columns ...interface{}) exp.JoinCondition {
return exp.NewJoinUsingCondition(columns...)
}
// Creates a new SQL literal with the provided arguments.
//
// L("a = 1") -> a = 1
//
// You can also you placeholders. All placeholders within a Literal are represented by '?'
//
// L("a = ?", "b") -> a = 'b'
//
// Literals can also contain placeholders for other expressions
//
// L("(? AND ?) OR (?)", I("a").Eq(1), I("b").Eq("b"), I("c").In([]string{"a", "b", "c"}))
func L(sql string, args ...interface{}) exp.LiteralExpression {
return Literal(sql, args...)
}
// Alias for goqu.L
func Literal(sql string, args ...interface{}) exp.LiteralExpression {
return exp.NewLiteralExpression(sql, args...)
}
// Create a new SQL value ( alias for goqu.L("?", val) ). The prrimary use case for this would be in selects.
// See examples.
func V(val interface{}) exp.LiteralExpression {
return exp.NewLiteralExpression("?", val)
}
// Creates a new Range to be used with a Between expression
//
// exp.C("col").Between(exp.Range(1, 10))
func Range(start, end interface{}) exp.RangeVal {
return exp.NewRangeVal(start, end)
}
// Creates a literal *
func Star() exp.LiteralExpression { return exp.Star() }
// Returns a literal for DEFAULT sql keyword
func Default() exp.LiteralExpression {
return exp.Default()
}
func Lateral(table exp.AppendableExpression) exp.LateralExpression {
return exp.NewLateralExpression(table)
}
// Create a new ANY comparison
func Any(val interface{}) exp.SQLFunctionExpression {
return Func("ANY ", val)
}
// Create a new ALL comparison
func All(val interface{}) exp.SQLFunctionExpression {
return Func("ALL ", val)
}
func Case() exp.CaseExpression {
return exp.NewCaseExpression()
}