diff --git a/README.md b/README.md index 01075d7d..972fecd1 100644 --- a/README.md +++ b/README.md @@ -118,11 +118,23 @@ db.Save(&user) ```go // Get the first record db.First(&user) -//// SELECT * FROM users LIMIT 1; +//// SELECT * FROM users ORDER BY id LIMIT 1; // Search table `users` are guessed from the out struct type. // You are possible to specify the table name with Model() if no out struct for some methods like Pluck() // Or set table name with Table(), if so, it will ignore the out struct even have it. more details following. +// Get the last record +db.Last(&user) +//// SELECT * FROM users ORDER BY id DESC LIMIT 1; + +// Get a record without order by primary key +db.Find(&user) +//// SELECT * FROM users LIMIT 1; + +// Get first record as map +db.First(&users) +//// SELECT * FROM users LIMIT 1; + // Get All records db.Find(&users) //// SELECT * FROM users; diff --git a/chain.go b/chain.go index 762fc7f3..1b05e564 100644 --- a/chain.go +++ b/chain.go @@ -175,9 +175,12 @@ func (s *Chain) Exec(sql string) *Chain { } func (s *Chain) First(out interface{}, where ...interface{}) *Chain { - do := s.do(out) - do.limitStr = "1" - do.where(where...).query() + s.do(out).where(where...).first() + return s +} + +func (s *Chain) Last(out interface{}, where ...interface{}) *Chain { + s.do(out).where(where...).last() return s } diff --git a/do.go b/do.go index c9086152..cd96a729 100644 --- a/do.go +++ b/do.go @@ -287,6 +287,18 @@ func (s *Do) prepareQuerySql() { return } +func (s *Do) first() { + s.limitStr = "1" + s.orderStrs = append(s.orderStrs, s.model.primaryKeyDb()) + s.query() +} + +func (s *Do) last() { + s.limitStr = "1" + s.orderStrs = append(s.orderStrs, s.model.primaryKeyDb()+" DESC") + s.query() +} + func (s *Do) query() { var ( is_slice bool @@ -297,6 +309,8 @@ func (s *Do) query() { if dest_out.Kind() == reflect.Slice { is_slice = true dest_type = dest_out.Type().Elem() + } else { + s.limitStr = "1" } s.prepareQuerySql() diff --git a/gorm_test.go b/gorm_test.go index 1a11aa25..c772ce9b 100644 --- a/gorm_test.go +++ b/gorm_test.go @@ -117,6 +117,23 @@ func TestSaveAndFind(t *testing.T) { db.Find(&users) } +func TestFirstAndLast(t *testing.T) { + var user1, user2, user3, user4 User + db.First(&user1) + db.Order("id").Find(&user2) + db.Last(&user3) + db.Order("id desc").Find(&user4) + if user1.Id != user2.Id || user3.Id != user4.Id { + t.Errorf("First and Last should works correctly") + } + + var users []User + db.First(&users) + if len(users) != 1 { + t.Errorf("Find first record as map") + } +} + func TestSaveAndUpdate(t *testing.T) { name, name2, new_name := "update", "update2", "new_update" user := User{Name: name, Age: 1} diff --git a/main.go b/main.go index 84aef79b..9eb91f66 100644 --- a/main.go +++ b/main.go @@ -34,6 +34,10 @@ func (s *DB) First(out interface{}, where ...interface{}) *Chain { return s.buildChain().First(out, where...) } +func (s *DB) Last(out interface{}, where ...interface{}) *Chain { + return s.buildChain().Last(out, where...) +} + func (s *DB) Attrs(attrs ...interface{}) *Chain { return s.buildChain().Attrs(attrs...) }