Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
492c6ee070
@ -125,6 +125,19 @@ func BuildQuerySQL(db *gorm.DB) {
|
||||
})
|
||||
}
|
||||
|
||||
if join.On != nil {
|
||||
primaryFields := make([]clause.Column, len(relation.FieldSchema.PrimaryFieldDBNames))
|
||||
for idx, ref := range relation.FieldSchema.PrimaryFieldDBNames {
|
||||
primaryFields[idx] = clause.Column{Table: tableAliasName, Name: ref}
|
||||
}
|
||||
|
||||
exprs := db.Statement.BuildCondition("(?) = (?)", primaryFields, join.On)
|
||||
joins = append(joins, clause.Join{
|
||||
Type: clause.LeftJoin,
|
||||
Table: clause.Table{Name: relation.FieldSchema.Table, Alias: tableAliasName},
|
||||
ON: clause.Where{Exprs: exprs},
|
||||
})
|
||||
} else {
|
||||
exprs := make([]clause.Expression, len(relation.References))
|
||||
for idx, ref := range relation.References {
|
||||
if ref.OwnPrimaryKey {
|
||||
@ -152,6 +165,7 @@ func BuildQuerySQL(db *gorm.DB) {
|
||||
Table: clause.Table{Name: relation.FieldSchema.Table, Alias: tableAliasName},
|
||||
ON: clause.Where{Exprs: exprs},
|
||||
})
|
||||
}
|
||||
} else {
|
||||
joins = append(joins, clause.Join{
|
||||
Expression: clause.NamedExpr{SQL: join.Name, Vars: join.Conds},
|
||||
|
@ -171,8 +171,17 @@ func (db *DB) Or(query interface{}, args ...interface{}) (tx *DB) {
|
||||
// Joins specify Joins conditions
|
||||
// db.Joins("Account").Find(&user)
|
||||
// db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Find(&user)
|
||||
// db.Joins("Account", DB.Select("id").Where("user_id = users.id AND name = ?", "someName").Model(&Account{}))
|
||||
func (db *DB) Joins(query string, args ...interface{}) (tx *DB) {
|
||||
tx = db.getInstance()
|
||||
|
||||
if len(args) > 0 {
|
||||
if db, ok := args[0].(*DB); ok {
|
||||
tx.Statement.Joins = append(tx.Statement.Joins, join{Name: query, Conds: args[1:], On: db})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
tx.Statement.Joins = append(tx.Statement.Joins, join{Name: query, Conds: args})
|
||||
return
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ type Statement struct {
|
||||
type join struct {
|
||||
Name string
|
||||
Conds []interface{}
|
||||
On interface{}
|
||||
}
|
||||
|
||||
// StatementModifier statement modifier interface
|
||||
|
@ -5,11 +5,11 @@ go 1.14
|
||||
require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/jinzhu/now v1.1.2
|
||||
github.com/lib/pq v1.10.2
|
||||
github.com/lib/pq v1.10.3
|
||||
gorm.io/driver/mysql v1.1.2
|
||||
gorm.io/driver/postgres v1.1.0
|
||||
gorm.io/driver/sqlite v1.1.4
|
||||
gorm.io/driver/sqlserver v1.0.8
|
||||
gorm.io/driver/sqlserver v1.0.9
|
||||
gorm.io/gorm v1.21.14
|
||||
)
|
||||
|
||||
|
@ -104,6 +104,26 @@ func TestJoinConds(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestJoinOn(t *testing.T) {
|
||||
var user = *GetUser("joins-on", Config{Pets: 2})
|
||||
DB.Save(&user)
|
||||
|
||||
var user1 User
|
||||
onQuery := DB.Select("id").Where("user_id = users.id AND name = ?", "joins-on_pet_1").Model(&Pet{})
|
||||
|
||||
if err := DB.Joins("NamedPet", onQuery).Where("users.name = ?", user.Name).First(&user1).Error; err != nil {
|
||||
t.Fatalf("Failed to load with joins on, got error: %v", err)
|
||||
}
|
||||
AssertEqual(t, user1.NamedPet.Name, "joins-on_pet_1")
|
||||
|
||||
onQuery2 := DB.Select("id").Where("user_id = users.id AND name = ?", "joins-on_pet_2").Model(&Pet{})
|
||||
var user2 User
|
||||
if err := DB.Joins("NamedPet", onQuery2).Where("users.name = ?", user.Name).First(&user2).Error; err != nil {
|
||||
t.Fatalf("Failed to load with joins on, got error: %v", err)
|
||||
}
|
||||
AssertEqual(t, user2.NamedPet.Name, "joins-on_pet_2")
|
||||
}
|
||||
|
||||
func TestJoinsWithSelect(t *testing.T) {
|
||||
type result struct {
|
||||
ID uint
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
// He works in a Company (belongs to), he has a Manager (belongs to - single-table), and also managed a Team (has many - single-table)
|
||||
// He speaks many languages (many to many) and has many friends (many to many - single-table)
|
||||
// His pet also has one Toy (has one - polymorphic)
|
||||
// NamedPet is a reference to a Named `Pets` (has many)
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
@ -18,6 +19,7 @@ type User struct {
|
||||
Birthday *time.Time
|
||||
Account Account
|
||||
Pets []*Pet
|
||||
NamedPet *Pet
|
||||
Toys []Toy `gorm:"polymorphic:Owner"`
|
||||
CompanyID *int
|
||||
Company Company
|
||||
|
Loading…
x
Reference in New Issue
Block a user