2013-12-26 06:50:44 +00:00
package xorm
import (
"database/sql"
"fmt"
"reflect"
2014-02-11 06:59:04 +00:00
"github.com/lunny/xorm/core"
2013-12-26 06:50:44 +00:00
)
type Rows struct {
NoTypeCheck bool
2013-12-26 18:14:30 +00:00
session * Session
2014-02-11 06:59:04 +00:00
stmt * core . Stmt
rows * core . Rows
2013-12-26 18:14:30 +00:00
fields [ ] string
fieldsCount int
beanType reflect . Type
lastError error
2013-12-26 06:50:44 +00:00
}
func newRows ( session * Session , bean interface { } ) ( * Rows , error ) {
rows := new ( Rows )
rows . session = session
rows . beanType = reflect . Indirect ( reflect . ValueOf ( bean ) ) . Type ( )
err := rows . session . newDb ( )
if err != nil {
return nil , err
}
defer rows . session . Statement . Init ( )
2014-02-11 17:35:26 +00:00
var sqlStr string
2013-12-26 06:50:44 +00:00
var args [ ] interface { }
rows . session . Statement . RefTable = rows . session . Engine . autoMap ( bean )
if rows . session . Statement . RawSQL == "" {
2014-02-11 17:35:26 +00:00
sqlStr , args = rows . session . Statement . genGetSql ( bean )
2013-12-26 06:50:44 +00:00
} else {
2014-02-11 17:35:26 +00:00
sqlStr = rows . session . Statement . RawSQL
2013-12-26 06:50:44 +00:00
args = rows . session . Statement . RawParams
}
for _ , filter := range rows . session . Engine . Filters {
2014-02-11 17:35:26 +00:00
sqlStr = filter . Do ( sqlStr , session . Engine . dialect , rows . session . Statement . RefTable )
2013-12-26 06:50:44 +00:00
}
2014-02-11 17:35:26 +00:00
rows . session . Engine . logSQL ( sqlStr , args )
2013-12-26 06:50:44 +00:00
2014-02-11 17:35:26 +00:00
rows . stmt , err = rows . session . Db . Prepare ( sqlStr )
2013-12-26 06:50:44 +00:00
if err != nil {
rows . lastError = err
defer rows . Close ( )
return nil , err
}
rows . rows , err = rows . stmt . Query ( args ... )
if err != nil {
rows . lastError = err
defer rows . Close ( )
return nil , err
}
rows . fields , err = rows . rows . Columns ( )
if err != nil {
rows . lastError = err
defer rows . Close ( )
return nil , err
}
2013-12-26 18:14:30 +00:00
rows . fieldsCount = len ( rows . fields )
2013-12-26 06:50:44 +00:00
return rows , nil
}
// move cursor to next record, return false if end has reached
func ( rows * Rows ) Next ( ) bool {
if rows . lastError == nil && rows . rows != nil {
hasNext := rows . rows . Next ( )
if ! hasNext {
rows . lastError = sql . ErrNoRows
}
return hasNext
}
return false
}
// Err returns the error, if any, that was encountered during iteration. Err may be called after an explicit or implicit Close.
func ( rows * Rows ) Err ( ) error {
return rows . lastError
}
// scan row record to bean properties
func ( rows * Rows ) Scan ( bean interface { } ) error {
if rows . lastError != nil {
return rows . lastError
}
if ! rows . NoTypeCheck && reflect . Indirect ( reflect . ValueOf ( bean ) ) . Type ( ) != rows . beanType {
return fmt . Errorf ( "scan arg is incompatible type to [%v]" , rows . beanType )
}
2013-12-26 18:14:30 +00:00
return rows . session . row2Bean ( rows . rows , rows . fields , rows . fieldsCount , bean )
// result, err := row2map(rows.rows, rows.fields) // !nashtsai! TODO remove row2map then scanMapIntoStruct conversation for better performance
// if err == nil {
// err = rows.session.scanMapIntoStruct(bean, result)
// }
// return err
2013-12-26 06:50:44 +00:00
}
// // Columns returns the column names. Columns returns an error if the rows are closed, or if the rows are from QueryRow and there was a deferred error.
// func (rows *Rows) Columns() ([]string, error) {
// if rows.lastError == nil && rows.rows != nil {
// return rows.rows.Columns()
// }
// return nil, rows.lastError
// }
// close session if session.IsAutoClose is true, and claimed any opened resources
func ( rows * Rows ) Close ( ) error {
if rows . session . IsAutoClose {
defer rows . session . Close ( )
}
if rows . lastError == nil {
if rows . rows != nil {
rows . lastError = rows . rows . Close ( )
if rows . lastError != nil {
defer rows . stmt . Close ( )
return rows . lastError
}
}
if rows . stmt != nil {
rows . lastError = rows . stmt . Close ( )
}
} else {
if rows . stmt != nil {
defer rows . stmt . Close ( )
}
if rows . rows != nil {
defer rows . rows . Close ( )
}
}
return rows . lastError
}