diff --git a/assets/resources/examples/fixtures.sql b/assets/resources/examples/fixtures.sql index 69914c9de..91293f034 100644 --- a/assets/resources/examples/fixtures.sql +++ b/assets/resources/examples/fixtures.sql @@ -1 +1,7 @@ -INSERT INTO cameras (camera_slug, camera_model, camera_make, camera_notes, created_at, updated_at) VALUES('iphone_5', 'iPhone 5', 'Apple', 'TEST FIXTURE', '2001-01-01', '2001-01-02') +INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_owner, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (1, 'unknown', 'Unknown', '', '', '', '', '', '2020-01-06 02:06:29', '2020-01-06 02:07:26', null); +INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_owner, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (2, 'apple-iphone-se', 'iPhone SE', 'Apple', '', '', '', '', '2020-01-06 02:06:30', '2020-01-06 02:07:28', null); +INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_owner, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (3, 'canon-eos-5d', 'EOS 5D', 'Canon', '', '', '', '', '2020-01-06 02:06:32', '2020-01-06 02:06:32', null); +INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_owner, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (4, 'canon-eos-7d', 'EOS 7D', 'Canon', '', '', '', '', '2020-01-06 02:06:33', '2020-01-06 02:06:33', null); +INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_owner, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (5, 'canon-eos-6d', 'EOS 6D', 'Canon', '', '', '', '', '2020-01-06 02:06:35', '2020-01-06 02:06:54', null); +INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_owner, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (6, 'apple-iphone-6', 'iPhone 6', 'Apple', '', '', '', '', '2020-01-06 02:06:42', '2020-01-06 02:06:42', null); +INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_owner, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (7, 'apple-iphone-7', 'iPhone 7', 'Apple', '', '', '', '', '2020-01-06 02:06:51', '2020-01-06 02:06:51', null); diff --git a/internal/config/db.go b/internal/config/db.go index e40ee5a37..6becf8b72 100644 --- a/internal/config/db.go +++ b/internal/config/db.go @@ -177,6 +177,7 @@ func (c *Config) ImportSQL(filename string) { } statements := strings.Split(string(contents), ";\n") + q := c.Db().Unscoped() for _, stmt := range statements { // Skip empty lines and comments @@ -184,7 +185,11 @@ func (c *Config) ImportSQL(filename string) { continue } - if _, err := c.Db().CommonDB().Query(stmt); err != nil { + var result struct {} + + err := q.Raw(stmt).Scan(&result).Error + + if err != nil { log.Error(err) } } diff --git a/internal/entity/camera.go b/internal/entity/camera.go index 20f90377e..9394d2bb3 100644 --- a/internal/entity/camera.go +++ b/internal/entity/camera.go @@ -51,6 +51,8 @@ func NewCamera(modelName string, makeName string) *Camera { } func (m *Camera) FirstOrCreate(db *gorm.DB) *Camera { + writeMutex.Lock() + defer writeMutex.Unlock() if err := db.FirstOrCreate(m, "camera_model = ? AND camera_make = ?", m.CameraModel, m.CameraMake).Error; err != nil { log.Errorf("camera: %s", err) } diff --git a/internal/entity/country.go b/internal/entity/country.go index 26bb7b0ad..1a087888a 100644 --- a/internal/entity/country.go +++ b/internal/entity/country.go @@ -51,6 +51,8 @@ func NewCountry(countryCode string, countryName string) *Country { } func (m *Country) FirstOrCreate(db *gorm.DB) *Country { + writeMutex.Lock() + defer writeMutex.Unlock() if err := db.FirstOrCreate(m, "id = ?", m.ID).Error; err != nil { log.Errorf("country: %s", err) } diff --git a/internal/entity/entity.go b/internal/entity/entity.go index 62b849cb4..6ba356a46 100644 --- a/internal/entity/entity.go +++ b/internal/entity/entity.go @@ -11,6 +11,7 @@ package entity import ( "strconv" + "sync" "time" "github.com/jinzhu/gorm" @@ -19,6 +20,7 @@ import ( ) var log = event.Log +var writeMutex = sync.Mutex{} func logError(result *gorm.DB) { if result.Error != nil { diff --git a/internal/entity/keyword.go b/internal/entity/keyword.go index 127237f7b..2a62fd6a9 100644 --- a/internal/entity/keyword.go +++ b/internal/entity/keyword.go @@ -24,6 +24,8 @@ func NewKeyword(keyword string) *Keyword { } func (m *Keyword) FirstOrCreate(db *gorm.DB) *Keyword { + writeMutex.Lock() + defer writeMutex.Unlock() if err := db.FirstOrCreate(m, "keyword = ?", m.Keyword).Error; err != nil { log.Errorf("keyword: %s", err) } diff --git a/internal/entity/label.go b/internal/entity/label.go index dbf5178e5..da728e5d8 100644 --- a/internal/entity/label.go +++ b/internal/entity/label.go @@ -53,6 +53,8 @@ func NewLabel(labelName string, labelPriority int) *Label { } func (m *Label) FirstOrCreate(db *gorm.DB) *Label { + writeMutex.Lock() + defer writeMutex.Unlock() if err := db.FirstOrCreate(m, "label_slug = ?", m.LabelSlug).Error; err != nil { log.Errorf("label: %s", err) } diff --git a/internal/entity/lens.go b/internal/entity/lens.go index 592a7a3d5..7c817da30 100644 --- a/internal/entity/lens.go +++ b/internal/entity/lens.go @@ -1,6 +1,7 @@ package entity import ( + "strings" "time" "github.com/gosimple/slug" @@ -27,6 +28,9 @@ func (Lens) TableName() string { } func NewLens(modelName string, makeName string) *Lens { + modelName = strings.TrimSpace(modelName) + makeName = strings.TrimSpace(makeName) + if modelName == "" { modelName = "Unknown" } @@ -43,7 +47,9 @@ func NewLens(modelName string, makeName string) *Lens { } func (m *Lens) FirstOrCreate(db *gorm.DB) *Lens { - if err := db.FirstOrCreate(m, "lens_model = ? AND lens_make = ?", m.LensModel, m.LensMake).Error; err != nil { + writeMutex.Lock() + defer writeMutex.Unlock() + if err := db.FirstOrCreate(m, "lens_slug = ?", m.LensSlug).Error; err != nil { log.Errorf("lens: %s", err) } diff --git a/internal/entity/location.go b/internal/entity/location.go index 9bc0e415b..7e4a895e8 100644 --- a/internal/entity/location.go +++ b/internal/entity/location.go @@ -45,6 +45,9 @@ func NewLocation(lat, lng float64) *Location { } func (m *Location) Find(db *gorm.DB) error { + writeMutex.Lock() + defer writeMutex.Unlock() + if err := db.First(m, "id = ?", m.ID).Error; err == nil { m.Place = FindPlace(m.PlaceID, db) return nil diff --git a/internal/entity/photo_album.go b/internal/entity/photo_album.go index b293ea49d..c0a2a9d1d 100644 --- a/internal/entity/photo_album.go +++ b/internal/entity/photo_album.go @@ -31,6 +31,8 @@ func NewPhotoAlbum(photoUUID, albumUUID string) *PhotoAlbum { } func (m *PhotoAlbum) FirstOrCreate(db *gorm.DB) *PhotoAlbum { + writeMutex.Lock() + defer writeMutex.Unlock() if err := db.FirstOrCreate(m, "photo_uuid = ? AND album_uuid = ?", m.PhotoUUID, m.AlbumUUID).Error; err != nil { log.Errorf("photo album: %s", err) } diff --git a/internal/entity/photo_keyword.go b/internal/entity/photo_keyword.go index 308d41e45..5f938f783 100644 --- a/internal/entity/photo_keyword.go +++ b/internal/entity/photo_keyword.go @@ -21,6 +21,8 @@ func NewPhotoKeyword(photoID, keywordID uint) *PhotoKeyword { } func (m *PhotoKeyword) FirstOrCreate(db *gorm.DB) *PhotoKeyword { + writeMutex.Lock() + defer writeMutex.Unlock() if err := db.FirstOrCreate(m, "photo_id = ? AND keyword_id = ?", m.PhotoID, m.KeywordID).Error; err != nil { log.Errorf("photo keyword: %s", err) } diff --git a/internal/entity/photo_label.go b/internal/entity/photo_label.go index 9999ef95d..b266b7f84 100644 --- a/internal/entity/photo_label.go +++ b/internal/entity/photo_label.go @@ -30,6 +30,8 @@ func NewPhotoLabel(photoId, labelId uint, uncertainty int, source string) *Photo } func (m *PhotoLabel) FirstOrCreate(db *gorm.DB) *PhotoLabel { + writeMutex.Lock() + defer writeMutex.Unlock() if err := db.FirstOrCreate(m, "photo_id = ? AND label_id = ?", m.PhotoID, m.LabelID).Error; err != nil { log.Errorf("photo label: %s", err) } diff --git a/internal/entity/place.go b/internal/entity/place.go index 8d7d17170..8b7d8ddf0 100644 --- a/internal/entity/place.go +++ b/internal/entity/place.go @@ -72,6 +72,8 @@ func (m *Place) Find(db *gorm.DB) error { } func (m *Place) FirstOrCreate(db *gorm.DB) *Place { + writeMutex.Lock() + defer writeMutex.Unlock() if err := db.FirstOrCreate(m, "id = ? OR loc_label = ?", m.ID, m.LocLabel).Error; err != nil { log.Debugf("place: %s for token %s or label \"%s\"", err.Error(), m.ID, m.LocLabel) } diff --git a/internal/photoprism/mediafile_test.go b/internal/photoprism/mediafile_test.go index a610b9e63..2a92144dd 100644 --- a/internal/photoprism/mediafile_test.go +++ b/internal/photoprism/mediafile_test.go @@ -34,6 +34,13 @@ func TestMediaFile_DateCreated(t *testing.T) { assert.Equal(t, "2013-11-26 13:53:55 +0000 UTC", date.String()) assert.Empty(t, err) }) + t.Run("dog_created_1919.jpg", func(t *testing.T) { + mediaFile, err := NewMediaFile(conf.ExamplesPath() + "/dog_created_1919.jpg") + assert.Nil(t, err) + date := mediaFile.DateCreated().UTC() + assert.Equal(t, "1919-05-04 05:59:26 +0000 UTC", date.String()) + assert.Empty(t, err) + }) } func TestMediaFile_HasTimeAndPlace(t *testing.T) { diff --git a/internal/query/camera_test.go b/internal/query/camera_test.go index 2ceac5e1a..cc13baa26 100644 --- a/internal/query/camera_test.go +++ b/internal/query/camera_test.go @@ -10,10 +10,10 @@ import ( // Example for using database fixtures defined in assets/resources/examples/fixtures.sql func TestCamera_FirstOrCreate(t *testing.T) { - t.Run("iphone_5", func(t *testing.T) { - camera := entity.NewCamera("iPhone 5", "Apple") + t.Run("iphone-se", func(t *testing.T) { + camera := entity.NewCamera("iPhone SE", "Apple") c := config.TestConfig() camera.FirstOrCreate(c.Db()) - assert.Equal(t, "TEST FIXTURE", camera.CameraNotes) + assert.Equal(t, uint(2), camera.ID) }) }