forked from aodin/aspect
/
clause.go
173 lines (146 loc) · 4.02 KB
/
clause.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
package aspect
import (
"fmt"
"strings"
)
// Clause is a common interface that most components implement.
type Clause interface {
Compiles
}
// ColumnClause is a clause used for column selections.
type ColumnClause struct {
table *TableElem
name string
}
// String returns the ColumnClause's SQL using the default dialect.
func (c ColumnClause) String() string {
compiled, _ := c.Compile(&defaultDialect{}, Params())
return compiled
}
// Compile creates the SQL to represent a table column using the given
// dialect, optionally without a table prefix.
func (c ColumnClause) Compile(d Dialect, params *Parameters) (string, error) {
if c.table == nil {
return fmt.Sprintf(`"%s"`, c.name), nil
} else {
return fmt.Sprintf(`"%s"."%s"`, c.table.name, c.name), nil
}
}
// ColumnClauseFromColumn creates a ColumnClause from a ColumnElem
func ColumnClauseFromColumn(c ColumnElem) ColumnClause {
return ColumnClause{table: c.table, name: c.name}
}
// ColumnClauseFromColumn creates a ColumnClause from a ColumnElem's name only
func ColumnOnlyClause(c ColumnElem) ColumnClause {
return ColumnClause{name: c.name}
}
// TODO This is a dangerous clause that leads to parameters not being escaped
type StringClause struct {
Name string
}
func (c StringClause) String() string {
compiled, _ := c.Compile(&defaultDialect{}, Params())
return compiled
}
func (c StringClause) Compile(d Dialect, params *Parameters) (string, error) {
return fmt.Sprintf(`'%s'`, c.Name), nil
}
// TODO This is a dangerous clause that leads to parameters not being escaped
type IntClause struct {
D int
}
func (c IntClause) String() string {
compiled, _ := c.Compile(&defaultDialect{}, Params())
return compiled
}
func (c IntClause) Compile(d Dialect, params *Parameters) (string, error) {
return fmt.Sprintf(`%d`, c.D), nil
}
type FuncClause struct {
Inner Clause
F string
}
func (c FuncClause) String() string {
compiled, _ := c.Compile(&defaultDialect{}, Params())
return compiled
}
func (c FuncClause) Compile(d Dialect, params *Parameters) (string, error) {
cc, err := c.Inner.Compile(d, params)
if err != nil {
return "", err
}
return fmt.Sprintf("%s(%s)", c.F, cc), nil
}
type UnaryClause struct {
Pre Clause
Sep string
}
func (c UnaryClause) String() string {
compiled, _ := c.Compile(&defaultDialect{}, Params())
return compiled
}
func (c UnaryClause) Compile(d Dialect, params *Parameters) (string, error) {
var pre string
var err error
if c.Pre != nil {
pre, err = c.Pre.Compile(d, params)
if err != nil {
return "", err
}
}
return fmt.Sprintf("%s%s", pre, c.Sep), nil
}
// BinaryClause is two clauses with a separator
type BinaryClause struct {
Pre, Post Clause
Sep string
}
func (c BinaryClause) String() string {
compiled, _ := c.Compile(&defaultDialect{}, Params())
return compiled
}
func (c BinaryClause) Compile(d Dialect, params *Parameters) (string, error) {
var pre, post string
var err error
if c.Pre != nil {
pre, err = c.Pre.Compile(d, params)
if err != nil {
return "", err
}
}
if c.Post != nil {
post, err = c.Post.Compile(d, params)
if err != nil {
return "", err
}
}
return fmt.Sprintf("%s%s%s", pre, c.Sep, post), nil
}
// ArrayClause is any number of clauses with a column join
type ArrayClause struct {
Clauses []Clause
Sep string
}
func (c ArrayClause) String() string {
compiled, _ := c.Compile(&defaultDialect{}, Params())
return compiled
}
func (c ArrayClause) Compile(d Dialect, params *Parameters) (string, error) {
compiled := make([]string, len(c.Clauses))
var err error
for i, clause := range c.Clauses {
compiled[i], err = clause.Compile(d, params)
if err != nil {
return "", err
}
}
return strings.Join(compiled, c.Sep), nil
}
// AllOf joins the given clauses with 'AND' and wraps them in parentheses
func AllOf(clauses ...Clause) Clause {
return FuncClause{Inner: ArrayClause{clauses, " AND "}}
}
// AnyOf joins the given clauses with 'OR' and wraps them in parentheses
func AnyOf(clauses ...Clause) Clause {
return FuncClause{Inner: ArrayClause{clauses, " OR "}}
}