-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathexpr.go
More file actions
159 lines (130 loc) · 3.55 KB
/
expr.go
File metadata and controls
159 lines (130 loc) · 3.55 KB
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
package query
import (
"fmt"
"strings"
)
// callExpr is the expression used for calling functions within PostgreSQL
type callExpr struct {
name string
args []Expr
}
type listExpr struct {
items []string
wrap bool
args []interface{}
}
type identExpr string
type argExpr struct {
val interface{}
}
type litExpr struct {
val interface{}
}
// Expr is an expression that exists within the Query being built. This would
// typically be an identifier, literal, argument, function call, or list
// values in queries.
type Expr interface {
// Args returns the arguments that were given to the Query expression.
Args() []interface{}
// Build returns the built up Query expression.
Build() string
}
var (
_ Expr = (*listExpr)(nil)
_ Expr = (*identExpr)(nil)
_ Expr = (*argExpr)(nil)
_ Expr = (*litExpr)(nil)
_ Expr = (*callExpr)(nil)
)
// Columns returns a list expression of the given column names. This will not
// be wrapped in parentheses when built.
func Columns(cols ...string) listExpr {
return listExpr{
items: cols,
wrap: false,
}
}
// Sum returns a call expression for the SUM function on the given column.
func Sum(col string) callExpr {
return callExpr{
name: "SUM",
args: []Expr{Lit(col)},
}
}
// Count returns a call expression for the COUNT function on the given columns.
func Count(cols ...string) callExpr {
exprs := make([]Expr, 0, len(cols))
for _, col := range cols {
exprs = append(exprs, Lit(col))
}
return callExpr{
name: "COUNT",
args: exprs,
}
}
// List returns a list expression of the given values. Each item in the
// given list will use the ? placeholder. This will be wrapped in parentheses
// when built.
func List(vals ...interface{}) listExpr {
items := make([]string, 0, len(vals))
for range vals {
items = append(items, "?")
}
return listExpr{
items: items,
wrap: true,
args: vals,
}
}
// Ident returns an identifier expression for the given string. When built
// this will simply use the initial string that was given.
func Ident(s string) identExpr { return identExpr(s) }
// Arg returns an argument expression for the given value. When built this will
// use ? as the placeholder for the argument value.
func Arg(val interface{}) argExpr {
return argExpr{
val: val,
}
}
// Lit returns a literal expression for the given value. This will place the
// literal value into the built up expression string itself, and not use the ?
// placeholder. For example using Lit like so,
//
// Where("deleted_at", "IS NOT", Lit("NULL"))
//
// would result in a WHERE clause being built up like this,
//
// WHERE (deleted_at IS NOT NULL)
func Lit(val interface{}) litExpr {
return litExpr{
val: val,
}
}
func (e listExpr) Args() []interface{} { return e.args }
func (e listExpr) Build() string {
items := strings.Join(e.items, ", ")
if e.wrap {
return "(" + items + ")"
}
return items
}
func (e identExpr) Args() []interface{} { return nil }
func (e identExpr) Build() string { return string(e) }
func (e argExpr) Args() []interface{} { return []interface{}{e.val} }
func (e argExpr) Build() string { return "?" }
func (e litExpr) Args() []interface{} { return nil }
func (e litExpr) Build() string { return fmt.Sprintf("%v", e.val) }
func (e callExpr) Args() []interface{} {
vals := make([]interface{}, 0)
for _, expr := range e.args {
vals = append(vals, expr.Args()...)
}
return vals
}
func (e callExpr) Build() string {
args := make([]string, 0, len(e.args))
for _, arg := range e.args {
args = append(args, arg.Build())
}
return e.name + "(" + strings.Join(args, ", ") + ")"
}