github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/go-xorm/core/rows.go (about) 1 package core 2 3 import ( 4 "database/sql" 5 "errors" 6 "reflect" 7 "sync" 8 ) 9 10 type Rows struct { 11 *sql.Rows 12 Mapper IMapper 13 } 14 15 func (rs *Rows) ToMapString() ([]map[string]string, error) { 16 cols, err := rs.Columns() 17 if err != nil { 18 return nil, err 19 } 20 21 var results = make([]map[string]string, 0, 10) 22 for rs.Next() { 23 var record = make(map[string]string, len(cols)) 24 err = rs.ScanMap(&record) 25 if err != nil { 26 return nil, err 27 } 28 results = append(results, record) 29 } 30 return results, nil 31 } 32 33 // scan data to a struct's pointer according field index 34 func (rs *Rows) ScanStructByIndex(dest ...interface{}) error { 35 if len(dest) == 0 { 36 return errors.New("at least one struct") 37 } 38 39 vvvs := make([]reflect.Value, len(dest)) 40 for i, s := range dest { 41 vv := reflect.ValueOf(s) 42 if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { 43 return errors.New("dest should be a struct's pointer") 44 } 45 46 vvvs[i] = vv.Elem() 47 } 48 49 cols, err := rs.Columns() 50 if err != nil { 51 return err 52 } 53 newDest := make([]interface{}, len(cols)) 54 55 var i = 0 56 for _, vvv := range vvvs { 57 for j := 0; j < vvv.NumField(); j++ { 58 newDest[i] = vvv.Field(j).Addr().Interface() 59 i = i + 1 60 } 61 } 62 63 return rs.Rows.Scan(newDest...) 64 } 65 66 var ( 67 fieldCache = make(map[reflect.Type]map[string]int) 68 fieldCacheMutex sync.RWMutex 69 ) 70 71 func fieldByName(v reflect.Value, name string) reflect.Value { 72 t := v.Type() 73 fieldCacheMutex.RLock() 74 cache, ok := fieldCache[t] 75 fieldCacheMutex.RUnlock() 76 if !ok { 77 cache = make(map[string]int) 78 for i := 0; i < v.NumField(); i++ { 79 cache[t.Field(i).Name] = i 80 } 81 fieldCacheMutex.Lock() 82 fieldCache[t] = cache 83 fieldCacheMutex.Unlock() 84 } 85 86 if i, ok := cache[name]; ok { 87 return v.Field(i) 88 } 89 90 return reflect.Zero(t) 91 } 92 93 // scan data to a struct's pointer according field name 94 func (rs *Rows) ScanStructByName(dest interface{}) error { 95 vv := reflect.ValueOf(dest) 96 if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { 97 return errors.New("dest should be a struct's pointer") 98 } 99 100 cols, err := rs.Columns() 101 if err != nil { 102 return err 103 } 104 105 newDest := make([]interface{}, len(cols)) 106 var v EmptyScanner 107 for j, name := range cols { 108 f := fieldByName(vv.Elem(), rs.Mapper.Table2Obj(name)) 109 if f.IsValid() { 110 newDest[j] = f.Addr().Interface() 111 } else { 112 newDest[j] = &v 113 } 114 } 115 116 return rs.Rows.Scan(newDest...) 117 } 118 119 type cacheStruct struct { 120 value reflect.Value 121 idx int 122 } 123 124 var ( 125 reflectCache = make(map[reflect.Type]*cacheStruct) 126 reflectCacheMutex sync.RWMutex 127 ) 128 129 func ReflectNew(typ reflect.Type) reflect.Value { 130 reflectCacheMutex.RLock() 131 cs, ok := reflectCache[typ] 132 reflectCacheMutex.RUnlock() 133 134 const newSize = 200 135 136 if !ok || cs.idx+1 > newSize-1 { 137 cs = &cacheStruct{reflect.MakeSlice(reflect.SliceOf(typ), newSize, newSize), 0} 138 reflectCacheMutex.Lock() 139 reflectCache[typ] = cs 140 reflectCacheMutex.Unlock() 141 } else { 142 reflectCacheMutex.Lock() 143 cs.idx = cs.idx + 1 144 reflectCacheMutex.Unlock() 145 } 146 return cs.value.Index(cs.idx).Addr() 147 } 148 149 // scan data to a slice's pointer, slice's length should equal to columns' number 150 func (rs *Rows) ScanSlice(dest interface{}) error { 151 vv := reflect.ValueOf(dest) 152 if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Slice { 153 return errors.New("dest should be a slice's pointer") 154 } 155 156 vvv := vv.Elem() 157 cols, err := rs.Columns() 158 if err != nil { 159 return err 160 } 161 162 newDest := make([]interface{}, len(cols)) 163 164 for j := 0; j < len(cols); j++ { 165 if j >= vvv.Len() { 166 newDest[j] = reflect.New(vvv.Type().Elem()).Interface() 167 } else { 168 newDest[j] = vvv.Index(j).Addr().Interface() 169 } 170 } 171 172 err = rs.Rows.Scan(newDest...) 173 if err != nil { 174 return err 175 } 176 177 srcLen := vvv.Len() 178 for i := srcLen; i < len(cols); i++ { 179 vvv = reflect.Append(vvv, reflect.ValueOf(newDest[i]).Elem()) 180 } 181 return nil 182 } 183 184 // scan data to a map's pointer 185 func (rs *Rows) ScanMap(dest interface{}) error { 186 vv := reflect.ValueOf(dest) 187 if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { 188 return errors.New("dest should be a map's pointer") 189 } 190 191 cols, err := rs.Columns() 192 if err != nil { 193 return err 194 } 195 196 newDest := make([]interface{}, len(cols)) 197 vvv := vv.Elem() 198 199 for i, _ := range cols { 200 newDest[i] = ReflectNew(vvv.Type().Elem()).Interface() 201 //v := reflect.New(vvv.Type().Elem()) 202 //newDest[i] = v.Interface() 203 } 204 205 err = rs.Rows.Scan(newDest...) 206 if err != nil { 207 return err 208 } 209 210 for i, name := range cols { 211 vname := reflect.ValueOf(name) 212 vvv.SetMapIndex(vname, reflect.ValueOf(newDest[i]).Elem()) 213 } 214 215 return nil 216 } 217 218 /*func (rs *Rows) ScanMap(dest interface{}) error { 219 vv := reflect.ValueOf(dest) 220 if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { 221 return errors.New("dest should be a map's pointer") 222 } 223 224 cols, err := rs.Columns() 225 if err != nil { 226 return err 227 } 228 229 newDest := make([]interface{}, len(cols)) 230 err = rs.ScanSlice(newDest) 231 if err != nil { 232 return err 233 } 234 235 vvv := vv.Elem() 236 237 for i, name := range cols { 238 vname := reflect.ValueOf(name) 239 vvv.SetMapIndex(vname, reflect.ValueOf(newDest[i]).Elem()) 240 } 241 242 return nil 243 }*/ 244 type Row struct { 245 rows *Rows 246 // One of these two will be non-nil: 247 err error // deferred error for easy chaining 248 } 249 250 func (row *Row) Columns() ([]string, error) { 251 if row.err != nil { 252 return nil, row.err 253 } 254 return row.rows.Columns() 255 } 256 257 func (row *Row) Scan(dest ...interface{}) error { 258 if row.err != nil { 259 return row.err 260 } 261 defer row.rows.Close() 262 263 for _, dp := range dest { 264 if _, ok := dp.(*sql.RawBytes); ok { 265 return errors.New("sql: RawBytes isn't allowed on Row.Scan") 266 } 267 } 268 269 if !row.rows.Next() { 270 if err := row.rows.Err(); err != nil { 271 return err 272 } 273 return sql.ErrNoRows 274 } 275 err := row.rows.Scan(dest...) 276 if err != nil { 277 return err 278 } 279 // Make sure the query can be processed to completion with no errors. 280 return row.rows.Close() 281 } 282 283 func (row *Row) ScanStructByName(dest interface{}) error { 284 if row.err != nil { 285 return row.err 286 } 287 defer row.rows.Close() 288 289 if !row.rows.Next() { 290 if err := row.rows.Err(); err != nil { 291 return err 292 } 293 return sql.ErrNoRows 294 } 295 err := row.rows.ScanStructByName(dest) 296 if err != nil { 297 return err 298 } 299 // Make sure the query can be processed to completion with no errors. 300 return row.rows.Close() 301 } 302 303 func (row *Row) ScanStructByIndex(dest interface{}) error { 304 if row.err != nil { 305 return row.err 306 } 307 defer row.rows.Close() 308 309 if !row.rows.Next() { 310 if err := row.rows.Err(); err != nil { 311 return err 312 } 313 return sql.ErrNoRows 314 } 315 err := row.rows.ScanStructByIndex(dest) 316 if err != nil { 317 return err 318 } 319 // Make sure the query can be processed to completion with no errors. 320 return row.rows.Close() 321 } 322 323 // scan data to a slice's pointer, slice's length should equal to columns' number 324 func (row *Row) ScanSlice(dest interface{}) error { 325 if row.err != nil { 326 return row.err 327 } 328 defer row.rows.Close() 329 330 if !row.rows.Next() { 331 if err := row.rows.Err(); err != nil { 332 return err 333 } 334 return sql.ErrNoRows 335 } 336 err := row.rows.ScanSlice(dest) 337 if err != nil { 338 return err 339 } 340 341 // Make sure the query can be processed to completion with no errors. 342 return row.rows.Close() 343 } 344 345 // scan data to a map's pointer 346 func (row *Row) ScanMap(dest interface{}) error { 347 if row.err != nil { 348 return row.err 349 } 350 defer row.rows.Close() 351 352 if !row.rows.Next() { 353 if err := row.rows.Err(); err != nil { 354 return err 355 } 356 return sql.ErrNoRows 357 } 358 err := row.rows.ScanMap(dest) 359 if err != nil { 360 return err 361 } 362 363 // Make sure the query can be processed to completion with no errors. 364 return row.rows.Close() 365 } 366 367 func (row *Row) ToMapString() (map[string]string, error) { 368 cols, err := row.Columns() 369 if err != nil { 370 return nil, err 371 } 372 373 var record = make(map[string]string, len(cols)) 374 err = row.ScanMap(&record) 375 if err != nil { 376 return nil, err 377 } 378 379 return record, nil 380 }