wp-go/model/relation.go

103 lines
2.2 KiB
Go
Raw Normal View History

2023-05-17 14:22:31 +00:00
package model
import (
"context"
"fmt"
2023-05-18 14:27:28 +00:00
"github.com/fthvgb1/wp-go/helper"
2023-05-17 14:22:31 +00:00
"reflect"
"strings"
)
func setTable[T Model](q *QueryCondition) {
if q.From == "" {
q.From = Table[T]()
}
}
2023-05-18 14:27:28 +00:00
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()
2023-05-17 14:22:31 +00:00
v := reflect.ValueOf(r).Elem()
for tableTag, relation := range q.Relation {
if tableTag == "" {
continue
}
2023-05-18 14:27:28 +00:00
tableTag := tableTag
relation := relation
2023-05-17 14:22:31 +00:00
for i := 0; i < t.NumField(); i++ {
2023-05-18 14:27:28 +00:00
i := i
2023-05-17 14:22:31 +00:00
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
}
2023-05-18 14:27:28 +00:00
foreignKey := tag.Get("foreignKey")
if foreignKey == "" {
continue
}
localKey := tag.Get("local")
if localKey == "" {
continue
}
2023-05-17 14:22:31 +00:00
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
}
}
2023-05-18 14:27:28 +00:00
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
}
2023-05-17 14:22:31 +00:00
}
2023-05-18 14:27:28 +00:00
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)
2023-05-17 14:22:31 +00:00
}
2023-05-18 14:27:28 +00:00
if err != nil {
return err
}
v.Field(i).Set(reflect.ValueOf(vv))
return nil
})
2023-05-17 14:22:31 +00:00
}
}
2023-05-18 14:27:28 +00:00
return fn, fns
2023-05-17 14:22:31 +00:00
}