Add database migrations for exif values
This commit is contained in:
parent
faf8602c59
commit
ad60eccf8b
|
@ -174,5 +174,12 @@ func MigrateDatabase(db *gorm.DB) error {
|
|||
db.Migrator().DropColumn(&models.Media{}, "date_imported")
|
||||
}
|
||||
|
||||
// v2.3.0 - Changed type of MediaEXIF.Exposure and MediaEXIF.Flash
|
||||
// from string values to decimal and int respectively
|
||||
err := migrate_exif_fields(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/photoview/photoview/api/graphql/models"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Migrate MediaExif fields "exposure" and "flash" from strings to integers
|
||||
func migrate_exif_fields(db *gorm.DB) error {
|
||||
mediaExifColumns, err := db.Migrator().ColumnTypes(&models.MediaEXIF{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = db.Transaction(func(tx *gorm.DB) error {
|
||||
for _, exifCol := range mediaExifColumns {
|
||||
if exifCol.Name() == "exposure" {
|
||||
switch exifCol.DatabaseTypeName() {
|
||||
case "double", "numeric", "real":
|
||||
// correct type, do nothing
|
||||
default:
|
||||
// do migration
|
||||
if err := migrate_exif_fields_exposure(db); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if exifCol.Name() == "flash" {
|
||||
switch exifCol.DatabaseTypeName() {
|
||||
case "double", "numeric", "real":
|
||||
// correct type, do nothing
|
||||
default:
|
||||
// do migration
|
||||
if err := migrate_exif_fields_flash(db); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.AutoMigrate(&models.MediaEXIF{}); err != nil {
|
||||
return errors.Wrap(err, "failed to auto migrate media_exif after exposure conversion")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func migrate_exif_fields_exposure(db *gorm.DB) error {
|
||||
log.Println("Migrating `media_exif.exposure` from string to double")
|
||||
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
type exifModel struct {
|
||||
ID int `gorm:"primarykey"`
|
||||
Exposure *string
|
||||
}
|
||||
var results []exifModel
|
||||
|
||||
return tx.Model(&exifModel{}).Table("media_exif").Where("exposure LIKE '%/%'").FindInBatches(&results, 100, func(tx *gorm.DB, batch int) error {
|
||||
for _, result := range results {
|
||||
frac := strings.Split(*result.Exposure, "/")
|
||||
if len(frac) != 2 {
|
||||
return errors.Errorf("failed to convert exposure value (%s) expected format x/y", frac)
|
||||
}
|
||||
|
||||
numerator, err := strconv.ParseFloat(frac[0], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
denominator, err := strconv.ParseFloat(frac[1], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
decimalValue := numerator / denominator
|
||||
*result.Exposure = fmt.Sprintf("%f", decimalValue)
|
||||
}
|
||||
|
||||
tx.Save(&results)
|
||||
|
||||
return nil
|
||||
}).Error
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "migrating `media_exif.exposure` failed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func migrate_exif_fields_flash(db *gorm.DB) error {
|
||||
log.Println("Migrating `media_exif.flash` from string to int")
|
||||
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
type exifModel struct {
|
||||
ID int `gorm:"primarykey"`
|
||||
Flash *string
|
||||
}
|
||||
var results []exifModel
|
||||
|
||||
var flashDescriptions = map[int]string{
|
||||
0x0: "No Flash",
|
||||
0x1: "Fired",
|
||||
0x5: "Fired, Return not detected",
|
||||
0x7: "Fired, Return detected",
|
||||
0x8: "On, Did not fire",
|
||||
0x9: "On, Fired",
|
||||
0xD: "On, Return not detected",
|
||||
0xF: "On, Return detected",
|
||||
0x10: "Off, Did not fire",
|
||||
0x14: "Off, Did not fire, Return not detected",
|
||||
0x18: "Auto, Did not fire",
|
||||
0x19: "Auto, Fired",
|
||||
0x1D: "Auto, Fired, Return not detected",
|
||||
0x1F: "Auto, Fired, Return detected",
|
||||
0x20: "No flash function",
|
||||
0x30: "Off, No flash function",
|
||||
0x41: "Fired, Red-eye reduction",
|
||||
0x45: "Fired, Red-eye reduction, Return not detected",
|
||||
0x47: "Fired, Red-eye reduction, Return detected",
|
||||
0x49: "On, Red-eye reduction",
|
||||
0x4D: "On, Red-eye reduction, Return not detected",
|
||||
0x4F: "On, Red-eye reduction, Return detected",
|
||||
0x50: "Off, Red-eye reduction",
|
||||
0x58: "Auto, Did not fire, Red-eye reduction",
|
||||
0x59: "Auto, Fired, Red-eye reduction",
|
||||
0x5D: "Auto, Fired, Red-eye reduction, Return not detected",
|
||||
0x5F: "Auto, Fired, Red-eye reduction, Return detected",
|
||||
}
|
||||
|
||||
return tx.Model(&exifModel{}).Table("media_exif").Where("flash IS NOT NULL").FindInBatches(&results, 100, func(tx *gorm.DB, batch int) error {
|
||||
for _, result := range results {
|
||||
for index, name := range flashDescriptions {
|
||||
if *result.Flash == name {
|
||||
*result.Flash = fmt.Sprintf("%d", index)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tx.Save(&results)
|
||||
|
||||
return nil
|
||||
}).Error
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "migrating `media_exif.flash` failed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue