github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/go-xorm/xorm/rows.go (about) 1 // Copyright 2015 The Xorm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package xorm 6 7 import ( 8 "database/sql" 9 "fmt" 10 "reflect" 11 12 "github.com/insionng/yougam/libraries/go-xorm/core" 13 ) 14 15 // Rows rows wrapper a rows to 16 type Rows struct { 17 NoTypeCheck bool 18 19 session *Session 20 stmt *core.Stmt 21 rows *core.Rows 22 fields []string 23 fieldsCount int 24 beanType reflect.Type 25 lastError error 26 } 27 28 func newRows(session *Session, bean interface{}) (*Rows, error) { 29 rows := new(Rows) 30 rows.session = session 31 rows.beanType = reflect.Indirect(reflect.ValueOf(bean)).Type() 32 33 defer rows.session.resetStatement() 34 35 var sqlStr string 36 var args []interface{} 37 38 rows.session.Statement.setRefValue(rValue(bean)) 39 if len(session.Statement.TableName()) <= 0 { 40 return nil, ErrTableNotFound 41 } 42 43 if rows.session.Statement.RawSQL == "" { 44 sqlStr, args = rows.session.Statement.genGetSQL(bean) 45 } else { 46 sqlStr = rows.session.Statement.RawSQL 47 args = rows.session.Statement.RawParams 48 } 49 50 for _, filter := range rows.session.Engine.dialect.Filters() { 51 sqlStr = filter.Do(sqlStr, session.Engine.dialect, rows.session.Statement.RefTable) 52 } 53 54 rows.session.saveLastSQL(sqlStr, args...) 55 var err error 56 if rows.session.prepareStmt { 57 rows.stmt, err = rows.session.DB().Prepare(sqlStr) 58 if err != nil { 59 rows.lastError = err 60 rows.Close() 61 return nil, err 62 } 63 64 rows.rows, err = rows.stmt.Query(args...) 65 if err != nil { 66 rows.lastError = err 67 rows.Close() 68 return nil, err 69 } 70 } else { 71 rows.rows, err = rows.session.DB().Query(sqlStr, args...) 72 if err != nil { 73 rows.lastError = err 74 rows.Close() 75 return nil, err 76 } 77 } 78 79 rows.fields, err = rows.rows.Columns() 80 if err != nil { 81 rows.lastError = err 82 rows.Close() 83 return nil, err 84 } 85 rows.fieldsCount = len(rows.fields) 86 87 return rows, nil 88 } 89 90 // Next move cursor to next record, return false if end has reached 91 func (rows *Rows) Next() bool { 92 if rows.lastError == nil && rows.rows != nil { 93 hasNext := rows.rows.Next() 94 if !hasNext { 95 rows.lastError = sql.ErrNoRows 96 } 97 return hasNext 98 } 99 return false 100 } 101 102 // Err returns the error, if any, that was encountered during iteration. Err may be called after an explicit or implicit Close. 103 func (rows *Rows) Err() error { 104 return rows.lastError 105 } 106 107 // Scan row record to bean properties 108 func (rows *Rows) Scan(bean interface{}) error { 109 if rows.lastError != nil { 110 return rows.lastError 111 } 112 113 if !rows.NoTypeCheck && reflect.Indirect(reflect.ValueOf(bean)).Type() != rows.beanType { 114 return fmt.Errorf("scan arg is incompatible type to [%v]", rows.beanType) 115 } 116 117 return rows.session.row2Bean(rows.rows, rows.fields, rows.fieldsCount, bean) 118 } 119 120 // Close session if session.IsAutoClose is true, and claimed any opened resources 121 func (rows *Rows) Close() error { 122 if rows.session.IsAutoClose { 123 defer rows.session.Close() 124 } 125 126 if rows.lastError == nil { 127 if rows.rows != nil { 128 rows.lastError = rows.rows.Close() 129 if rows.lastError != nil { 130 defer rows.stmt.Close() 131 return rows.lastError 132 } 133 } 134 if rows.stmt != nil { 135 rows.lastError = rows.stmt.Close() 136 } 137 } else { 138 if rows.stmt != nil { 139 defer rows.stmt.Close() 140 } 141 if rows.rows != nil { 142 defer rows.rows.Close() 143 } 144 } 145 return rows.lastError 146 }