@@ -189,6 +189,175 @@ func (r *Query) Cursor() chan contractsdb.Row {
189189 return cursorChan
190190}
191191
192+ func (r * Query ) Chunk (count int , callback func ([]any ) error ) error {
193+ if count <= 0 {
194+ return errors .OrmQueryChunkZeroOrLess
195+ }
196+
197+ var remaining * int
198+ if r .conditions .limit != nil {
199+ limit := * r .conditions .limit
200+ remaining = & limit
201+ }
202+
203+ query := r .addGlobalScopes ().buildConditions ()
204+
205+ destType := reflect .TypeOf (r .conditions .model )
206+ sliceType := reflect .SliceOf (reflect .PointerTo (destType ))
207+ offset := 0
208+
209+ for {
210+ if remaining != nil && * remaining == 0 {
211+ break
212+ }
213+
214+ chunkLimit := count
215+ if remaining != nil && * remaining < count {
216+ chunkLimit = * remaining
217+ }
218+
219+ results := reflect .New (sliceType ).Interface ()
220+
221+ chunkQuery := query .Offset (offset ).Limit (chunkLimit ).(* Query )
222+ err := chunkQuery .Find (results )
223+ if err != nil {
224+ return err
225+ }
226+
227+ resultsValue := reflect .ValueOf (results ).Elem ()
228+ length := resultsValue .Len ()
229+ if length == 0 {
230+ return nil
231+ }
232+
233+ if remaining != nil {
234+ * remaining = max (* remaining - length , 0 )
235+ }
236+
237+ values := make ([]any , length )
238+ for i := 0 ; i < length ; i ++ {
239+ values [i ] = resultsValue .Index (i ).Interface ()
240+ }
241+
242+ if err = callback (values ); err != nil {
243+ return err
244+ }
245+
246+ if length < chunkLimit {
247+ return nil
248+ }
249+
250+ offset += chunkLimit
251+ }
252+
253+ return nil
254+ }
255+
256+ func (r * Query ) ChunkByID (count int , callback func ([]any ) error ) error {
257+ return r .OrderedChunkByID (count , callback , false )
258+ }
259+
260+ func (r * Query ) ChunkByIDDesc (count int , callback func ([]any ) error ) error {
261+ return r .OrderedChunkByID (count , callback , true )
262+ }
263+
264+ func (r * Query ) OrderedChunkByID (count int , callback func ([]any ) error , descending bool ) error {
265+ if count <= 0 {
266+ return errors .OrmQueryChunkZeroOrLess
267+ }
268+
269+ column := "id"
270+ initialOffset := 0
271+ if r .conditions .offset != nil {
272+ initialOffset = * r .conditions .offset
273+ }
274+ var remaining * int
275+ if r .conditions .limit != nil {
276+ limit := * r .conditions .limit
277+ remaining = & limit
278+ }
279+
280+ destType := reflect .TypeOf (r .conditions .model )
281+ sliceType := reflect .SliceOf (reflect .PointerTo (destType ))
282+ var lastID any
283+ page := 1
284+
285+ for {
286+ if remaining != nil && * remaining == 0 {
287+ break
288+ }
289+
290+ chunkLimit := count
291+ if remaining != nil && * remaining < count {
292+ chunkLimit = * remaining
293+ }
294+
295+ clone := r .addGlobalScopes ()
296+
297+ if initialOffset > 0 {
298+ if page > 1 {
299+ clone = clone .Offset (0 ).(* Query )
300+ } else {
301+ clone = clone .Offset (initialOffset ).(* Query )
302+ }
303+ }
304+
305+ if descending {
306+ clone = clone .OrderByDesc (column ).(* Query )
307+ } else {
308+ clone = clone .OrderBy (column ).(* Query )
309+ }
310+
311+ if lastID != nil {
312+ if descending {
313+ clone = clone .Where (column + " < ?" , lastID ).(* Query )
314+ } else {
315+ clone = clone .Where (column + " > ?" , lastID ).(* Query )
316+ }
317+ }
318+ clone = clone .Limit (chunkLimit ).(* Query )
319+
320+ query := clone .buildConditions ()
321+ results := reflect .New (sliceType ).Interface ()
322+
323+ err := query .Find (results )
324+ if err != nil {
325+ return err
326+ }
327+
328+ resultsValue := reflect .ValueOf (results ).Elem ()
329+ length := resultsValue .Len ()
330+
331+ if length == 0 {
332+ break
333+ }
334+
335+ if remaining != nil {
336+ * remaining = max (* remaining - length , 0 )
337+ }
338+
339+ values := make ([]any , length )
340+ for i := 0 ; i < length ; i ++ {
341+ values [i ] = resultsValue .Index (i ).Interface ()
342+ }
343+
344+ lastRecord := values [length - 1 ]
345+ lastID = database .GetID (lastRecord )
346+
347+ if err = callback (values ); err != nil {
348+ return err
349+ }
350+
351+ if length < chunkLimit {
352+ break
353+ }
354+
355+ page ++
356+ }
357+
358+ return nil
359+ }
360+
192361func (r * Query ) DB () (* sql.DB , error ) {
193362 return r .instance .DB ()
194363}
0 commit comments