Files
photoprism/internal/commands/migrations.go
2025-05-10 23:21:53 +10:00

972 lines
27 KiB
Go

package commands
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/entity/migrate"
"github.com/photoprism/photoprism/pkg/txt/report"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
var MigrationsStatusCommand = &cli.Command{
Name: "ls",
Aliases: []string{"status", "show"},
Usage: "Displays the status of schema migrations",
ArgsUsage: "[migrations...]",
Flags: report.CliFlags,
Action: migrationsStatusAction,
}
var MigrationsRunCommand = &cli.Command{
Name: "run",
Aliases: []string{"execute", "migrate"},
Usage: "Executes database schema migrations",
ArgsUsage: "[migrations...]",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "failed",
Aliases: []string{"f"},
Usage: "run previously failed migrations",
},
&cli.BoolFlag{
Name: "trace",
Aliases: []string{"t"},
Usage: "show trace logs for debugging",
},
},
Action: migrationsRunAction,
}
var MigrationsTransferCommand = &cli.Command{
Name: "transfer",
Aliases: []string{"copy"},
Usage: "Executes database data transfers",
ArgsUsage: "[migrations...]",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "force",
Aliases: []string{"f"},
Usage: "truncate target tables if populated",
},
&cli.BoolFlag{
Name: "trace",
Aliases: []string{"t"},
Usage: "show trace logs for debugging",
},
},
Action: migrationsTransferAction,
}
// MigrationsCommands registers the "migrations" CLI command.
var MigrationsCommands = &cli.Command{
Name: "migrations",
Usage: "Database schema migration subcommands",
Subcommands: []*cli.Command{
MigrationsStatusCommand,
MigrationsRunCommand,
MigrationsTransferCommand,
},
}
// migrationsStatusAction lists the status of schema migration.
func migrationsStatusAction(ctx *cli.Context) error {
conf, err := InitConfig(ctx)
_, cancel := context.WithCancel(context.Background())
defer cancel()
if err != nil {
return err
}
defer conf.Shutdown()
var ids []string
// Check argument for specific migrations to be run.
if migrations := strings.TrimSpace(ctx.Args().First()); migrations != "" {
ids = strings.Fields(migrations)
}
db := conf.Db()
status, err := migrate.Status(db, ids)
if err != nil {
return err
}
// Report columns.
cols := []string{"ID", "Dialect", "Stage", "Started At", "Finished At", "Status"}
// Report rows.
rows := make([][]string, 0, len(status))
for _, m := range status {
var stage, started, finished, info string
if m.Stage == "" {
stage = "main"
} else {
stage = m.Stage
}
if m.StartedAt.IsZero() {
started = "-"
} else {
started = m.StartedAt.Format("2006-01-02 15:04:05")
}
if m.Finished() {
finished = m.FinishedAt.Format("2006-01-02 15:04:05")
} else {
finished = "-"
}
if m.Error != "" {
info = m.Error
} else if m.Finished() {
info = "OK"
} else if m.StartedAt.IsZero() {
info = "-"
} else if m.Repeat(false) {
info = "Repeat"
} else {
info = "Running?"
}
rows = append(rows, []string{m.ID, m.Dialect, stage, started, finished, info})
}
// Display report.
info, err := report.RenderFormat(rows, cols, report.CliFormat(ctx))
if err != nil {
return err
}
fmt.Println(info)
return nil
}
// migrationsRunAction executes database schema migrations.
func migrationsRunAction(ctx *cli.Context) error {
if ctx.Args().First() == "ls" {
return fmt.Errorf("run '%s migrations ls' to display the status of schema migrations", filepath.Base(os.Args[0]))
}
start := time.Now()
conf := config.NewConfig(ctx)
_, cancel := context.WithCancel(context.Background())
defer cancel()
if err := conf.Init(); err != nil {
return err
}
defer conf.Shutdown()
if ctx.Bool("trace") {
log.SetLevel(logrus.TraceLevel)
log.Infoln("migrate: enabled trace mode")
}
runFailed := ctx.Bool("failed")
if runFailed {
log.Infoln("migrate: running previously failed migrations")
}
var ids []string
// Check argument for specific migrations to be run.
if migrations := strings.TrimSpace(ctx.Args().First()); migrations != "" {
ids = strings.Fields(migrations)
}
log.Infoln("migrating database schema...")
// Run migrations.
conf.MigrateDb(runFailed, ids)
elapsed := time.Since(start)
log.Infof("completed in %s", elapsed)
return nil
}
// migrationsTransferAction executes database data migrations.
func migrationsTransferAction(ctx *cli.Context) error {
if ctx.Args().First() == "ls" {
return fmt.Errorf("run '%s migrations ls' to display the status of schema migrations", filepath.Base(os.Args[0]))
}
batchSize := 5
start := time.Now()
conf := config.NewConfig(ctx)
tfrConf := config.NewConfig(ctx)
//log = event.Log
if err := tfrConf.SwapDBAndTransfer(); err != nil {
return err
}
_, cancel := context.WithCancel(context.Background())
defer cancel()
if err := conf.Init(); err != nil {
return err
}
if err := tfrConf.Init(); err != nil {
return err
}
defer conf.Shutdown()
defer tfrConf.Shutdown()
if ctx.Bool("trace") {
log.SetLevel(logrus.TraceLevel)
log.Infoln("migrate: enabled trace mode")
}
var ids []string
runForced := ctx.Bool("force")
log.Infoln("migrate: ensure target is empty...")
if tfrConf.Db().Unscoped().Migrator().HasTable(&entity.Photo{}) {
var photoCount int64
if err := tfrConf.Db().Unscoped().Model(&entity.Photo{}).Count(&photoCount).Error; err != nil {
log.Errorf("migrate: count of photos has failed with %s", err.Error())
return err
}
if photoCount > 0 {
if !runForced {
errmsg := fmt.Sprintf("migrate: transfer target database is not empty, %d photos found", photoCount)
log.Error(errmsg)
return fmt.Errorf(errmsg)
} else {
entity.SetDbProvider(tfrConf)
entity.Entities.Truncate(tfrConf.Db())
}
} else {
runForced = false
}
}
log.Infoln("migrate: migrating database schema...")
// Run migrations.
log.Infof("migrate: migrating against %s", tfrConf.DatabaseDsn())
entity.SetDbProvider(tfrConf)
tfrConf.MigrateDb(false, ids)
if runForced {
entity.CreateDefaultFixtures()
}
log.Infof("migrate: migrating against %s", conf.DatabaseDsn())
entity.SetDbProvider(conf)
conf.MigrateDb(false, ids)
// Copy tables
// Replace the admin user with the source one.
var userRecord entity.User
if err := tfrConf.Db().Unscoped().
Where("id = 1").
Find(&userRecord).Error; err != nil {
log.Errorf("migrate: error in admin user preselect %s", err.Error())
return err
} else {
if err = tfrConf.Db().Unscoped().Delete(&entity.UserDetails{UserUID: userRecord.UserUID}).Error; err != nil {
log.Errorf("migrate: error in admin user cleanup user details %s", err.Error())
return err
}
if err = tfrConf.Db().Unscoped().Delete(&entity.UserSettings{UserUID: userRecord.UserUID}).Error; err != nil {
log.Errorf("migrate: error in admin user cleanup user settings %s", err.Error())
return err
}
if err = tfrConf.Db().Unscoped().Delete(&entity.UserShare{UserUID: userRecord.UserUID}).Error; err != nil {
log.Errorf("migrate: error in admin user cleanup user share %s", err.Error())
return err
}
if err := conf.Db().Unscoped().
Where("id = 1").
Find(&userRecord).Error; err != nil {
log.Errorf("migrate: error in admin user preselect %s", err.Error())
return err
} else {
if err = tfrConf.Db().Save(&userRecord).Error; err != nil {
log.Errorf("migrate: error in admin user update %s", err.Error())
return err
}
}
}
// Bring the rest of the users across
var users entity.Users
result := conf.Db().Unscoped().
//Clauses(clause.OnConflict{UpdateAll: true}). // <-- This is not working against sqlite. Not generating the ON CONFLICT statements.
Where("id > 1").
FindInBatches(&users, batchSize, func(tx *gorm.DB, batch int) error {
var newUsers []*entity.User
for _, user := range users {
newUsers = append(newUsers, &user)
}
if result := tfrConf.Db().Create(newUsers); result.Error != nil {
log.Errorf("migrate: error in batch user create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of users transfered %v", result.RowsAffected)
}
var albums entity.Albums
result = conf.Db().Unscoped().
FindInBatches(&albums, batchSize, func(tx *gorm.DB, batch int) error {
var newAlbums []*entity.Album
for _, album := range albums {
newAlbums = append(newAlbums, &album)
}
if result := tfrConf.Db().Create(newAlbums); result.Error != nil {
log.Errorf("migrate: error in batch album create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of albums transfered %v", result.RowsAffected)
}
var cameras []entity.Camera
result = conf.Db().Unscoped().
Where("id > 1").
FindInBatches(&cameras, batchSize, func(tx *gorm.DB, batch int) error {
var newCameras []*entity.Camera
for _, camera := range cameras {
newCameras = append(newCameras, &camera)
}
if result := tfrConf.Db().Create(newCameras); result.Error != nil {
log.Errorf("migrate: error in batch camera create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of cameras transfered %v", result.RowsAffected)
}
var lenses entity.Lenses
result = conf.Db().Unscoped().
Where("id > 1").
FindInBatches(&lenses, batchSize, func(tx *gorm.DB, batch int) error {
var newLenses []*entity.Lens
for _, lens := range lenses {
newLenses = append(newLenses, &lens)
}
if result := tfrConf.Db().Create(newLenses); result.Error != nil {
log.Errorf("migrate: error in batch lens create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of lenses transfered %v", result.RowsAffected)
}
var places []entity.Place
result = conf.Db().Unscoped().
Where("id <> 'zz'").
FindInBatches(&places, batchSize, func(tx *gorm.DB, batch int) error {
var newPlaces []*entity.Place
for _, place := range places {
newPlaces = append(newPlaces, &place)
}
if result := tfrConf.Db().Create(newPlaces); result.Error != nil {
log.Errorf("migrate: error in batch place create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of places transfered %v", result.RowsAffected)
}
var cells []entity.Cell
result = conf.Db().Unscoped().
Where("id <> 'zz'").
FindInBatches(&cells, batchSize, func(tx *gorm.DB, batch int) error {
var newCells []*entity.Cell
for _, cell := range cells {
newCells = append(newCells, &cell)
}
if result := tfrConf.Db().Create(newCells); result.Error != nil {
log.Errorf("migrate: error in batch cell create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of cells transfered %v", result.RowsAffected)
}
var countries entity.Countries
result = conf.Db().Unscoped().
Where("id <> 'zz'").
FindInBatches(&countries, batchSize, func(tx *gorm.DB, batch int) error {
var newCountries []*entity.Country
for _, country := range countries {
newCountries = append(newCountries, &country)
}
if result := tfrConf.Db().Create(newCountries); result.Error != nil {
log.Errorf("migrate: error in batch country create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of countries transfered %v", result.RowsAffected)
}
var keywords []entity.Keyword
result = conf.Db().Unscoped().
FindInBatches(&keywords, batchSize, func(tx *gorm.DB, batch int) error {
var newKeywords []*entity.Keyword
for _, keyword := range keywords {
newKeywords = append(newKeywords, &keyword)
}
if result := tfrConf.Db().Create(newKeywords); result.Error != nil {
log.Errorf("migrate: error in batch keyword create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of keywords transfered %v", result.RowsAffected)
}
var labels []entity.Label
result = conf.Db().Unscoped().
FindInBatches(&labels, batchSize, func(tx *gorm.DB, batch int) error {
var newLabels []*entity.Label
for _, label := range labels {
newLabels = append(newLabels, &label)
}
if result := tfrConf.Db().Create(newLabels); result.Error != nil {
log.Errorf("migrate: error in batch label create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of labels transfered %v", result.RowsAffected)
}
var photos []entity.Photo
result = conf.Db().Unscoped().
Preload("Labels", func(db *gorm.DB) *gorm.DB {
return db.Order("photos_labels.uncertainty ASC, photos_labels.label_id DESC")
}).
Preload("Labels.Label").
Preload("Camera").
Preload("Lens").
Preload("Details").
Preload("Place").
Preload("Cell").
Preload("Cell.Place").
Preload("Albums").
Preload("Keywords").
Preload("Labels").
FindInBatches(&photos, batchSize, func(tx *gorm.DB, batch int) error {
var newPhotos []*entity.Photo
for _, photo := range photos {
newPhotos = append(newPhotos, &photo)
}
if result := tfrConf.Db().Create(newPhotos); result.Error != nil {
log.Errorf("migrate: error in batch photo create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of photos transfered %v", result.RowsAffected)
}
var files entity.Files
result = conf.Db().Unscoped().FindInBatches(&files, batchSize, func(tx *gorm.DB, batch int) error {
var newFiles []*entity.File
for _, file := range files {
newFiles = append(newFiles, &file)
}
if result := tfrConf.Db().Create(newFiles); result.Error != nil {
log.Errorf("migrate: error in batch file create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of files transfered %v", result.RowsAffected)
}
var albumUsers []entity.AlbumUser
result = conf.Db().Unscoped().
FindInBatches(&albumUsers, batchSize, func(tx *gorm.DB, batch int) error {
var newAlbumUsers []*entity.AlbumUser
for _, albumUser := range albumUsers {
newAlbumUsers = append(newAlbumUsers, &albumUser)
}
if result := tfrConf.Db().Create(newAlbumUsers); result.Error != nil {
log.Errorf("migrate: error in batch albumuser create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of albumusers transfered %v", result.RowsAffected)
}
var clients entity.Clients
result = conf.Db().Unscoped().
FindInBatches(&clients, batchSize, func(tx *gorm.DB, batch int) error {
var newClients []*entity.Client
for _, client := range clients {
newClients = append(newClients, &client)
}
if result := tfrConf.Db().Create(newClients); result.Error != nil {
log.Errorf("migrate: error in batch client create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of clients transfered %v", result.RowsAffected)
}
var sessions entity.Sessions
result = conf.Db().Unscoped().
FindInBatches(&sessions, batchSize, func(tx *gorm.DB, batch int) error {
var newSessions []*entity.Session
for _, session := range sessions {
newSessions = append(newSessions, &session)
}
if result := tfrConf.Db().Create(newSessions); result.Error != nil {
log.Errorf("migrate: error in batch session create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of sessions transfered %v", result.RowsAffected)
}
var userdetails []entity.UserDetails
result = conf.Db().Unscoped().
FindInBatches(&userdetails, batchSize, func(tx *gorm.DB, batch int) error {
var newUserDetails []*entity.UserDetails
for _, userdetail := range userdetails {
newUserDetails = append(newUserDetails, &userdetail)
}
if result := tfrConf.Db().
Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "user_uid"}},
UpdateAll: true,
}).Create(newUserDetails); result.Error != nil {
log.Errorf("migrate: error in batch userdetail create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of userdetails transfered %v", result.RowsAffected)
}
var usersettings []entity.UserSettings
result = conf.Db().Unscoped().
FindInBatches(&usersettings, batchSize, func(tx *gorm.DB, batch int) error {
var newUserSettings []*entity.UserSettings
for _, usersetting := range usersettings {
newUserSettings = append(newUserSettings, &usersetting)
}
if result := tfrConf.Db().
Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "user_uid"}},
UpdateAll: true,
}).
Create(newUserSettings); result.Error != nil {
log.Errorf("migrate: error in batch usersetting create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of usersettings transfered %v", result.RowsAffected)
}
var usershares entity.UserShares
result = conf.Db().Unscoped().
FindInBatches(&usershares, batchSize, func(tx *gorm.DB, batch int) error {
var newUserShares []*entity.UserShare
for _, usershare := range usershares {
newUserShares = append(newUserShares, &usershare)
}
if result := tfrConf.Db().Create(newUserShares); result.Error != nil {
log.Errorf("migrate: error in batch usershare create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of usershares transfered %v", result.RowsAffected)
}
var categorys []entity.Category
result = conf.Db().Unscoped().
FindInBatches(&categorys, batchSize, func(tx *gorm.DB, batch int) error {
var newCategorys []*entity.Category
for _, category := range categorys {
newCategorys = append(newCategorys, &category)
}
if result := tfrConf.Db().Create(newCategorys); result.Error != nil {
log.Errorf("migrate: error in batch category create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of categories transfered %v", result.RowsAffected)
}
var duplicates entity.Duplicates
result = conf.Db().Unscoped().
FindInBatches(&duplicates, batchSize, func(tx *gorm.DB, batch int) error {
var newDuplicates []*entity.Duplicate
for _, duplicate := range duplicates {
newDuplicates = append(newDuplicates, &duplicate)
}
if result := tfrConf.Db().Create(newDuplicates); result.Error != nil {
log.Errorf("migrate: error in batch duplicate create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of duplicates transfered %v", result.RowsAffected)
}
var errors entity.Errors
result = conf.Db().Unscoped().
FindInBatches(&errors, batchSize, func(tx *gorm.DB, batch int) error {
var newErrors []*entity.Error
for _, error := range errors {
newErrors = append(newErrors, &error)
}
if result := tfrConf.Db().
Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
UpdateAll: true,
}).
Create(newErrors); result.Error != nil {
log.Errorf("migrate: error in batch error create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of errors transfered %v", result.RowsAffected)
}
var faces entity.Faces
result = conf.Db().Unscoped().
FindInBatches(&faces, batchSize, func(tx *gorm.DB, batch int) error {
var newFaces []*entity.Face
for _, face := range faces {
newFaces = append(newFaces, &face)
}
if result := tfrConf.Db().Create(newFaces); result.Error != nil {
log.Errorf("migrate: error in batch face create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of faces transfered %v", result.RowsAffected)
}
var services entity.Services
result = conf.Db().Unscoped().
FindInBatches(&services, batchSize, func(tx *gorm.DB, batch int) error {
var newServices []*entity.Service
for _, service := range services {
newServices = append(newServices, &service)
}
if result := tfrConf.Db().Create(newServices); result.Error != nil {
log.Errorf("migrate: error in batch service create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of services transfered %v", result.RowsAffected)
}
var fileshares []entity.FileShare
result = conf.Db().Unscoped().
FindInBatches(&fileshares, batchSize, func(tx *gorm.DB, batch int) error {
var newFileShares []*entity.FileShare
for _, fileshare := range fileshares {
newFileShares = append(newFileShares, &fileshare)
}
if result := tfrConf.Db().Create(newFileShares); result.Error != nil {
log.Errorf("migrate: error in batch fileshare create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of fileshares transfered %v", result.RowsAffected)
}
var filesyncs []entity.FileSync
result = conf.Db().Unscoped().
FindInBatches(&filesyncs, batchSize, func(tx *gorm.DB, batch int) error {
var newFileSyncs []*entity.FileSync
for _, filesync := range filesyncs {
newFileSyncs = append(newFileSyncs, &filesync)
}
if result := tfrConf.Db().Create(newFileSyncs); result.Error != nil {
log.Errorf("migrate: error in batch filesync create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of filesyncs transfered %v", result.RowsAffected)
}
var folders entity.Folders
result = conf.Db().Unscoped().
FindInBatches(&folders, batchSize, func(tx *gorm.DB, batch int) error {
var newFolders []*entity.Folder
for _, folder := range folders {
newFolders = append(newFolders, &folder)
}
if result := tfrConf.Db().Create(newFolders); result.Error != nil {
log.Errorf("migrate: error in batch folder create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of folders transfered %v", result.RowsAffected)
}
var links entity.Links
result = conf.Db().Unscoped().
FindInBatches(&links, batchSize, func(tx *gorm.DB, batch int) error {
var newLinks []*entity.Link
for _, link := range links {
newLinks = append(newLinks, &link)
}
if result := tfrConf.Db().Create(newLinks); result.Error != nil {
log.Errorf("migrate: error in batch link create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of links transfered %v", result.RowsAffected)
}
var markers entity.Markers
result = conf.Db().Unscoped().
FindInBatches(&markers, batchSize, func(tx *gorm.DB, batch int) error {
var newMarkers []*entity.Marker
for _, marker := range markers {
newMarkers = append(newMarkers, &marker)
}
if result := tfrConf.Db().Create(newMarkers); result.Error != nil {
log.Errorf("migrate: error in batch marker create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of markers transfered %v", result.RowsAffected)
}
var passcodes []entity.Passcode
result = conf.Db().Unscoped().
FindInBatches(&passcodes, batchSize, func(tx *gorm.DB, batch int) error {
var newPasscodes []*entity.Passcode
for _, passcode := range passcodes {
newPasscodes = append(newPasscodes, &passcode)
}
if result := tfrConf.Db().Create(newPasscodes); result.Error != nil {
log.Errorf("migrate: error in batch passcode create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of passcodes transfered %v", result.RowsAffected)
}
var passwords []entity.Password
result = conf.Db().Unscoped().
FindInBatches(&passwords, batchSize, func(tx *gorm.DB, batch int) error {
var newPasswords []*entity.Password
for _, password := range passwords {
newPasswords = append(newPasswords, &password)
}
if result := tfrConf.Db().Create(newPasswords); result.Error != nil {
log.Errorf("migrate: error in batch password create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of passwords transfered %v", result.RowsAffected)
}
var photousers []entity.PhotoUser
result = conf.Db().Unscoped().
FindInBatches(&photousers, batchSize, func(tx *gorm.DB, batch int) error {
var newPhotoUsers []*entity.PhotoUser
for _, photouser := range photousers {
newPhotoUsers = append(newPhotoUsers, &photouser)
}
if result := tfrConf.Db().Create(newPhotoUsers); result.Error != nil {
log.Errorf("migrate: error in batch photouser create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of photousers transfered %v", result.RowsAffected)
}
var reactions []entity.Reaction
result = conf.Db().Unscoped().
FindInBatches(&reactions, batchSize, func(tx *gorm.DB, batch int) error {
var newReactions []*entity.Reaction
for _, reaction := range reactions {
newReactions = append(newReactions, &reaction)
}
if result := tfrConf.Db().Create(newReactions); result.Error != nil {
log.Errorf("migrate: error in batch reaction create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of reactions transfered %v", result.RowsAffected)
}
var subjects entity.Subjects
result = conf.Db().Unscoped().
FindInBatches(&subjects, batchSize, func(tx *gorm.DB, batch int) error {
var newSubjects []*entity.Subject
for _, subject := range subjects {
newSubjects = append(newSubjects, &subject)
}
if result := tfrConf.Db().Create(newSubjects); result.Error != nil {
log.Errorf("migrate: error in batch subject create %s", result.Error)
return result.Error
}
return nil
})
if result.Error != nil {
return result.Error
} else {
log.Infof("migrate: number of subjects transfered %v", result.RowsAffected)
}
elapsed := time.Since(start)
log.Infof("completed in %s", elapsed)
return nil
}