Refactor Join ON
This commit is contained in:
		
							parent
							
								
									ba16b2368f
								
							
						
					
					
						commit
						a16db07945
					
				| @ -125,47 +125,48 @@ func BuildQuerySQL(db *gorm.DB) { | |||||||
| 						}) | 						}) | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					if join.On != nil { | 					exprs := make([]clause.Expression, len(relation.References)) | ||||||
| 						primaryFields := make([]clause.Column, len(relation.FieldSchema.PrimaryFieldDBNames)) | 					for idx, ref := range relation.References { | ||||||
| 						for idx, ref := range relation.FieldSchema.PrimaryFieldDBNames { | 						if ref.OwnPrimaryKey { | ||||||
| 							primaryFields[idx] = clause.Column{Table: tableAliasName, Name: ref} | 							exprs[idx] = clause.Eq{ | ||||||
| 						} | 								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) | 							} | ||||||
| 						joins = append(joins, clause.Join{ | 						} else { | ||||||
| 							Type:  clause.LeftJoin, | 							if ref.PrimaryValue == "" { | ||||||
| 							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.PrimaryKey.DBName}, | 									Column: clause.Column{Table: clause.CurrentTable, Name: ref.ForeignKey.DBName}, | ||||||
| 									Value:  clause.Column{Table: tableAliasName, Name: ref.ForeignKey.DBName}, | 									Value:  clause.Column{Table: tableAliasName, Name: ref.PrimaryKey.DBName}, | ||||||
| 								} | 								} | ||||||
| 							} else { | 							} else { | ||||||
| 								if ref.PrimaryValue == "" { | 								exprs[idx] = clause.Eq{ | ||||||
| 									exprs[idx] = clause.Eq{ | 									Column: clause.Column{Table: tableAliasName, Name: ref.ForeignKey.DBName}, | ||||||
| 										Column: clause.Column{Table: clause.CurrentTable, Name: ref.ForeignKey.DBName}, | 									Value:  ref.PrimaryValue, | ||||||
| 										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}, |  | ||||||
| 						}) |  | ||||||
| 					} | 					} | ||||||
|  | 
 | ||||||
|  | 					if join.On != nil { | ||||||
|  | 						onStmt := gorm.Statement{Table: tableAliasName, DB: db} | ||||||
|  | 						join.On.Build(&onStmt) | ||||||
|  | 						onSQL := onStmt.SQL.String() | ||||||
|  | 						vars := onStmt.Vars | ||||||
|  | 						for idx, v := range onStmt.Vars { | ||||||
|  | 							bindvar := strings.Builder{} | ||||||
|  | 							onStmt.Vars = vars[0 : idx+1] | ||||||
|  | 							db.Dialector.BindVarTo(&bindvar, &onStmt, v) | ||||||
|  | 							onSQL = strings.Replace(onSQL, bindvar.String(), "?", 1) | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 						exprs = append(exprs, clause.Expr{SQL: onSQL, Vars: vars}) | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					joins = append(joins, clause.Join{ | ||||||
|  | 						Type:  clause.LeftJoin, | ||||||
|  | 						Table: clause.Table{Name: relation.FieldSchema.Table, Alias: tableAliasName}, | ||||||
|  | 						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}, | ||||||
|  | |||||||
| @ -177,7 +177,9 @@ func (db *DB) Joins(query string, args ...interface{}) (tx *DB) { | |||||||
| 
 | 
 | ||||||
| 	if len(args) > 0 { | 	if len(args) > 0 { | ||||||
| 		if db, ok := args[0].(*DB); ok { | 		if db, ok := args[0].(*DB); ok { | ||||||
| 			tx.Statement.Joins = append(tx.Statement.Joins, join{Name: query, Conds: args[1:], On: db}) | 			if where, ok := db.Statement.Clauses["WHERE"].Expression.(clause.Where); ok { | ||||||
|  | 				tx.Statement.Joins = append(tx.Statement.Joins, join{Name: query, Conds: args[1:], On: &where}) | ||||||
|  | 			} | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -50,7 +50,7 @@ type Statement struct { | |||||||
| type join struct { | type join struct { | ||||||
| 	Name  string | 	Name  string | ||||||
| 	Conds []interface{} | 	Conds []interface{} | ||||||
| 	On    interface{} | 	On    *clause.Where | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // StatementModifier statement modifier interface
 | // StatementModifier statement modifier interface
 | ||||||
|  | |||||||
| @ -109,14 +109,15 @@ func TestJoinOn(t *testing.T) { | |||||||
| 	DB.Save(&user) | 	DB.Save(&user) | ||||||
| 
 | 
 | ||||||
| 	var user1 User | 	var user1 User | ||||||
| 	onQuery := DB.Select("id").Where("user_id = users.id AND name = ?", "joins-on_pet_1").Model(&Pet{}) | 	onQuery := DB.Where(&Pet{Name: "joins-on_pet_1"}) | ||||||
| 
 | 
 | ||||||
| 	if err := DB.Joins("NamedPet", onQuery).Where("users.name = ?", user.Name).First(&user1).Error; err != nil { | 	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) | 		t.Fatalf("Failed to load with joins on, got error: %v", err) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	AssertEqual(t, user1.NamedPet.Name, "joins-on_pet_1") | 	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{}) | 	onQuery2 := DB.Where(&Pet{Name: "joins-on_pet_2"}) | ||||||
| 	var user2 User | 	var user2 User | ||||||
| 	if err := DB.Joins("NamedPet", onQuery2).Where("users.name = ?", user.Name).First(&user2).Error; err != nil { | 	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) | 		t.Fatalf("Failed to load with joins on, got error: %v", err) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user