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))
 | 
										if join.On != nil {
 | 
				
			||||||
					for idx, ref := range relation.References {
 | 
											primaryFields := make([]clause.Column, len(relation.FieldSchema.PrimaryFieldDBNames))
 | 
				
			||||||
						if ref.OwnPrimaryKey {
 | 
											for idx, ref := range relation.FieldSchema.PrimaryFieldDBNames {
 | 
				
			||||||
							exprs[idx] = clause.Eq{
 | 
												primaryFields[idx] = clause.Column{Table: tableAliasName, Name: ref}
 | 
				
			||||||
								Column: clause.Column{Table: clause.CurrentTable, Name: ref.PrimaryKey.DBName},
 | 
											}
 | 
				
			||||||
								Value:  clause.Column{Table: tableAliasName, Name: ref.ForeignKey.DBName},
 | 
					
 | 
				
			||||||
							}
 | 
											exprs := db.Statement.BuildCondition("(?) = (?)", primaryFields, join.On)
 | 
				
			||||||
						} else {
 | 
											joins = append(joins, clause.Join{
 | 
				
			||||||
							if ref.PrimaryValue == "" {
 | 
												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{
 | 
													exprs[idx] = clause.Eq{
 | 
				
			||||||
									Column: clause.Column{Table: clause.CurrentTable, Name: ref.ForeignKey.DBName},
 | 
														Column: clause.Column{Table: clause.CurrentTable, Name: ref.PrimaryKey.DBName},
 | 
				
			||||||
									Value:  clause.Column{Table: tableAliasName, Name: ref.PrimaryKey.DBName},
 | 
														Value:  clause.Column{Table: tableAliasName, Name: ref.ForeignKey.DBName},
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								exprs[idx] = clause.Eq{
 | 
													if ref.PrimaryValue == "" {
 | 
				
			||||||
									Column: clause.Column{Table: tableAliasName, Name: ref.ForeignKey.DBName},
 | 
														exprs[idx] = clause.Eq{
 | 
				
			||||||
									Value:  ref.PrimaryValue,
 | 
															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{
 | 
											joins = append(joins, clause.Join{
 | 
				
			||||||
						Type:  clause.LeftJoin,
 | 
												Type:  clause.LeftJoin,
 | 
				
			||||||
						Table: clause.Table{Name: relation.FieldSchema.Table, Alias: tableAliasName},
 | 
												Table: clause.Table{Name: relation.FieldSchema.Table, Alias: tableAliasName},
 | 
				
			||||||
						ON:    clause.Where{Exprs: exprs},
 | 
												ON:    clause.Where{Exprs: exprs},
 | 
				
			||||||
					})
 | 
											})
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					joins = append(joins, clause.Join{
 | 
										joins = append(joins, clause.Join{
 | 
				
			||||||
						Expression: clause.NamedExpr{SQL: join.Name, Vars: join.Conds},
 | 
											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
 | 
					// Joins specify Joins conditions
 | 
				
			||||||
//     db.Joins("Account").Find(&user)
 | 
					//     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("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) {
 | 
					func (db *DB) Joins(query string, args ...interface{}) (tx *DB) {
 | 
				
			||||||
	tx = db.getInstance()
 | 
						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})
 | 
						tx.Statement.Joins = append(tx.Statement.Joins, join{Name: query, Conds: args})
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -50,6 +50,7 @@ type Statement struct {
 | 
				
			|||||||
type join struct {
 | 
					type join struct {
 | 
				
			||||||
	Name  string
 | 
						Name  string
 | 
				
			||||||
	Conds []interface{}
 | 
						Conds []interface{}
 | 
				
			||||||
 | 
						On    interface{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StatementModifier statement modifier interface
 | 
					// StatementModifier statement modifier interface
 | 
				
			||||||
 | 
				
			|||||||
@ -5,11 +5,11 @@ go 1.14
 | 
				
			|||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/google/uuid v1.3.0
 | 
						github.com/google/uuid v1.3.0
 | 
				
			||||||
	github.com/jinzhu/now v1.1.2
 | 
						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/mysql v1.1.2
 | 
				
			||||||
	gorm.io/driver/postgres v1.1.0
 | 
						gorm.io/driver/postgres v1.1.0
 | 
				
			||||||
	gorm.io/driver/sqlite v1.1.4
 | 
						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
 | 
						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) {
 | 
					func TestJoinsWithSelect(t *testing.T) {
 | 
				
			||||||
	type result struct {
 | 
						type result struct {
 | 
				
			||||||
		ID    uint
 | 
							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 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)
 | 
					// 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)
 | 
					// His pet also has one Toy (has one - polymorphic)
 | 
				
			||||||
 | 
					// NamedPet is a reference to a Named `Pets` (has many)
 | 
				
			||||||
type User struct {
 | 
					type User struct {
 | 
				
			||||||
	gorm.Model
 | 
						gorm.Model
 | 
				
			||||||
	Name      string
 | 
						Name      string
 | 
				
			||||||
@ -18,6 +19,7 @@ type User struct {
 | 
				
			|||||||
	Birthday  *time.Time
 | 
						Birthday  *time.Time
 | 
				
			||||||
	Account   Account
 | 
						Account   Account
 | 
				
			||||||
	Pets      []*Pet
 | 
						Pets      []*Pet
 | 
				
			||||||
 | 
						NamedPet  *Pet
 | 
				
			||||||
	Toys      []Toy `gorm:"polymorphic:Owner"`
 | 
						Toys      []Toy `gorm:"polymorphic:Owner"`
 | 
				
			||||||
	CompanyID *int
 | 
						CompanyID *int
 | 
				
			||||||
	Company   Company
 | 
						Company   Company
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user