mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-24 04:19:44 +09:00
77 lines
1.8 KiB
Go
77 lines
1.8 KiB
Go
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"gitea.dev/modules/setting"
|
|
|
|
"xorm.io/builder"
|
|
"xorm.io/xorm/schemas"
|
|
)
|
|
|
|
func iterateTableByColumn[Bean any](ctx context.Context, colName string, cond builder.Cond, f func(ctx context.Context, bean *Bean) error) error {
|
|
table, err := xormEngine.TableInfo(new(Bean))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var col *schemas.Column
|
|
if colName == "" {
|
|
if len(table.PrimaryKeys) != 1 {
|
|
return fmt.Errorf("table %s has %d primary keys, only the table with exactly one primary key can be iterated", table.Name, len(table.PrimaryKeys))
|
|
}
|
|
colName = table.PrimaryKeys[0]
|
|
}
|
|
|
|
col = table.GetColumn(colName)
|
|
batchSize := setting.Database.IterateBufferSize
|
|
var lastColValue any
|
|
for {
|
|
if ctx.Err() != nil {
|
|
return ctx.Err()
|
|
}
|
|
|
|
beans := make([]*Bean, 0, batchSize)
|
|
query := GetEngine(ctx).Table(table.Name).Asc(colName)
|
|
|
|
batchCond := cond
|
|
if lastColValue != nil {
|
|
batchCond = builder.And(cond, builder.Gt{col.Name: lastColValue})
|
|
}
|
|
if batchCond != nil {
|
|
query = query.Where(batchCond)
|
|
}
|
|
|
|
if err := query.Limit(batchSize).Find(&beans); err != nil {
|
|
return err
|
|
}
|
|
if len(beans) == 0 {
|
|
return nil
|
|
}
|
|
|
|
reflectVal, err := col.ValueOf(beans[len(beans)-1])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
lastColValue = reflectVal.Interface()
|
|
|
|
for _, bean := range beans {
|
|
if err := f(ctx, bean); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func IterateByColumn[Bean any](ctx context.Context, colName string, cond builder.Cond, f func(ctx context.Context, bean *Bean) error) error {
|
|
return iterateTableByColumn(ctx, colName, cond, f)
|
|
}
|
|
|
|
func Iterate[Bean any](ctx context.Context, cond builder.Cond, f func(ctx context.Context, bean *Bean) error) error {
|
|
return iterateTableByColumn(ctx, "", cond, f)
|
|
}
|