-
-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathjoin_query.go
145 lines (122 loc) · 4.34 KB
/
join_query.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
package rel
// JoinQuery defines join clause in query.
type JoinQuery struct {
Mode string
Table string
From string
To string
Assoc string
Filter FilterQuery
Arguments []any
}
// Build query.
func (jq JoinQuery) Build(query *Query) {
query.JoinQuery = append(query.JoinQuery, jq)
if jq.Assoc != "" {
query.AddPopulator(&query.JoinQuery[len(query.JoinQuery)-1])
}
}
func (jq *JoinQuery) Populate(query *Query, docMeta DocumentMeta) {
var (
assocMeta = docMeta.Association(jq.Assoc)
assocDocMeta = assocMeta.DocumentMeta()
)
jq.Table = assocDocMeta.Table() + " as " + jq.Assoc
jq.To = jq.Assoc + "." + assocMeta.ForeignField()
jq.From = docMeta.Table() + "." + assocMeta.ReferenceField()
// load association if defined and supported
if assocMeta.Type() == HasOne || assocMeta.Type() == BelongsTo {
var (
load = false
selectField = jq.Assoc + ".*"
)
for i := range query.SelectQuery.Fields {
if load && i > 0 {
query.SelectQuery.Fields[i-1] = query.SelectQuery.Fields[i]
}
if query.SelectQuery.Fields[i] == selectField {
load = true
}
}
if load {
fields := make([]string, len(assocDocMeta.Fields()))
for i, f := range assocDocMeta.Fields() {
fields[i] = jq.Assoc + "." + f + " as " + jq.Assoc + "." + f
}
query.SelectQuery.Fields = append(query.SelectQuery.Fields[:(len(query.SelectQuery.Fields)-1)], fields...)
}
}
}
// NewJoinWith query with custom join mode, table, field and additional filters with AND condition.
func NewJoinWith(mode string, table string, from string, to string, filter ...FilterQuery) JoinQuery {
return JoinQuery{
Mode: mode,
Table: table,
From: from,
To: to,
Filter: And(filter...),
}
}
// NewJoinFragment defines a join clause using raw query.
func NewJoinFragment(expr string, args ...any) JoinQuery {
if args == nil {
// prevent buildJoin to populate From and To variable.
args = []any{}
}
return JoinQuery{
Mode: expr,
Arguments: args,
}
}
// NewJoin with given table.
func NewJoin(table string, filter ...FilterQuery) JoinQuery {
return NewJoinWith("JOIN", table, "", "", filter...)
}
// NewJoinOn table with given field and optional additional filter.
func NewJoinOn(table string, from string, to string, filter ...FilterQuery) JoinQuery {
return NewJoinWith("JOIN", table, from, to, filter...)
}
// NewInnerJoin with given table and optional filter.
func NewInnerJoin(table string, filter ...FilterQuery) JoinQuery {
return NewInnerJoinOn(table, "", "", filter...)
}
// NewInnerJoinOn table with given field and optional additional filter.
func NewInnerJoinOn(table string, from string, to string, filter ...FilterQuery) JoinQuery {
return NewJoinWith("INNER JOIN", table, from, to, filter...)
}
// NewLeftJoin with given table and optional filter.
func NewLeftJoin(table string, filter ...FilterQuery) JoinQuery {
return NewLeftJoinOn(table, "", "", filter...)
}
// NewLeftJoinOn table with given field and optional additional filter.
func NewLeftJoinOn(table string, from string, to string, filter ...FilterQuery) JoinQuery {
return NewJoinWith("LEFT JOIN", table, from, to, filter...)
}
// NewRightJoin with given table and optional filter.
func NewRightJoin(table string, filter ...FilterQuery) JoinQuery {
return NewRightJoinOn(table, "", "", filter...)
}
// NewRightJoinOn table with given field and optional additional filter.
func NewRightJoinOn(table string, from string, to string, filter ...FilterQuery) JoinQuery {
return NewJoinWith("RIGHT JOIN", table, from, to, filter...)
}
// NewFullJoin with given table and optional filter.
func NewFullJoin(table string, filter ...FilterQuery) JoinQuery {
return NewFullJoinOn(table, "", "", filter...)
}
// NewFullJoinOn table with given field and optional additional filter.
func NewFullJoinOn(table string, from string, to string, filter ...FilterQuery) JoinQuery {
return NewJoinWith("FULL JOIN", table, from, to, filter...)
}
// NewJoinAssocWith with given association field and optional additional filters.
func NewJoinAssocWith(mode string, assoc string, filter ...FilterQuery) JoinQuery {
return JoinQuery{
Mode: mode,
Assoc: assoc,
Filter: And(filter...),
}
}
// NewJoinAssoc with given association field and optional additional filters.
func NewJoinAssoc(assoc string, filter ...FilterQuery) JoinQuery {
return NewJoinAssocWith("JOIN", assoc, filter...)
}