2017-01-03 11:20:28 +03:00
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package xorm
2020-03-22 18:12:55 +03:00
import (
"reflect"
"xorm.io/xorm/internal/utils"
)
2017-01-03 11:20:28 +03:00
// IterFunc only use by Iterate
type IterFunc func ( idx int , bean interface { } ) error
// Rows return sql.Rows compatible Rows obj, as a forward Iterator object for iterating record by record, bean's non-empty fields
// are conditions.
func ( session * Session ) Rows ( bean interface { } ) ( * Rows , error ) {
return newRows ( session , bean )
}
// Iterate record by record handle records from table, condiBeans's non-empty fields
// are conditions. beans could be []Struct, []*Struct, map[int64]Struct
// map[int64]*Struct
func ( session * Session ) Iterate ( bean interface { } , fun IterFunc ) error {
2017-09-13 08:18:22 +03:00
if session . isAutoClose {
defer session . Close ( )
}
2020-03-22 18:12:55 +03:00
if session . statement . LastError != nil {
return session . statement . LastError
2019-06-23 18:22:43 +03:00
}
2020-03-22 18:12:55 +03:00
if session . statement . BufferSize > 0 {
2017-10-01 19:52:35 +03:00
return session . bufferIterate ( bean , fun )
}
2017-01-03 11:20:28 +03:00
rows , err := session . Rows ( bean )
if err != nil {
return err
}
defer rows . Close ( )
i := 0
for rows . Next ( ) {
b := reflect . New ( rows . beanType ) . Interface ( )
err = rows . Scan ( b )
if err != nil {
return err
}
err = fun ( i , b )
if err != nil {
return err
}
i ++
}
return err
}
2017-10-01 19:52:35 +03:00
// BufferSize sets the buffersize for iterate
func ( session * Session ) BufferSize ( size int ) * Session {
2020-03-22 18:12:55 +03:00
session . statement . BufferSize = size
2017-10-01 19:52:35 +03:00
return session
}
func ( session * Session ) bufferIterate ( bean interface { } , fun IterFunc ) error {
2020-03-22 18:12:55 +03:00
var bufferSize = session . statement . BufferSize
var pLimitN = session . statement . LimitN
if pLimitN != nil && bufferSize > * pLimitN {
bufferSize = * pLimitN
2017-10-01 19:52:35 +03:00
}
var start = session . statement . Start
2020-03-22 18:12:55 +03:00
v := utils . ReflectValue ( bean )
2017-10-01 19:52:35 +03:00
sliceType := reflect . SliceOf ( v . Type ( ) )
var idx = 0
2020-03-22 18:12:55 +03:00
session . autoResetStatement = false
defer func ( ) {
session . autoResetStatement = true
} ( )
for bufferSize > 0 {
2017-10-01 19:52:35 +03:00
slice := reflect . New ( sliceType )
2020-03-22 18:12:55 +03:00
if err := session . NoCache ( ) . Limit ( bufferSize , start ) . find ( slice . Interface ( ) , bean ) ; err != nil {
2017-10-01 19:52:35 +03:00
return err
}
for i := 0 ; i < slice . Elem ( ) . Len ( ) ; i ++ {
if err := fun ( idx , slice . Elem ( ) . Index ( i ) . Addr ( ) . Interface ( ) ) ; err != nil {
return err
}
idx ++
}
2020-03-22 18:12:55 +03:00
if bufferSize > slice . Elem ( ) . Len ( ) {
break
2017-10-01 19:52:35 +03:00
}
2020-03-22 18:12:55 +03:00
start = start + slice . Elem ( ) . Len ( )
if pLimitN != nil && start + bufferSize > * pLimitN {
bufferSize = * pLimitN - start
2017-10-01 19:52:35 +03:00
}
}
return nil
}