diff --git a/main.go b/main.go index 82ec2a16..04f39228 100644 --- a/main.go +++ b/main.go @@ -166,7 +166,10 @@ func (s *DB) Offset(offset interface{}) *DB { } // Order specify order when retrieve records from database, set reorder to `true` to overwrite defined conditions -func (s *DB) Order(value string, reorder ...bool) *DB { +// db.Order("name DESC") +// db.Order("name DESC", true) // reorder +// db.Order(gorm.Expr("name = ? DESC", "first")) // sql expression +func (s *DB) Order(value interface{}, reorder ...bool) *DB { return s.clone().search.Order(value, reorder...).db } diff --git a/query_test.go b/query_test.go index 7dc3d91b..62f86ce9 100644 --- a/query_test.go +++ b/query_test.go @@ -307,6 +307,12 @@ func TestOrderAndPluck(t *testing.T) { DB.Save(&user1).Save(&user2).Save(&user3) scopedb := DB.Model(&User{}).Where("name like ?", "%OrderPluckUser%") + var user User + scopedb.Order(gorm.Expr("name = ? DESC", "OrderPluckUser2")).First(&user) + if user.Name != "OrderPluckUser2" { + t.Errorf("Order with sql expression") + } + var ages []int64 scopedb.Order("age desc").Pluck("age", &ages) if ages[0] != 20 { diff --git a/scope.go b/scope.go index f4a21548..0ecf43df 100644 --- a/scope.go +++ b/scope.go @@ -730,7 +730,15 @@ func (scope *Scope) orderSQL() string { var orders []string for _, order := range scope.Search.orders { - orders = append(orders, scope.quoteIfPossible(order)) + if str, ok := order.(string); ok { + orders = append(orders, scope.quoteIfPossible(str)) + } else if expr, ok := order.(*expr); ok { + exp := expr.expr + for _, arg := range expr.args { + exp = strings.Replace(exp, "?", scope.AddToVars(arg), 1) + } + orders = append(orders, exp) + } } return " ORDER BY " + strings.Join(orders, ",") } diff --git a/search.go b/search.go index 1cb577ad..8ddc5b29 100644 --- a/search.go +++ b/search.go @@ -13,7 +13,7 @@ type search struct { assignAttrs []interface{} selects map[string]interface{} omits []string - orders []string + orders []interface{} preload []searchPreload offset interface{} limit interface{} @@ -59,14 +59,12 @@ func (s *search) Assign(attrs ...interface{}) *search { return s } -func (s *search) Order(value string, reorder ...bool) *search { +func (s *search) Order(value interface{}, reorder ...bool) *search { if len(reorder) > 0 && reorder[0] { - if value != "" { - s.orders = []string{value} - } else { - s.orders = []string{} - } - } else if value != "" { + s.orders = []interface{}{} + } + + if value != nil { s.orders = append(s.orders, value) } return s