Merge remote-tracking branch 'upstream/master'
This commit is contained in:
		
						commit
						492c6ee070
					
				@ -125,33 +125,47 @@ func BuildQuerySQL(db *gorm.DB) {
 | 
			
		||||
						})
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					exprs := make([]clause.Expression, len(relation.References))
 | 
			
		||||
					for idx, ref := range relation.References {
 | 
			
		||||
						if ref.OwnPrimaryKey {
 | 
			
		||||
							exprs[idx] = clause.Eq{
 | 
			
		||||
								Column: clause.Column{Table: clause.CurrentTable, Name: ref.PrimaryKey.DBName},
 | 
			
		||||
								Value:  clause.Column{Table: tableAliasName, Name: ref.ForeignKey.DBName},
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							if ref.PrimaryValue == "" {
 | 
			
		||||
					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 {
 | 
			
		||||
								exprs[idx] = clause.Eq{
 | 
			
		||||
									Column: clause.Column{Table: clause.CurrentTable, Name: ref.ForeignKey.DBName},
 | 
			
		||||
									Value:  clause.Column{Table: tableAliasName, Name: ref.PrimaryKey.DBName},
 | 
			
		||||
									Column: clause.Column{Table: clause.CurrentTable, Name: ref.PrimaryKey.DBName},
 | 
			
		||||
									Value:  clause.Column{Table: tableAliasName, Name: ref.ForeignKey.DBName},
 | 
			
		||||
								}
 | 
			
		||||
							} else {
 | 
			
		||||
								exprs[idx] = clause.Eq{
 | 
			
		||||
									Column: clause.Column{Table: tableAliasName, Name: ref.ForeignKey.DBName},
 | 
			
		||||
									Value:  ref.PrimaryValue,
 | 
			
		||||
								if ref.PrimaryValue == "" {
 | 
			
		||||
									exprs[idx] = clause.Eq{
 | 
			
		||||
										Column: clause.Column{Table: clause.CurrentTable, Name: ref.ForeignKey.DBName},
 | 
			
		||||
										Value:  clause.Column{Table: tableAliasName, Name: ref.PrimaryKey.DBName},
 | 
			
		||||
									}
 | 
			
		||||
								} else {
 | 
			
		||||
									exprs[idx] = clause.Eq{
 | 
			
		||||
										Column: clause.Column{Table: tableAliasName, Name: ref.ForeignKey.DBName},
 | 
			
		||||
										Value:  ref.PrimaryValue,
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					joins = append(joins, clause.Join{
 | 
			
		||||
						Type:  clause.LeftJoin,
 | 
			
		||||
						Table: clause.Table{Name: relation.FieldSchema.Table, Alias: tableAliasName},
 | 
			
		||||
						ON:    clause.Where{Exprs: exprs},
 | 
			
		||||
					})
 | 
			
		||||
						joins = append(joins, clause.Join{
 | 
			
		||||
							Type:  clause.LeftJoin,
 | 
			
		||||
							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