Add method Raw and Scan

This commit is contained in:
Jinzhu 2014-01-03 18:14:51 +08:00
parent 3e24b14906
commit 8010616e89
5 changed files with 91 additions and 5 deletions

View File

@ -818,16 +818,42 @@ db.Debug().Where("name = ?", "jinzhu").First(&User{})
Row & Rows is not chainable, it works just like `QueryRow` and `Query`
```go
row := db.Where("name = ?", "jinzhu").select("name, age").Row() // (*sql.Row)
row := db.Table("users").Where("name = ?", "jinzhu").select("name, age").Row() // (*sql.Row)
row.Scan(&name, &age)
rows, err := db.Where("name = ?", "jinzhu").select("name, age, email").Rows() // (*sql.Rows, error)
rows, err := db.Model(User{}).Where("name = ?", "jinzhu").select("name, age, email").Rows() // (*sql.Rows, error)
defer rows.Close()
for rows.Next() {
...
rows.Scan(&name, &age, &email)
...
}
// Rows() with raw sql
rows, err := db.Raw("select name, age, email from users where name = ?", "jinzhu").Rows() // (*sql.Rows, error)
defer rows.Close()
for rows.Next() {
...
rows.Scan(&name, &age, &email)
...
}
```
## Scan
Scan sql results into strcut
```go
type Result struct {
Name string
Age int
}
var result Result
db.Table("users").Select("name, age").Where("name = ?", 3).Scan(&result)
// Scan raw sql
db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result)
```
## Group & Having

13
do.go
View File

@ -327,7 +327,11 @@ func (s *Do) delete() *Do {
}
func (s *Do) prepareQuerySql() {
if s.search.raw {
s.setSql(strings.TrimLeft(s.combinedSql(), "WHERE "))
} else {
s.setSql(fmt.Sprintf("SELECT %v FROM %v %v", s.selectSql(), s.table(), s.combinedSql()))
}
return
}
@ -398,13 +402,18 @@ func (s *Do) rows() (*sql.Rows, error) {
return s.db.db.Query(s.sql, s.sqlVars...)
}
func (s *Do) query() *Do {
func (s *Do) query(dests ...interface{}) *Do {
defer s.trace(time.Now())
var (
is_slice bool
dest_type reflect.Type
)
dest_out := reflect.Indirect(reflect.ValueOf(s.value))
var dest_out reflect.Value
if len(dests) > 0 {
dest_out = reflect.Indirect(reflect.ValueOf(dests[0]))
} else {
dest_out = reflect.Indirect(reflect.ValueOf(s.value))
}
if dest_out.Kind() == reflect.Slice {
is_slice = true

View File

@ -1527,6 +1527,42 @@ func TestRows(t *testing.T) {
}
}
type result struct {
Name string
Age int
}
func TestScan(t *testing.T) {
var res result
db.Table("users").Select("name, age").Where("name = ?", 3).Scan(&res)
if res.Name != "3" {
t.Errorf("Scan into struct should works")
}
var ress []result
db.Table("users").Select("name, age").Where("name = ?", 3).Scan(&ress)
if len(ress) != 2 || ress[0].Name != "3" || ress[1].Name != "3" {
t.Errorf("Scan into struct map")
}
}
func TestRaw(t *testing.T) {
var ress []result
db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&ress)
if len(ress) != 2 || ress[0].Name != "3" || ress[1].Name != "3" {
t.Errorf("Raw with scan")
}
rows, _ := db.Raw("select name, age from users where name = ?", 3).Rows()
count := 0
for rows.Next() {
count++
}
if count != 2 {
t.Errorf("Raw with Rows should find two records with name 3")
}
}
func TestGroup(t *testing.T) {
rows, err := db.Select("name").Table("users").Group("name").Rows()

View File

@ -128,6 +128,10 @@ func (s *DB) Rows() (*sql.Rows, error) {
return s.do(s.data).rows()
}
func (s *DB) Scan(dest interface{}) *DB {
return s.do(s.data).query(dest).db
}
func (s *DB) Attrs(attrs ...interface{}) *DB {
return s.clone().search.attrs(attrs...).db
}
@ -180,6 +184,10 @@ func (s *DB) Delete(value interface{}) *DB {
return s.clone().do(value).begin().delete().commit_or_rollback().db
}
func (s *DB) Raw(sql string, values ...interface{}) *DB {
return s.clone().search.setraw(true).where(sql, values...).db
}
func (s *DB) Exec(sql string, values ...interface{}) *DB {
return s.clone().do(nil).raw(sql, values...).exec().db
}

View File

@ -21,6 +21,7 @@ type search struct {
groupStr string
tableName string
unscope bool
raw bool
}
func (s *search) clone() *search {
@ -39,6 +40,7 @@ func (s *search) clone() *search {
groupStr: s.groupStr,
joinsStr: s.joinsStr,
tableName: s.tableName,
raw: s.raw,
}
}
@ -110,6 +112,11 @@ func (s *search) joins(query string) *search {
return s
}
func (s *search) setraw(b bool) *search {
s.raw = b
return s
}
func (s *search) unscoped() *search {
s.unscope = true
return s