You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.4 KiB
146 lines
4.4 KiB
package rel
|
|
|
|
// JoinQuery defines join clause in query.
|
|
type JoinQuery struct {
|
|
Mode string
|
|
Table string
|
|
From string
|
|
To string
|
|
Assoc string
|
|
Filter FilterQuery
|
|
Arguments []interface{}
|
|
}
|
|
|
|
// 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 ...interface{}) JoinQuery {
|
|
if args == nil {
|
|
// prevent buildJoin to populate From and To variable.
|
|
args = []interface{}{}
|
|
}
|
|
|
|
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...)
|
|
}
|