-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathjoin.go
130 lines (102 loc) · 3.52 KB
/
join.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
package sqlbuilder
import (
"fmt"
"strings"
)
type table struct {
name string
joinType int
joinConstraints []SQLProvider
subQuery SQLProvider
}
func (t *table) GetSQL(cache *VarCache) string {
if t.joinType == join_none {
if t.subQuery != nil {
return t.subQuery.GetSQL(cache)
}
return t.name
}
joinType := joinTypes[t.joinType]
ons := make([]string, len(t.joinConstraints))
for i, c := range t.joinConstraints {
ons[i] = c.GetSQL(cache)
}
return fmt.Sprintf("%s JOIN %s ON %s", joinType, t.name, strings.Join(ons, " AND "))
}
var joinTypes = map[int]string{
join_inner: "INNER",
join_left: "LEFT",
join_right: "RIGHT",
join_outer: "OUTER",
}
// Used within a JOIN context, joins on a particular column link
func OnColumn(field, otherField string) SQLProvider {
return Raw{field + " = " + otherField}
}
// Just a passthru to make people feel better
func OnExpression(expr SQLProvider) SQLProvider {
return expr
}
// Add a JOIN component. Constraints can be any number of sqlPRoviders, but you should only
// use OnColumn and OnValue
func (q *Query) join(joinType int, tableName string, constraints ...SQLProvider) *Query {
newTable := &table{
joinType: joinType,
name: tableName,
joinConstraints: constraints,
}
q.tables = append(q.tables, newTable)
return q
}
func (q *Query) InnerJoin(tableName string, constraints ...SQLProvider) *Query {
return q.join(join_inner, tableName, constraints...)
}
func (q *Query) LeftJoin(tableName string, constraints ...SQLProvider) *Query {
return q.join(join_left, tableName, constraints...)
}
func (q *Query) RightJoin(tableName string, constraints ...SQLProvider) *Query {
return q.join(join_right, tableName, constraints...)
}
func (q *Query) OuterJoin(tableName string, constraints ...SQLProvider) *Query {
return q.join(join_outer, tableName, constraints...)
}
// Get the alias of a table that has already been joined on the query. This is useful for when you construct the query using several different components and potentially more than one component may need to join the same table. Important to note, however that this function will return the first joined table that matches. If you join the same table twice with different aliases, you should not rely on this function.
func (q *Query) GetJoinAlias(tableName string) (found bool, alias string) {
var spl []string
var lowerName string
for _, t := range q.tables {
lowerName = strings.ToLower(t.name)
spl = strings.Split(lowerName, " as ")
if spl[0] == tableName {
found = true
if len(spl) > 1 {
alias = spl[1]
} else {
alias = spl[0]
}
break
}
}
return
}
// Join a table/alias comboination if it hasn't already been joined
func (q *Query) lazyJoin(joinType int, tableName string, constraints ...SQLProvider) *Query {
for _, t := range q.tables {
if t.name == tableName && t.joinType == joinType {
return q
}
}
return q.join(joinType, tableName, constraints...)
}
func (q *Query) LazyInnerJoin(tableName string, constraints ...SQLProvider) *Query {
return q.lazyJoin(join_inner, tableName, constraints...)
}
func (q *Query) LazyLeftJoin(tableName string, constraints ...SQLProvider) *Query {
return q.lazyJoin(join_left, tableName, constraints...)
}
func (q *Query) LazyRightJoin(tableName string, constraints ...SQLProvider) *Query {
return q.lazyJoin(join_right, tableName, constraints...)
}
func (q *Query) LazyOuterJoin(tableName string, constraints ...SQLProvider) *Query {
return q.lazyJoin(join_outer, tableName, constraints...)
}