103 lines
2.2 KiB
Go
103 lines
2.2 KiB
Go
package model
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/fthvgb1/wp-go/helper"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
func setTable[T Model](q *QueryCondition) {
|
|
if q.From == "" {
|
|
q.From = Table[T]()
|
|
}
|
|
}
|
|
|
|
func Relation(db dbQuery, ctx context.Context, r any, q *QueryCondition) ([]func(), []func() error) {
|
|
var fn []func()
|
|
var fns []func() error
|
|
t := reflect.TypeOf(r).Elem()
|
|
v := reflect.ValueOf(r).Elem()
|
|
for tableTag, relation := range q.Relation {
|
|
if tableTag == "" {
|
|
continue
|
|
}
|
|
tableTag := tableTag
|
|
relation := relation
|
|
for i := 0; i < t.NumField(); i++ {
|
|
i := i
|
|
tag := t.Field(i).Tag
|
|
table, ok := tag.Lookup("table")
|
|
if !ok || table == "" {
|
|
continue
|
|
}
|
|
tables := strings.Split(table, " ")
|
|
if tables[len(tables)-1] != tableTag {
|
|
continue
|
|
}
|
|
foreignKey := tag.Get("foreignKey")
|
|
if foreignKey == "" {
|
|
continue
|
|
}
|
|
localKey := tag.Get("local")
|
|
if localKey == "" {
|
|
continue
|
|
}
|
|
if relation == nil {
|
|
relation = &QueryCondition{
|
|
Fields: "*",
|
|
}
|
|
}
|
|
relation.From = table
|
|
id := ""
|
|
j := 0
|
|
for ; j < t.NumField(); j++ {
|
|
vvv, ok := t.Field(j).Tag.Lookup("db")
|
|
if ok && vvv == tag.Get("local") {
|
|
break
|
|
}
|
|
}
|
|
if relation.WithJoin {
|
|
from := strings.Split(q.From, " ")
|
|
fn = append(fn, func() {
|
|
qq := helper.GetContextVal(ctx, "ancestorsQueryCondition", q)
|
|
qq.Join = append(q.Join, SqlBuilder{
|
|
{"left join", table, fmt.Sprintf("%s.%s=%s.%s", tables[len(tables)-1], foreignKey, from[len(from)-1], localKey)},
|
|
}...)
|
|
})
|
|
}
|
|
fns = append(fns, func() error {
|
|
{
|
|
var w any = relation.Where
|
|
if w == nil {
|
|
w = SqlBuilder{}
|
|
}
|
|
ww, ok := w.(SqlBuilder)
|
|
if ok {
|
|
id = fmt.Sprintf("%v", v.Field(j).Interface())
|
|
ww = append(ww, SqlBuilder{{
|
|
foreignKey, "=", id, "int",
|
|
}}...)
|
|
relation.Where = ww
|
|
}
|
|
}
|
|
var err error
|
|
vv := reflect.New(v.Field(i).Type().Elem()).Interface()
|
|
switch tag.Get("relation") {
|
|
case "hasOne":
|
|
err = parseRelation(false, db, ctx, vv, relation)
|
|
case "hasMany":
|
|
err = parseRelation(true, db, ctx, vv, relation)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.Field(i).Set(reflect.ValueOf(vv))
|
|
return nil
|
|
})
|
|
}
|
|
}
|
|
return fn, fns
|
|
}
|