wp-go/model/relation.go
2023-05-17 22:22:31 +08:00

82 lines
1.6 KiB
Go

package model
import (
"context"
"fmt"
"reflect"
"strings"
)
func setTable[T Model](q *QueryCondition) {
if q.From == "" {
q.From = Table[T]()
}
}
func Relation[T Model](db dbQuery, ctx context.Context, r *T, q *QueryCondition) (err error) {
var rr T
t := reflect.TypeOf(rr)
v := reflect.ValueOf(r).Elem()
for tableTag, relation := range q.Relation {
if tableTag == "" {
continue
}
for i := 0; i < t.NumField(); 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
}
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") {
id = fmt.Sprintf("%v", v.Field(j).Interface())
break
}
}
{
var w any = relation.Where
if w == nil {
w = SqlBuilder{}
}
ww, ok := w.(SqlBuilder)
if ok {
ww = append(ww, SqlBuilder{{
tag.Get("foreignKey"), "=", id, "int",
}}...)
relation.Where = ww
}
}
sq, args, er := BuildQuerySql(*relation)
if er != nil {
err = er
return
}
vv := reflect.New(v.Field(i).Type().Elem()).Interface()
switch tag.Get("relation") {
case "hasOne":
err = db.Get(ctx, vv, sq, args...)
case "hasMany":
err = db.Select(ctx, vv, sq, args...)
}
if err != nil {
return
}
v.Field(i).Set(reflect.ValueOf(vv))
}
}
return
}