Complete the design and implementation of generic version Join
This commit is contained in:
parent
7095605cd0
commit
05925b2fc0
@ -448,9 +448,10 @@ func (db *DB) Assign(attrs ...interface{}) (tx *DB) {
|
||||
// Unscoped allows queries to include records marked as deleted,
|
||||
// overriding the soft deletion behavior.
|
||||
// Example:
|
||||
// var users []User
|
||||
// db.Unscoped().Find(&users)
|
||||
// // Retrieves all users, including deleted ones.
|
||||
//
|
||||
// var users []User
|
||||
// db.Unscoped().Find(&users)
|
||||
// // Retrieves all users, including deleted ones.
|
||||
func (db *DB) Unscoped() (tx *DB) {
|
||||
tx = db.getInstance()
|
||||
tx.Statement.Unscoped = true
|
||||
|
@ -11,6 +11,30 @@ const (
|
||||
RightJoin JoinType = "RIGHT"
|
||||
)
|
||||
|
||||
type JoinTarget struct {
|
||||
Type JoinType
|
||||
Association string
|
||||
Subquery Expression
|
||||
Table string
|
||||
}
|
||||
|
||||
func Has(name string) JoinTarget {
|
||||
return JoinTarget{Type: LeftJoin, Association: name}
|
||||
}
|
||||
|
||||
func (jt JoinType) Association(name string) JoinTarget {
|
||||
return JoinTarget{Type: jt, Association: name}
|
||||
}
|
||||
|
||||
func (jt JoinType) Subquery(subquery Expression) JoinTarget {
|
||||
return JoinTarget{Type: jt, Subquery: subquery}
|
||||
}
|
||||
|
||||
func (jt JoinTarget) As(name string) JoinTarget {
|
||||
jt.Table = name
|
||||
return jt
|
||||
}
|
||||
|
||||
// Join clause for from
|
||||
type Join struct {
|
||||
Type JoinType
|
||||
|
16
generics.go
16
generics.go
@ -28,8 +28,7 @@ type ChainInterface[T any] interface {
|
||||
Or(query interface{}, args ...interface{}) ChainInterface[T]
|
||||
Limit(offset int) ChainInterface[T]
|
||||
Offset(offset int) ChainInterface[T]
|
||||
Joins(query string, args ...interface{}) ChainInterface[T]
|
||||
InnerJoins(query string, args ...interface{}) ChainInterface[T]
|
||||
Joins(query clause.JoinTarget, args func(db ChainInterface[any], joinTable clause.Table, curTable clause.Table) ChainInterface[any]) ChainInterface[T]
|
||||
Select(query string, args ...interface{}) ChainInterface[T]
|
||||
Omit(columns ...string) ChainInterface[T]
|
||||
MapColumns(m map[string]string) ChainInterface[T]
|
||||
@ -186,16 +185,9 @@ func (c chainG[T]) Offset(offset int) ChainInterface[T] {
|
||||
})
|
||||
}
|
||||
|
||||
func (c chainG[T]) Joins(query string, args ...interface{}) ChainInterface[T] {
|
||||
return c.with(func(db *DB) *DB {
|
||||
return db.Joins(query, args...)
|
||||
})
|
||||
}
|
||||
|
||||
func (c chainG[T]) InnerJoins(query string, args ...interface{}) ChainInterface[T] {
|
||||
return c.with(func(db *DB) *DB {
|
||||
return db.InnerJoins(query, args...)
|
||||
})
|
||||
func (c chainG[T]) Joins(query clause.JoinTarget, args func(db ChainInterface[any], joinTable clause.Table, curTable clause.Table) ChainInterface[any]) ChainInterface[T] {
|
||||
// TODO
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c chainG[T]) Select(query string, args ...interface{}) ChainInterface[T] {
|
||||
|
@ -285,7 +285,9 @@ func TestGenericsJoinsAndPreload(t *testing.T) {
|
||||
db.Create(ctx, &u)
|
||||
|
||||
// LEFT JOIN + WHERE
|
||||
result, err := db.Joins("Company").Where("?.name = ?", clause.JoinTable("Company"), u.Company.Name).First(ctx)
|
||||
result, err := db.Joins(clause.Has("Company"), func(db gorm.ChainInterface[any], joinTable clause.Table, curTable clause.Table) gorm.ChainInterface[any] {
|
||||
return db.Where("?.name = ?", joinTable, u.Company.Name)
|
||||
}).First(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Joins failed: %v", err)
|
||||
}
|
||||
@ -293,13 +295,26 @@ func TestGenericsJoinsAndPreload(t *testing.T) {
|
||||
t.Fatalf("Joins expected %s, got %+v", u.Name, result)
|
||||
}
|
||||
|
||||
// INNER JOIN + Inline WHERE
|
||||
result2, err := db.InnerJoins("Company", "?.name = ?", clause.JoinTable("Company"), u.Company.Name).First(ctx)
|
||||
// JOIN
|
||||
result, err = db.Joins(clause.Has("Company"), func(db gorm.ChainInterface[any], joinTable clause.Table, curTable clause.Table) gorm.ChainInterface[any] {
|
||||
return nil
|
||||
}).First(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("InnerJoins failed: %v", err)
|
||||
t.Fatalf("Joins failed: %v", err)
|
||||
}
|
||||
if result2.Name != u.Name || result2.Company.Name != u.Company.Name {
|
||||
t.Errorf("InnerJoins expected , got %+v", result2)
|
||||
if result.Name != u.Name || result.Company.Name != u.Company.Name {
|
||||
t.Fatalf("Joins expected %s, got %+v", u.Name, result)
|
||||
}
|
||||
|
||||
// Left JOIN
|
||||
result, err = db.Joins(clause.LeftJoin.Association("Company").As("t"), func(db gorm.ChainInterface[any], joinTable clause.Table, curTable clause.Table) gorm.ChainInterface[any] {
|
||||
return nil
|
||||
}).First(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Joins failed: %v", err)
|
||||
}
|
||||
if result.Name != u.Name || result.Company.Name != u.Company.Name {
|
||||
t.Fatalf("Joins expected %s, got %+v", u.Name, result)
|
||||
}
|
||||
|
||||
// Preload
|
||||
|
@ -29,8 +29,8 @@ require (
|
||||
github.com/microsoft/go-mssqldb v1.8.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
golang.org/x/crypto v0.37.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/crypto v0.38.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user