Simple and Powerful ORM for Go, support mysql,postgres,tidb,sqlite3,mssql,oracle https://xorm.io
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

104 lines
2.4 KiB

  1. // Copyright 2016 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. package xorm
  5. import (
  6. "reflect"
  7. )
  8. // IterFunc only use by Iterate
  9. type IterFunc func(idx int, bean interface{}) error
  10. // Rows return sql.Rows compatible Rows obj, as a forward Iterator object for iterating record by record, bean's non-empty fields
  11. // are conditions.
  12. func (session *Session) Rows(bean interface{}) (*Rows, error) {
  13. return newRows(session, bean)
  14. }
  15. // Iterate record by record handle records from table, condiBeans's non-empty fields
  16. // are conditions. beans could be []Struct, []*Struct, map[int64]Struct
  17. // map[int64]*Struct
  18. func (session *Session) Iterate(bean interface{}, fun IterFunc) error {
  19. if session.isAutoClose {
  20. defer session.Close()
  21. }
  22. if session.statement.lastError != nil {
  23. return session.statement.lastError
  24. }
  25. if session.statement.bufferSize > 0 {
  26. return session.bufferIterate(bean, fun)
  27. }
  28. rows, err := session.Rows(bean)
  29. if err != nil {
  30. return err
  31. }
  32. defer rows.Close()
  33. i := 0
  34. for rows.Next() {
  35. b := reflect.New(rows.beanType).Interface()
  36. err = rows.Scan(b)
  37. if err != nil {
  38. return err
  39. }
  40. err = fun(i, b)
  41. if err != nil {
  42. return err
  43. }
  44. i++
  45. }
  46. return err
  47. }
  48. // BufferSize sets the buffersize for iterate
  49. func (session *Session) BufferSize(size int) *Session {
  50. session.statement.bufferSize = size
  51. return session
  52. }
  53. func (session *Session) bufferIterate(bean interface{}, fun IterFunc) error {
  54. var bufferSize = session.statement.bufferSize
  55. var pLimitN = session.statement.LimitN
  56. if pLimitN != nil && bufferSize > *pLimitN {
  57. bufferSize = *pLimitN
  58. }
  59. var start = session.statement.Start
  60. v := rValue(bean)
  61. sliceType := reflect.SliceOf(v.Type())
  62. var idx = 0
  63. session.autoResetStatement = false
  64. defer func() {
  65. session.autoResetStatement = true
  66. }()
  67. for bufferSize > 0 {
  68. slice := reflect.New(sliceType)
  69. if err := session.NoCache().Limit(bufferSize, start).find(slice.Interface(), bean); err != nil {
  70. return err
  71. }
  72. for i := 0; i < slice.Elem().Len(); i++ {
  73. if err := fun(idx, slice.Elem().Index(i).Addr().Interface()); err != nil {
  74. return err
  75. }
  76. idx++
  77. }
  78. if bufferSize > slice.Elem().Len() {
  79. break
  80. }
  81. start = start + slice.Elem().Len()
  82. if pLimitN != nil && start+bufferSize > *pLimitN {
  83. bufferSize = *pLimitN - start
  84. }
  85. }
  86. return nil
  87. }