166 lines
4.3 KiB
Go
166 lines
4.3 KiB
Go
package orm
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const PopulateAll = "~~~ALL~~~"
|
|
|
|
func join(r *Relationship) (string, string, string) {
|
|
rtable := r.RelatedModel.TableName
|
|
field := r.Model.Fields[r.FieldName]
|
|
var fk, pk, alias string
|
|
if !r.RelatedModel.embeddedIsh && !r.Model.embeddedIsh {
|
|
alias = pascalToSnakeCase(field.Name)
|
|
fk = fmt.Sprintf("%s.%s", alias, r.RelatedModel.Fields[r.RelatedModel.IDField].ColumnName)
|
|
pk = fmt.Sprintf("%s.%s", r.Model.TableName, field.ColumnName)
|
|
alias = pascalToSnakeCase(field.Name)
|
|
} else if !r.Model.embeddedIsh {
|
|
alias = pascalToSnakeCase(r.FieldName)
|
|
sid := strings.TrimSuffix(r.JoinField(), "ID")
|
|
fk = fmt.Sprintf("%s.%s", alias, r.RelatedModel.Fields[sid].ColumnName)
|
|
pk = fmt.Sprintf("%s.%s", r.Model.TableName, r.Model.Fields[r.Model.IDField].ColumnName)
|
|
}
|
|
return alias, rtable, fmt.Sprintf("%s = %s", fk, pk)
|
|
}
|
|
|
|
func m2mJoin(r *Relationship) [][3]string {
|
|
result := make([][3]string, 0)
|
|
jt := r.JoinTable()
|
|
first := [3]string{
|
|
pascalToSnakeCase(r.FieldName),
|
|
jt,
|
|
fmt.Sprintf("%s = %s",
|
|
fmt.Sprintf("%s.%s",
|
|
jt,
|
|
r.RelatedModel.Fields[r.RelatedModel.IDField].ColumnName,
|
|
),
|
|
fmt.Sprintf("%s.%s",
|
|
r.Model.TableName,
|
|
r.Model.Fields[r.Model.IDField].ColumnName,
|
|
),
|
|
),
|
|
}
|
|
second := [3]string{
|
|
pascalToSnakeCase(r.m2mInverse.FieldName),
|
|
r.RelatedModel.TableName,
|
|
fmt.Sprintf("%s = %s",
|
|
fmt.Sprintf("%s.%s", r.RelatedModel.TableName, r.RelatedModel.Fields[r.RelatedModel.IDField].ColumnName),
|
|
fmt.Sprintf("%s.%s", jt, r.m2mInverse.JoinField()),
|
|
),
|
|
}
|
|
|
|
/*first := fmt.Sprintf("%s AS %s ON %s = %s",
|
|
jt,
|
|
fmt.Sprintf("%s.%s",
|
|
jt,
|
|
r.RelatedModel.Fields[r.RelatedModel.IDField].ColumnName,
|
|
),
|
|
fmt.Sprintf("%s.%s",
|
|
r.Model.TableName,
|
|
r.Model.Fields[r.Model.IDField].ColumnName,
|
|
),
|
|
)
|
|
second := fmt.Sprintf("%s ON %s = %s",
|
|
r.RelatedModel.TableName,
|
|
fmt.Sprintf("%s.%s", r.RelatedModel.TableName, r.RelatedModel.Fields[r.RelatedModel.IDField].ColumnName),
|
|
fmt.Sprintf("%s.%s", jt, r.m2mInverse.JoinField()),
|
|
)*/
|
|
result = append(result, first, second)
|
|
return result
|
|
}
|
|
|
|
func nestedJoin(m *Model, path string) (joins [][3]string, ree []*Relationship) {
|
|
splitPath := strings.Split(path, ".")
|
|
prevModel := m
|
|
for _, f := range splitPath {
|
|
rel, ok := m.Relationships[f]
|
|
if !ok {
|
|
break
|
|
}
|
|
var (
|
|
fk, pk string
|
|
)
|
|
if !rel.Model.embeddedIsh && !rel.RelatedModel.embeddedIsh {
|
|
pk = prevModel.Fields[rel.FieldName].ColumnName
|
|
fk = rel.RelatedModel.Fields[rel.RelatedModel.IDField].ColumnName
|
|
} else if !rel.Model.embeddedIsh {
|
|
pk = prevModel.Fields[prevModel.IDField].ColumnName
|
|
fk = rel.RelatedModel.Fields[strings.TrimSuffix(rel.JoinField(), "ID")].ColumnName
|
|
}
|
|
ree = append(ree, rel)
|
|
j2 := [3]string{
|
|
rel.Model.Fields[rel.FieldName].ColumnName,
|
|
rel.RelatedModel.TableName,
|
|
fmt.Sprintf("%s.%s = %s.%s",
|
|
rel.RelatedModel.TableName, fk,
|
|
prevModel.TableName, pk),
|
|
}
|
|
|
|
/*j2 := fmt.Sprintf("%s AS %s ON %s.%s = %s.%s",
|
|
rel.RelatedModel.TableName,
|
|
rel.Model.Fields[rel.FieldName].ColumnName,
|
|
rel.RelatedModel.TableName, fk,
|
|
prevModel.TableName, pk,
|
|
)*/
|
|
joins = append(joins, j2)
|
|
prevModel = rel.RelatedModel
|
|
}
|
|
return
|
|
}
|
|
|
|
func (q *Query) Populate(relation string) *Query {
|
|
if relation == PopulateAll {
|
|
for _, rel := range q.model.Relationships {
|
|
if rel.Type == ManyToMany {
|
|
mjs := m2mJoin(rel)
|
|
for _, ajoin := range mjs {
|
|
q.joins[rel] = [3]string{
|
|
ajoin[0],
|
|
ajoin[1],
|
|
ajoin[2],
|
|
}
|
|
}
|
|
//q.joins = append(q.joins, m2mJoin(rel)...)
|
|
} else {
|
|
alias, tn, cond := join(rel)
|
|
q.joins[rel] = [3]string{
|
|
alias,
|
|
tn,
|
|
cond,
|
|
}
|
|
//q.joins = append(q.joins, tn)
|
|
}
|
|
q.relatedModels[rel.RelatedModel.Name] = rel.RelatedModel
|
|
}
|
|
} else {
|
|
if strings.Contains(relation, ".") {
|
|
njs, rmodels := nestedJoin(q.model, relation)
|
|
for i, m := range rmodels {
|
|
curTuple := njs[i]
|
|
q.joins[m] = [3]string{
|
|
curTuple[0],
|
|
curTuple[1],
|
|
curTuple[2],
|
|
}
|
|
q.relatedModels[m.Model.Name] = m.Model
|
|
}
|
|
//q.joins = append(q.joins, njs...)
|
|
} else {
|
|
rel, ok := q.model.Relationships[relation]
|
|
if ok {
|
|
alias, tn, j := join(rel)
|
|
q.joins[rel] = [3]string{
|
|
alias,
|
|
tn,
|
|
j,
|
|
}
|
|
//q.joins = append(q.joins, tn)
|
|
q.relatedModels[rel.RelatedModel.Name] = rel.RelatedModel
|
|
}
|
|
}
|
|
}
|
|
return q
|
|
}
|