package database import ( "reflect" "github.com/pkg/errors" "gorm.io/gorm" ) const copyBatchSize = 100 // CopyObjects is a helper to copy elements of a given type from the // src to the target GORM database interface func CopyObjects(src, target *gorm.DB, objects ...any) (err error) { for _, obj := range objects { copySlice := reflect.New(reflect.SliceOf(reflect.TypeOf(obj))).Elem().Addr().Interface() if err = target.AutoMigrate(obj); err != nil { return errors.Wrap(err, "applying migration to target") } if err = target.Where("1 = 1").Delete(obj).Error; err != nil { return errors.Wrap(err, "cleaning target table") } if err = src.FindInBatches(copySlice, copyBatchSize, func(tx *gorm.DB, _ int) error { if err = target.Save(copySlice).Error; err != nil { if errors.Is(err, gorm.ErrEmptySlice) { // That's fine and no reason to exit here return nil } return errors.Wrap(err, "inserting collected elements") } return nil }).Error; err != nil { return errors.Wrap(err, "batch-copying data") } } return nil }