Joins support parameters, close #673

This commit is contained in:
Jinzhu 2016-02-16 22:48:26 +08:00
parent 5883c70478
commit 115789960a
5 changed files with 26 additions and 14 deletions

View File

@ -929,7 +929,7 @@ db.Table("users").Select("users.name, emails.email").Joins("left join emails on
db.Joins("inner join emails on emails.user_id = users.id").Where("emails.email = ?", "x@example.org").Find(&user) db.Joins("inner join emails on emails.user_id = users.id").Where("emails.email = ?", "x@example.org").Find(&user)
// find all email addresses for a user // find all email addresses for a user
db.Joins("left join users on users.id = emails.user_id").Where("users.name = ?", "jinzhu").Find(&emails) db.Joins("LEFT JOIN users ON users.id = emails.user_id AND users.name = ?", "jinzhu").Find(&emails)
``` ```
## Transactions ## Transactions

View File

@ -171,8 +171,8 @@ func (s *DB) Having(query string, values ...interface{}) *DB {
return s.clone().search.Having(query, values...).db return s.clone().search.Having(query, values...).db
} }
func (s *DB) Joins(query string) *DB { func (s *DB) Joins(query string, args ...interface{}) *DB {
return s.clone().search.Joins(query).db return s.clone().search.Joins(query, args...).db
} }
func (s *DB) Scopes(funcs ...func(*DB) *DB) *DB { func (s *DB) Scopes(funcs ...func(*DB) *DB) *DB {

View File

@ -506,10 +506,16 @@ func TestJoins(t *testing.T) {
} }
DB.Save(&user) DB.Save(&user)
var result User var users1 []User
DB.Joins("left join emails on emails.user_id = users.id").Where("name = ?", "joins").First(&result) DB.Joins("left join emails on emails.user_id = users.id").Where("name = ?", "joins").Find(&users1)
if result.Name != "joins" || result.Id != user.Id { if len(users1) != 2 {
t.Errorf("Should find all two emails with Join") t.Errorf("should find two users using left join")
}
var users2 []User
DB.Joins("left join emails on emails.user_id = users.id AND emails.email = ?", "join1@example.com").Where("name = ?", "joins").First(&users2)
if len(users2) != 1 {
t.Errorf("should find one users using left join with conditions")
} }
} }

View File

@ -234,7 +234,7 @@ var hasCountRegexp = regexp.MustCompile(`(?i)count\(.+\)`)
func (scope *Scope) selectSql() string { func (scope *Scope) selectSql() string {
if len(scope.Search.selects) == 0 { if len(scope.Search.selects) == 0 {
if scope.Search.joins != "" { if len(scope.Search.joinConditions) > 0 {
return fmt.Sprintf("%v.*", scope.QuotedTableName()) return fmt.Sprintf("%v.*", scope.QuotedTableName())
} }
return "*" return "*"
@ -263,12 +263,11 @@ func (scope *Scope) groupSql() string {
} }
func (scope *Scope) havingSql() string { func (scope *Scope) havingSql() string {
if scope.Search.havingConditions == nil { if len(scope.Search.havingConditions) == 0 {
return "" return ""
} }
var andConditions []string var andConditions []string
for _, clause := range scope.Search.havingConditions { for _, clause := range scope.Search.havingConditions {
if sql := scope.buildWhereCondition(clause); sql != "" { if sql := scope.buildWhereCondition(clause); sql != "" {
andConditions = append(andConditions, sql) andConditions = append(andConditions, sql)
@ -284,7 +283,14 @@ func (scope *Scope) havingSql() string {
} }
func (scope *Scope) joinsSql() string { func (scope *Scope) joinsSql() string {
return scope.Search.joins + " " var joinConditions []string
for _, clause := range scope.Search.joinConditions {
if sql := scope.buildWhereCondition(clause); sql != "" {
joinConditions = append(joinConditions, strings.TrimSuffix(strings.TrimPrefix(sql, "("), ")"))
}
}
return strings.Join(joinConditions, " ") + " "
} }
func (scope *Scope) prepareQuerySql() { func (scope *Scope) prepareQuerySql() {

View File

@ -8,12 +8,12 @@ type search struct {
orConditions []map[string]interface{} orConditions []map[string]interface{}
notConditions []map[string]interface{} notConditions []map[string]interface{}
havingConditions []map[string]interface{} havingConditions []map[string]interface{}
joinConditions []map[string]interface{}
initAttrs []interface{} initAttrs []interface{}
assignAttrs []interface{} assignAttrs []interface{}
selects map[string]interface{} selects map[string]interface{}
omits []string omits []string
orders []string orders []string
joins string
preload []searchPreload preload []searchPreload
offset int offset int
limit int limit int
@ -102,8 +102,8 @@ func (s *search) Having(query string, values ...interface{}) *search {
return s return s
} }
func (s *search) Joins(query string) *search { func (s *search) Joins(query string, values ...interface{}) *search {
s.joins = query s.joinConditions = append(s.joinConditions, map[string]interface{}{"query": query, "args": values})
return s return s
} }