Merge branch 'query_middle_table'
# Conflicts: # model/relation.go # model/relation_test.go
This commit is contained in:
commit
b41b6e0a09
|
@ -40,6 +40,9 @@ type post struct {
|
|||
User *user
|
||||
Ships *[]TermRelationships
|
||||
PostMeta *[]models.PostMeta
|
||||
TermTaxonomy *[]TermTaxonomy
|
||||
Terms *[]models.Terms
|
||||
CommentMetas *[]CommentMeta
|
||||
}
|
||||
|
||||
type TermRelationships struct {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
"github.com/fthvgb1/wp-go/helper/slice"
|
||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||
"golang.org/x/exp/constraints"
|
||||
"strings"
|
||||
)
|
||||
|
@ -36,25 +37,79 @@ type Relationship struct {
|
|||
ForeignKey string
|
||||
Local string
|
||||
On string
|
||||
Middle *Relationship
|
||||
}
|
||||
|
||||
func parseBeforeJoin(qq *QueryCondition, ship Relationship) {
|
||||
var fromTable, foreignKey, local string
|
||||
if ship.Middle != nil {
|
||||
parseBeforeJoin(qq, *ship.Middle)
|
||||
local = ship.Local
|
||||
fromTable = ship.Middle.Table
|
||||
} else {
|
||||
fromTable = qq.From
|
||||
}
|
||||
foreignKey = ship.ForeignKey
|
||||
local = ship.Local
|
||||
tables := strings.Split(ship.Table, " ")
|
||||
from := strings.Split(fromTable, " ")
|
||||
on := ""
|
||||
if ship.On != "" {
|
||||
on = fmt.Sprintf("and %s", on)
|
||||
}
|
||||
qq.Join = append(qq.Join, []string{
|
||||
"left join", ship.Table,
|
||||
fmt.Sprintf("%s.%s=%s.%s %s",
|
||||
tables[len(tables)-1], foreignKey, from[len(from)-1], local, on,
|
||||
)})
|
||||
|
||||
}
|
||||
|
||||
func parseAfterJoin(fromTable string, ids [][]any, qq *QueryCondition, ship Relationship) bool {
|
||||
tables := strings.Split(ship.Middle.Table, " ")
|
||||
from := strings.Split(fromTable, " ")
|
||||
on := ""
|
||||
if ship.On != "" {
|
||||
on = fmt.Sprintf("and %s", on)
|
||||
}
|
||||
foreignKey := ship.ForeignKey
|
||||
local := ship.Local
|
||||
qq.Join = append(qq.Join, []string{
|
||||
"left join", ship.Middle.Table,
|
||||
fmt.Sprintf("%s.%s=%s.%s %s",
|
||||
tables[len(tables)-1], foreignKey, from[len(from)-1], local, on,
|
||||
),
|
||||
})
|
||||
if ship.Middle != nil && ship.Middle.Middle != nil {
|
||||
return parseAfterJoin(tables[len(tables)-1], ids, qq, *ship.Middle)
|
||||
} else {
|
||||
from := strings.Split(qq.From, " ")
|
||||
ww, ok := qq.Where.(SqlBuilder)
|
||||
if ok {
|
||||
ww = append(ww, []string{fmt.Sprintf("%s.%s",
|
||||
tables[len(tables)-1], ship.Middle.ForeignKey), "in", ""},
|
||||
)
|
||||
qq.Where = ww
|
||||
}
|
||||
if qq.Fields == "" || qq.Fields == "*" {
|
||||
qq.Fields = str.Join(from[len(from)-1], ".", "*", ",", tables[len(tables)-1], ".", ship.Middle.ForeignKey)
|
||||
}
|
||||
qq.In = ids
|
||||
return ship.Middle.RelationType == HasMany
|
||||
}
|
||||
}
|
||||
|
||||
func Relation(isPlural bool, db dbQuery, ctx context.Context, r any, q *QueryCondition) ([]func(), []func() error) {
|
||||
var beforeFn []func()
|
||||
var afterFn []func() error
|
||||
qx := helper.GetContextVal(ctx, "ancestorsQueryCondition", q)
|
||||
|
||||
for _, f := range q.RelationFn {
|
||||
getVal, isJoin, qq, relationship := f()
|
||||
idFn, assignmentFn, rr, rrs, ship := relationship()
|
||||
if isJoin {
|
||||
beforeFn = append(beforeFn, func() {
|
||||
tables := strings.Split(ship.Table, " ")
|
||||
from := strings.Split(q.From, " ")
|
||||
on := ""
|
||||
if ship.On != "" {
|
||||
on = fmt.Sprintf("and %s", on)
|
||||
}
|
||||
qq := helper.GetContextVal(ctx, "ancestorsQueryCondition", q)
|
||||
qq.Join = append(qq.Join, []string{
|
||||
"left join", ship.Table, fmt.Sprintf("%s.%s=%s.%s %s", tables[len(tables)-1], ship.ForeignKey, from[len(from)-1], ship.Local, on)})
|
||||
parseBeforeJoin(qx, ship)
|
||||
})
|
||||
}
|
||||
if !getVal {
|
||||
|
@ -71,21 +126,26 @@ func Relation(isPlural bool, db dbQuery, ctx context.Context, r any, q *QueryCon
|
|||
Fields: "*",
|
||||
}
|
||||
}
|
||||
var w any = qq.Where
|
||||
if w == nil {
|
||||
w = SqlBuilder{}
|
||||
}
|
||||
ww, ok := w.(SqlBuilder)
|
||||
if ok {
|
||||
ww = append(ww, SqlBuilder{{
|
||||
ship.ForeignKey, "in", "",
|
||||
}}...)
|
||||
qq.In = [][]any{ids}
|
||||
qq.Where = ww
|
||||
}
|
||||
if qq.From == "" {
|
||||
qq.From = ship.Table
|
||||
}
|
||||
var w any = qq.Where
|
||||
if w == nil {
|
||||
qq.Where = SqlBuilder{}
|
||||
}
|
||||
ww, ok := qq.Where.(SqlBuilder)
|
||||
in := [][]any{ids}
|
||||
if ok {
|
||||
if ship.Middle != nil {
|
||||
isPlural = parseAfterJoin(qq.From, in, qq, ship)
|
||||
} else {
|
||||
ww = append(ww, SqlBuilder{{
|
||||
ship.ForeignKey, "in", "",
|
||||
}}...)
|
||||
qq.In = in
|
||||
qq.Where = ww
|
||||
}
|
||||
}
|
||||
err = ParseRelation(isPlural || ship.RelationType == HasMany, db, ctx, helper.Or(isPlural, rrs, rr), qq)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
|
|
|
@ -2,6 +2,7 @@ package model
|
|||
|
||||
import (
|
||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||
"github.com/fthvgb1/wp-go/helper/slice"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -15,6 +16,13 @@ type TermTaxonomy struct {
|
|||
Term *models.Terms
|
||||
}
|
||||
|
||||
type CommentMeta struct {
|
||||
MetaId uint64 `db:"meta_id"`
|
||||
CommentId uint64 `db:"comment_id"`
|
||||
MetaKey string `db:"meta_key"`
|
||||
MetaValue string `db:"meta_value"`
|
||||
}
|
||||
|
||||
var termMyHasOneTerm = RelationHasOne(func(m *TermTaxonomy) uint64 {
|
||||
return m.TermTaxonomyId
|
||||
}, func(p *models.Terms) uint64 {
|
||||
|
@ -117,6 +125,71 @@ func PostMetas() (func(any) []any, func(any, any), any, any, Relationship) {
|
|||
}
|
||||
}
|
||||
|
||||
var postHaveManyTerms = RelationHasMany(func(m *post) uint64 {
|
||||
return m.Id
|
||||
}, func(p *struct {
|
||||
ObjectId uint64 `db:"object_id"`
|
||||
models.Terms
|
||||
}) uint64 {
|
||||
return p.ObjectId
|
||||
}, func(m *post, i *[]struct {
|
||||
ObjectId uint64 `db:"object_id"`
|
||||
models.Terms
|
||||
}) {
|
||||
v := slice.Map(*i, func(t struct {
|
||||
ObjectId uint64 `db:"object_id"`
|
||||
models.Terms
|
||||
}) models.Terms {
|
||||
return t.Terms
|
||||
})
|
||||
m.Terms = &v
|
||||
}, Relationship{
|
||||
RelationType: HasOne,
|
||||
Table: "wp_terms",
|
||||
ForeignKey: "term_id",
|
||||
Local: "term_id",
|
||||
Middle: &Relationship{
|
||||
RelationType: HasOne,
|
||||
Table: "wp_term_taxonomy taxonomy",
|
||||
ForeignKey: "term_taxonomy_id",
|
||||
Local: "term_taxonomy_id",
|
||||
Middle: &Relationship{
|
||||
RelationType: HasMany,
|
||||
Table: "wp_term_relationships",
|
||||
ForeignKey: "object_id",
|
||||
Local: "ID",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
var postHaveManyCommentMetas = func() RelationFn {
|
||||
type metas struct {
|
||||
CommentPostID uint64 `db:"comment_post_ID"`
|
||||
CommentMeta
|
||||
}
|
||||
return RelationHasMany(func(m *post) uint64 {
|
||||
return m.Id
|
||||
}, func(p *metas) uint64 {
|
||||
return p.CommentPostID
|
||||
}, func(m *post, i *[]metas) {
|
||||
v := slice.Map(*i, func(t metas) CommentMeta {
|
||||
return t.CommentMeta
|
||||
})
|
||||
m.CommentMetas = &v
|
||||
}, Relationship{
|
||||
RelationType: HasOne,
|
||||
Table: "wp_commentmeta",
|
||||
ForeignKey: "comment_id",
|
||||
Local: "comment_ID",
|
||||
Middle: &Relationship{
|
||||
RelationType: HasMany,
|
||||
Table: "wp_comments comments",
|
||||
ForeignKey: "comment_post_ID",
|
||||
Local: "ID",
|
||||
},
|
||||
})
|
||||
}()
|
||||
|
||||
func Meta2() RelationFn {
|
||||
return RelationHasMany(postId, metasPostId, func(m *post, i *[]models.PostMeta) {
|
||||
m.PostMeta = i
|
||||
|
@ -156,7 +229,7 @@ func TestGets2(t *testing.T) {
|
|||
WithFn(true, false, nil, termMyHasOneTerm),
|
||||
), shipHasManyTermMy),
|
||||
), postHasManyShip),
|
||||
//WithFn(true, false, nil, term),
|
||||
WithFn(true, false, nil, postHaveManyTerms),
|
||||
)
|
||||
got, err := Gets[post](ctx, q)
|
||||
_ = got
|
||||
|
@ -169,7 +242,7 @@ func TestGets2(t *testing.T) {
|
|||
{
|
||||
q := Conditions(
|
||||
Where(SqlBuilder{{"posts.id", "in", ""}}),
|
||||
In([]any{190, 3022, 291}),
|
||||
In([]any{190, 3022, 291, 2858}),
|
||||
WithCtx(&ctx),
|
||||
WithFn(true, false, Conditions(
|
||||
Fields("ID,user_login,user_pass"),
|
||||
|
@ -177,12 +250,13 @@ func TestGets2(t *testing.T) {
|
|||
Fields("posts.*"),
|
||||
From("wp_posts posts"),
|
||||
WithFn(true, false, nil, Meta2()),
|
||||
WithFn(true, false, Conditions(
|
||||
/*WithFn(true, false, Conditions(
|
||||
WithFn(true, false, Conditions(
|
||||
WithFn(true, false, nil, termMyHasOneTerm),
|
||||
), shipHasManyTermMy),
|
||||
), postHasManyShip),
|
||||
//WithFn(true, false, nil, term),
|
||||
), postHasManyShip),*/
|
||||
WithFn(true, false, nil, postHaveManyTerms),
|
||||
WithFn(true, false, nil, postHaveManyCommentMetas),
|
||||
)
|
||||
got, err := Finds[post](ctx, q)
|
||||
_ = got
|
||||
|
|
Loading…
Reference in New Issue
Block a user