mirror of
https://github.com/photoprism/photoprism.git
synced 2025-10-06 01:07:16 +08:00
Fix gorm relations; make most SQL more generic
This commit is contained in:
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-03-22 14:48+0000\n"
|
"POT-Creation-Date: 2024-06-23 17:25+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
7
go.mod
7
go.mod
@@ -79,7 +79,7 @@ require (
|
|||||||
github.com/pquerna/otp v1.4.0
|
github.com/pquerna/otp v1.4.0
|
||||||
gorm.io/driver/mysql v1.5.6
|
gorm.io/driver/mysql v1.5.6
|
||||||
gorm.io/driver/sqlite v1.5.5
|
gorm.io/driver/sqlite v1.5.5
|
||||||
gorm.io/gorm v1.25.9
|
gorm.io/gorm v1.25.10
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -98,6 +98,10 @@ require (
|
|||||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/gosimple/unidecode v1.0.1 // indirect
|
github.com/gosimple/unidecode v1.0.1 // indirect
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
|
github.com/jackc/pgx/v5 v5.5.5 // indirect
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
@@ -117,6 +121,7 @@ require (
|
|||||||
golang.org/x/sys v0.19.0 // indirect
|
golang.org/x/sys v0.19.0 // indirect
|
||||||
google.golang.org/protobuf v1.33.0 // indirect
|
google.golang.org/protobuf v1.33.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
gorm.io/driver/postgres v1.5.9 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
12
go.sum
12
go.sum
@@ -188,6 +188,14 @@ github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOn
|
|||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||||
|
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
github.com/jdeng/goheif v0.0.0-20200323230657-a0d6a8b3e68f/go.mod h1:G7IyA3/eR9IFmUIPdyP3c0l4ZaqEvXAk876WfaQ8plc=
|
github.com/jdeng/goheif v0.0.0-20200323230657-a0d6a8b3e68f/go.mod h1:G7IyA3/eR9IFmUIPdyP3c0l4ZaqEvXAk876WfaQ8plc=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||||
@@ -550,11 +558,15 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
|
gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
|
||||||
gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||||
|
gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8=
|
||||||
|
gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
|
||||||
gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E=
|
gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E=
|
||||||
gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE=
|
gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE=
|
||||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8=
|
gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8=
|
||||||
gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
|
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
|
||||||
|
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
@@ -146,7 +146,7 @@ func PhotoUnstack(router *gin.RouterGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := entity.UnscopedDb().Exec(`UPDATE files
|
if err := entity.UnscopedDb().Exec(`UPDATE files
|
||||||
SET photo_id = ?, photo_uid = ?, file_name = ?, file_missing = 0
|
SET photo_id = ?, photo_uid = ?, file_name = ?, file_missing = FALSE
|
||||||
WHERE file_name = ? AND file_root = ?`,
|
WHERE file_name = ? AND file_root = ?`,
|
||||||
newPhoto.ID, newPhoto.PhotoUID, r.RootRelName(),
|
newPhoto.ID, newPhoto.PhotoUID, r.RootRelName(),
|
||||||
relName, relRoot).Error; err != nil {
|
relName, relRoot).Error; err != nil {
|
||||||
|
@@ -523,27 +523,27 @@ func (c *Config) ClientUser(withSettings bool) ClientConfig {
|
|||||||
if hidePrivate {
|
if hidePrivate {
|
||||||
c.Db().
|
c.Db().
|
||||||
Table("photos").
|
Table("photos").
|
||||||
Select("SUM(photo_type = 'video' AND photo_quality > -1 AND photo_private = 0) AS videos, " +
|
Select("COUNT(CASE WHEN photo_type = 'video' AND photo_quality > -1 AND photo_private = FALSE THEN 1 END) AS videos, " +
|
||||||
"SUM(photo_type = 'live' AND photo_quality > -1 AND photo_private = 0) AS live, " +
|
"COUNT(CASE WHEN photo_type = 'live' AND photo_quality > -1 AND photo_private = FALSE THEN 1 END) AS live, " +
|
||||||
"SUM(photo_quality = -1) AS hidden, " +
|
"COUNT(CASE WHEN photo_quality = -1 THEN 1 END) AS hidden, " +
|
||||||
"SUM(photo_type NOT IN ('live', 'video') AND photo_quality > -1 AND photo_private = 0) AS photos, " +
|
"COUNT(CASE WHEN photo_type NOT IN ('live', 'video') AND photo_quality > -1 AND photo_private = FALSE THEN 1 END) AS photos, " +
|
||||||
"SUM(photo_quality BETWEEN 0 AND 2) AS review, " +
|
"COUNT(CASE WHEN photo_quality BETWEEN 0 AND 2 THEN 1 END) AS review, " +
|
||||||
"SUM(photo_favorite = 1 AND photo_private = 0 AND photo_quality > -1) AS favorites, " +
|
"COUNT(CASE WHEN photo_favorite = TRUE AND photo_private = FALSE AND photo_quality > -1 THEN 1 END) AS favorites, " +
|
||||||
"SUM(photo_private = 1 AND photo_quality > -1) AS private").
|
"COUNT(CASE WHEN photo_private = TRUE AND photo_quality > -1 THEN 1 END) AS private").
|
||||||
Where("photos.id NOT IN (SELECT photo_id FROM files WHERE file_primary = 1 AND (file_missing = 1 OR file_error <> ''))").
|
Where("photos.id NOT IN (SELECT photo_id FROM files WHERE file_primary = TRUE AND (file_missing = TRUE OR file_error <> ''))").
|
||||||
Where("deleted_at IS NULL").
|
Where("deleted_at IS NULL").
|
||||||
Take(&cfg.Count)
|
Take(&cfg.Count)
|
||||||
} else {
|
} else {
|
||||||
c.Db().
|
c.Db().
|
||||||
Table("photos").
|
Table("photos").
|
||||||
Select("SUM(photo_type = 'video' AND photo_quality > -1) AS videos, " +
|
Select("COUNT(CASE WHEN photo_type = 'video' AND photo_quality > -1 THEN 1 END) AS videos, " +
|
||||||
"SUM(photo_type = 'live' AND photo_quality > -1) AS live, " +
|
"COUNT(CASE WHEN photo_type = 'live' AND photo_quality > -1 THEN 1 END) AS live, " +
|
||||||
"SUM(photo_quality = -1) AS hidden, " +
|
"COUNT(CASE WHEN photo_quality = -1 THEN 1 END) AS hidden, " +
|
||||||
"SUM(photo_type NOT IN ('live', 'video') AND photo_quality > -1) AS photos, " +
|
"COUNT(CASE WHEN photo_type NOT IN ('live', 'video') AND photo_quality > -1 THEN 1 END) AS photos, " +
|
||||||
"SUM(photo_quality BETWEEN 0 AND 2) AS review, " +
|
"COUNT(CASE WHEN photo_quality BETWEEN 0 AND 2 THEN 1 END) AS review, " +
|
||||||
"SUM(photo_favorite = 1 AND photo_quality > -1) AS favorites, " +
|
"COUNT(CASE WHEN photo_favorite = TRUE AND photo_quality > -1 THEN 1 END) AS favorites, " +
|
||||||
"0 AS private").
|
"0 AS private").
|
||||||
Where("photos.id NOT IN (SELECT photo_id FROM files WHERE file_primary = 1 AND (file_missing = 1 OR file_error <> ''))").
|
Where("photos.id NOT IN (SELECT photo_id FROM files WHERE file_primary = TRUE AND (file_missing = TRUE OR file_error <> ''))").
|
||||||
Where("deleted_at IS NULL").
|
Where("deleted_at IS NULL").
|
||||||
Take(&cfg.Count)
|
Take(&cfg.Count)
|
||||||
}
|
}
|
||||||
@@ -552,7 +552,7 @@ func (c *Config) ClientUser(withSettings bool) ClientConfig {
|
|||||||
if c.Settings().Features.Archive {
|
if c.Settings().Features.Archive {
|
||||||
c.Db().
|
c.Db().
|
||||||
Table("photos").
|
Table("photos").
|
||||||
Select("SUM(photo_quality > -1) AS archived").
|
Select("COUNT(CASE WHEN photo_quality > -1 THEN 1 END) AS archived").
|
||||||
Where("deleted_at IS NOT NULL").
|
Where("deleted_at IS NOT NULL").
|
||||||
Take(&cfg.Count)
|
Take(&cfg.Count)
|
||||||
}
|
}
|
||||||
@@ -570,34 +570,34 @@ func (c *Config) ClientUser(withSettings bool) ClientConfig {
|
|||||||
Select("MAX(photo_count) AS label_max_photos, COUNT(*) AS labels").
|
Select("MAX(photo_count) AS label_max_photos, COUNT(*) AS labels").
|
||||||
Where("photo_count > 0").
|
Where("photo_count > 0").
|
||||||
Where("deleted_at IS NULL").
|
Where("deleted_at IS NULL").
|
||||||
Where("(label_priority >= 0 OR label_favorite = 1)").
|
Where("(label_priority >= 0 OR label_favorite = TRUE)").
|
||||||
Take(&cfg.Count)
|
Take(&cfg.Count)
|
||||||
|
|
||||||
if hidePrivate {
|
if hidePrivate {
|
||||||
c.Db().
|
c.Db().
|
||||||
Table("albums").
|
Table("albums").
|
||||||
Select("SUM(album_type = ?) AS albums, "+
|
Select("COUNT(CASE WHEN album_type = ? THEN 1 END) AS albums, "+
|
||||||
"SUM(album_type = ?) AS moments, "+
|
"COUNT(CASE WHEN album_type = ? THEN 1 END) AS moments, "+
|
||||||
"SUM(album_type = ?) AS months, "+
|
"COUNT(CASE WHEN album_type = ? THEN 1 END) AS months, "+
|
||||||
"SUM(album_type = ?) AS states, "+
|
"COUNT(CASE WHEN album_type = ? THEN 1 END) AS states, "+
|
||||||
"SUM(album_type = ?) AS folders, "+
|
"COUNT(CASE WHEN album_type = ? THEN 1 END) AS folders, "+
|
||||||
"SUM(album_type = ? AND album_private = 1) AS private_albums, "+
|
"COUNT(CASE WHEN album_type = ? AND album_private = TRUE THEN 1 END) AS private_albums, "+
|
||||||
"SUM(album_type = ? AND album_private = 1) AS private_moments, "+
|
"COUNT(CASE WHEN album_type = ? AND album_private = TRUE THEN 1 END) AS private_moments, "+
|
||||||
"SUM(album_type = ? AND album_private = 1) AS private_months, "+
|
"COUNT(CASE WHEN album_type = ? AND album_private = TRUE THEN 1 END) AS private_months, "+
|
||||||
"SUM(album_type = ? AND album_private = 1) AS private_states, "+
|
"COUNT(CASE WHEN album_type = ? AND album_private = TRUE THEN 1 END) AS private_states, "+
|
||||||
"SUM(album_type = ? AND album_private = 1) AS private_folders",
|
"COUNT(CASE WHEN album_type = ? AND album_private = TRUE THEN 1 END) AS private_folders",
|
||||||
entity.AlbumManual, entity.AlbumMoment, entity.AlbumMonth, entity.AlbumState, entity.AlbumFolder,
|
entity.AlbumManual, entity.AlbumMoment, entity.AlbumMonth, entity.AlbumState, entity.AlbumFolder,
|
||||||
entity.AlbumManual, entity.AlbumMoment, entity.AlbumMonth, entity.AlbumState, entity.AlbumFolder).
|
entity.AlbumManual, entity.AlbumMoment, entity.AlbumMonth, entity.AlbumState, entity.AlbumFolder).
|
||||||
Where("deleted_at IS NULL AND (albums.album_type <> 'folder' OR albums.album_path IN (SELECT photos.photo_path FROM photos WHERE photos.photo_private = 0 AND photos.deleted_at IS NULL))").
|
Where("deleted_at IS NULL AND (albums.album_type <> 'folder' OR albums.album_path IN (SELECT photos.photo_path FROM photos WHERE photos.photo_private = FALSE AND photos.deleted_at IS NULL))").
|
||||||
Take(&cfg.Count)
|
Take(&cfg.Count)
|
||||||
} else {
|
} else {
|
||||||
c.Db().
|
c.Db().
|
||||||
Table("albums").
|
Table("albums").
|
||||||
Select("SUM(album_type = ?) AS albums, "+
|
Select("COUNT(CASE WHEN album_type = ? THEN 1 END) AS albums, "+
|
||||||
"SUM(album_type = ?) AS moments, "+
|
"COUNT(CASE WHEN album_type = ? THEN 1 END) AS moments, "+
|
||||||
"SUM(album_type = ?) AS months, "+
|
"COUNT(CASE WHEN album_type = ? THEN 1 END) AS months, "+
|
||||||
"SUM(album_type = ?) AS states, "+
|
"COUNT(CASE WHEN album_type = ? THEN 1 END) AS states, "+
|
||||||
"SUM(album_type = ?) AS folders",
|
"COUNT(CASE WHEN album_type = ? THEN 1 END) AS folders",
|
||||||
entity.AlbumManual, entity.AlbumMoment, entity.AlbumMonth, entity.AlbumState, entity.AlbumFolder).
|
entity.AlbumManual, entity.AlbumMoment, entity.AlbumMonth, entity.AlbumState, entity.AlbumFolder).
|
||||||
Where("deleted_at IS NULL AND (albums.album_type <> 'folder' OR albums.album_path IN (SELECT photos.photo_path FROM photos WHERE photos.deleted_at IS NULL))").
|
Where("deleted_at IS NULL AND (albums.album_type <> 'folder' OR albums.album_path IN (SELECT photos.photo_path FROM photos WHERE photos.deleted_at IS NULL))").
|
||||||
Take(&cfg.Count)
|
Take(&cfg.Count)
|
||||||
@@ -606,7 +606,7 @@ func (c *Config) ClientUser(withSettings bool) ClientConfig {
|
|||||||
c.Db().
|
c.Db().
|
||||||
Table("files").
|
Table("files").
|
||||||
Select("COUNT(*) AS files").
|
Select("COUNT(*) AS files").
|
||||||
Where("file_missing = 0 AND file_root = ? AND deleted_at IS NULL", entity.RootOriginals).
|
Where("file_missing = FALSE AND file_root = ? AND deleted_at IS NULL", entity.RootOriginals).
|
||||||
Take(&cfg.Count)
|
Take(&cfg.Count)
|
||||||
|
|
||||||
c.Db().
|
c.Db().
|
||||||
@@ -616,7 +616,7 @@ func (c *Config) ClientUser(withSettings bool) ClientConfig {
|
|||||||
|
|
||||||
c.Db().
|
c.Db().
|
||||||
Table("places").
|
Table("places").
|
||||||
Select("SUM(photo_count > 0) AS places").
|
Select("COUNT(CASE WHEN photo_count > 0 THEN 1 END) AS places").
|
||||||
Where("id <> 'zz'").
|
Where("id <> 'zz'").
|
||||||
Take(&cfg.Count)
|
Take(&cfg.Count)
|
||||||
|
|
||||||
@@ -640,7 +640,7 @@ func (c *Config) ClientUser(withSettings bool) ClientConfig {
|
|||||||
Find(&cfg.Lenses)
|
Find(&cfg.Lenses)
|
||||||
|
|
||||||
c.Db().
|
c.Db().
|
||||||
Where("deleted_at IS NULL AND album_favorite = 1").
|
Where("deleted_at IS NULL AND album_favorite = TRUE").
|
||||||
Limit(20).Order("album_title").
|
Limit(20).Order("album_title").
|
||||||
Find(&cfg.Albums)
|
Find(&cfg.Albums)
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/logger"
|
"gorm.io/gorm/logger"
|
||||||
@@ -39,8 +40,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var drivers = map[string]func(string) gorm.Dialector{
|
var drivers = map[string]func(string) gorm.Dialector{
|
||||||
MySQL: mysql.Open,
|
MySQL: mysql.Open,
|
||||||
SQLite3: sqlite.Open,
|
SQLite3: sqlite.Open,
|
||||||
|
Postgres: postgres.Open,
|
||||||
}
|
}
|
||||||
|
|
||||||
// DatabaseDriver returns the database driver name.
|
// DatabaseDriver returns the database driver name.
|
||||||
@@ -50,6 +52,8 @@ func (c *Config) DatabaseDriver() string {
|
|||||||
c.options.DatabaseDriver = MySQL
|
c.options.DatabaseDriver = MySQL
|
||||||
case SQLite3, "sqllite", "test", "file", "":
|
case SQLite3, "sqllite", "test", "file", "":
|
||||||
c.options.DatabaseDriver = SQLite3
|
c.options.DatabaseDriver = SQLite3
|
||||||
|
case Postgres:
|
||||||
|
c.options.DatabaseDriver = Postgres
|
||||||
case "tidb":
|
case "tidb":
|
||||||
log.Warnf("config: database driver 'tidb' is deprecated, using sqlite")
|
log.Warnf("config: database driver 'tidb' is deprecated, using sqlite")
|
||||||
c.options.DatabaseDriver = SQLite3
|
c.options.DatabaseDriver = SQLite3
|
||||||
@@ -153,9 +157,16 @@ func (c *Config) DatabaseHost() string {
|
|||||||
return c.options.DatabaseServer
|
return c.options.DatabaseServer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) _DefaultDatabasePort() int {
|
||||||
|
if c.DatabaseDriver() == Postgres {
|
||||||
|
return 5432
|
||||||
|
}
|
||||||
|
return 3306
|
||||||
|
}
|
||||||
|
|
||||||
// DatabasePort the database server port.
|
// DatabasePort the database server port.
|
||||||
func (c *Config) DatabasePort() int {
|
func (c *Config) DatabasePort() int {
|
||||||
const defaultPort = 3306
|
defaultPort := c._DefaultDatabasePort()
|
||||||
|
|
||||||
if server := c.DatabaseServer(); server == "" {
|
if server := c.DatabaseServer(); server == "" {
|
||||||
return 0
|
return 0
|
||||||
|
@@ -32,36 +32,36 @@ type Albums []Album
|
|||||||
|
|
||||||
// Album represents a photo album
|
// Album represents a photo album
|
||||||
type Album struct {
|
type Album struct {
|
||||||
ID uint `gorm:"primaryKey;" json:"ID" yaml:"-"`
|
ID uint `gorm:"primaryKey;" json:"ID" yaml:"-"`
|
||||||
AlbumUID string `gorm:"type:VARBINARY(42);uniqueIndex;" json:"UID" yaml:"UID"`
|
AlbumUID string `gorm:"size:42;uniqueIndex;" json:"UID" yaml:"UID"`
|
||||||
ParentUID string `gorm:"type:VARBINARY(42);default:'';" json:"ParentUID,omitempty" yaml:"ParentUID,omitempty"`
|
ParentUID string `gorm:"size:42;default:'';" json:"ParentUID,omitempty" yaml:"ParentUID,omitempty"`
|
||||||
AlbumSlug string `gorm:"type:VARBINARY(160);index;" json:"Slug" yaml:"Slug"`
|
AlbumSlug string `gorm:"size:160;index;" json:"Slug" yaml:"Slug"`
|
||||||
AlbumPath string `gorm:"type:VARCHAR(1024);index;" json:"Path,omitempty" yaml:"Path,omitempty"`
|
AlbumPath string `gorm:"size:1024;index;" json:"Path,omitempty" yaml:"Path,omitempty"`
|
||||||
AlbumType string `gorm:"type:VARBINARY(8);default:'album';" json:"Type" yaml:"Type,omitempty"`
|
AlbumType string `gorm:"size:8;default:'album';" json:"Type" yaml:"Type,omitempty"`
|
||||||
AlbumTitle string `gorm:"type:VARCHAR(160);index;" json:"Title" yaml:"Title"`
|
AlbumTitle string `gorm:"type:VARCHAR(160);index;" json:"Title" yaml:"Title"`
|
||||||
AlbumLocation string `gorm:"type:VARCHAR(160);" json:"Location" yaml:"Location,omitempty"`
|
AlbumLocation string `gorm:"type:VARCHAR(160);" json:"Location" yaml:"Location,omitempty"`
|
||||||
AlbumCategory string `gorm:"type:VARCHAR(100);index;" json:"Category" yaml:"Category,omitempty"`
|
AlbumCategory string `gorm:"type:VARCHAR(100);index;" json:"Category" yaml:"Category,omitempty"`
|
||||||
AlbumCaption string `gorm:"type:VARCHAR(1024);" json:"Caption" yaml:"Caption,omitempty"`
|
AlbumCaption string `gorm:"type:VARCHAR(1024);" json:"Caption" yaml:"Caption,omitempty"`
|
||||||
AlbumDescription string `gorm:"type:VARCHAR(2048);" json:"Description" yaml:"Description,omitempty"`
|
AlbumDescription string `gorm:"type:VARCHAR(2048);" json:"Description" yaml:"Description,omitempty"`
|
||||||
AlbumNotes string `gorm:"type:VARCHAR(1024);" json:"Notes" yaml:"Notes,omitempty"`
|
AlbumNotes string `gorm:"type:VARCHAR(1024);" json:"Notes" yaml:"Notes,omitempty"`
|
||||||
AlbumFilter string `gorm:"type:VARBINARY(2048);" json:"Filter" yaml:"Filter,omitempty"`
|
AlbumFilter string `gorm:"size:2048;" json:"Filter" yaml:"Filter,omitempty"`
|
||||||
AlbumOrder string `gorm:"type:VARBINARY(32);" json:"Order" yaml:"Order,omitempty"`
|
AlbumOrder string `gorm:"size:32;" json:"Order" yaml:"Order,omitempty"`
|
||||||
AlbumTemplate string `gorm:"type:VARBINARY(255);" json:"Template" yaml:"Template,omitempty"`
|
AlbumTemplate string `gorm:"size:255;" json:"Template" yaml:"Template,omitempty"`
|
||||||
AlbumState string `gorm:"type:VARCHAR(100);index;" json:"State" yaml:"State,omitempty"`
|
AlbumState string `gorm:"type:VARCHAR(100);index;" json:"State" yaml:"State,omitempty"`
|
||||||
AlbumCountry string `gorm:"type:VARBINARY(2);index:idx_albums_country_year_month;default:'zz';" json:"Country" yaml:"Country,omitempty"`
|
AlbumCountry string `gorm:"size:2;index:idx_albums_country_year_month;default:'zz';" json:"Country" yaml:"Country,omitempty"`
|
||||||
AlbumYear int `gorm:"index:idx_albums_ymd;index:idx_albums_country_year_month;" json:"Year" yaml:"Year,omitempty"`
|
AlbumYear int `gorm:"index:idx_albums_ymd;index:idx_albums_country_year_month;" json:"Year" yaml:"Year,omitempty"`
|
||||||
AlbumMonth int `gorm:"index:idx_albums_ymd;index:idx_albums_country_year_month;" json:"Month" yaml:"Month,omitempty"`
|
AlbumMonth int `gorm:"index:idx_albums_ymd;index:idx_albums_country_year_month;" json:"Month" yaml:"Month,omitempty"`
|
||||||
AlbumDay int `gorm:"index:idx_albums_ymd;" json:"Day" yaml:"Day,omitempty"`
|
AlbumDay int `gorm:"index:idx_albums_ymd;" json:"Day" yaml:"Day,omitempty"`
|
||||||
AlbumFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
AlbumFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
||||||
AlbumPrivate bool `json:"Private" yaml:"Private,omitempty"`
|
AlbumPrivate bool `json:"Private" yaml:"Private,omitempty"`
|
||||||
Thumb string `gorm:"type:VARBINARY(128);index;default:'';" json:"Thumb" yaml:"Thumb,omitempty"`
|
Thumb string `gorm:"size:128;index;default:'';" json:"Thumb" yaml:"Thumb,omitempty"`
|
||||||
ThumbSrc string `gorm:"type:VARBINARY(8);default:'';" json:"ThumbSrc,omitempty" yaml:"ThumbSrc,omitempty"`
|
ThumbSrc string `gorm:"size:8;default:'';" json:"ThumbSrc,omitempty" yaml:"ThumbSrc,omitempty"`
|
||||||
CreatedBy string `gorm:"type:VARBINARY(42);index" json:"CreatedBy,omitempty" yaml:"CreatedBy,omitempty"`
|
CreatedBy string `gorm:"size:42;index" json:"CreatedBy,omitempty" yaml:"CreatedBy,omitempty"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt,omitempty"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt,omitempty"`
|
||||||
UpdatedAt time.Time `json:"UpdatedAt" yaml:"UpdatedAt,omitempty"`
|
UpdatedAt time.Time `json:"UpdatedAt" yaml:"UpdatedAt,omitempty"`
|
||||||
PublishedAt *time.Time `sql:"index" json:"PublishedAt,omitempty" yaml:"PublishedAt,omitempty"`
|
PublishedAt *time.Time `sql:"index" json:"PublishedAt,omitempty" yaml:"PublishedAt,omitempty"`
|
||||||
DeletedAt *time.Time `sql:"index" json:"DeletedAt" yaml:"DeletedAt,omitempty"`
|
DeletedAt *time.Time `sql:"index" json:"DeletedAt" yaml:"DeletedAt,omitempty"`
|
||||||
Photos PhotoAlbums `gorm:"foreignKey:AlbumUID" json:"-" yaml:"Photos,omitempty"`
|
Photos []PhotoAlbum `gorm:"foreignKey:AlbumUID;references:AlbumUID" json:"-" yaml:"Photos,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AfterUpdate flushes the album cache.
|
// AfterUpdate flushes the album cache.
|
||||||
|
@@ -4,9 +4,9 @@ import "github.com/photoprism/photoprism/internal/event"
|
|||||||
|
|
||||||
// AlbumUser represents the user and group ownership of an Album and the corresponding permissions.
|
// AlbumUser represents the user and group ownership of an Album and the corresponding permissions.
|
||||||
type AlbumUser struct {
|
type AlbumUser struct {
|
||||||
UID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false" json:"UID" yaml:"UID"`
|
UID string `gorm:"primaryKey;autoIncrement:false" json:"UID" yaml:"UID"`
|
||||||
UserUID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false;index" json:"UserUID,omitempty" yaml:"UserUID,omitempty"`
|
UserUID string `gorm:"primaryKey;autoIncrement:false;index" json:"UserUID,omitempty" yaml:"UserUID,omitempty"`
|
||||||
TeamUID string `gorm:"type:VARBINARY(42);index" json:"TeamUID,omitempty" yaml:"TeamUID,omitempty"`
|
TeamUID string `gorm:"index" json:"TeamUID,omitempty" yaml:"TeamUID,omitempty"`
|
||||||
Perm uint `json:"Perm,omitempty" yaml:"Perm,omitempty"`
|
Perm uint `json:"Perm,omitempty" yaml:"Perm,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,17 +29,17 @@ type Clients []Client
|
|||||||
|
|
||||||
// Client represents a client application.
|
// Client represents a client application.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
ClientUID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false;" json:"-" yaml:"ClientUID"`
|
ClientUID string `gorm:"size:42;primaryKey;autoIncrement:false;" json:"-" yaml:"ClientUID"`
|
||||||
UserUID string `gorm:"type:VARBINARY(42);index;default:'';" json:"UserUID" yaml:"UserUID,omitempty"`
|
UserUID string `gorm:"size:42;index;default:'';" json:"UserUID" yaml:"UserUID,omitempty"`
|
||||||
UserName string `gorm:"size:200;index;" json:"UserName" yaml:"UserName,omitempty"`
|
UserName string `gorm:"size:200;index;" json:"UserName" yaml:"UserName,omitempty"`
|
||||||
user *User `gorm:"-" yaml:"-"`
|
user *User `gorm:"foreignKey:UserUID;references:UserUID" yaml:"-"`
|
||||||
ClientName string `gorm:"size:200;" json:"ClientName" yaml:"ClientName,omitempty"`
|
ClientName string `gorm:"size:200;" json:"ClientName" yaml:"ClientName,omitempty"`
|
||||||
ClientRole string `gorm:"size:64;default:'';" json:"ClientRole" yaml:"ClientRole,omitempty"`
|
ClientRole string `gorm:"size:64;default:'';" json:"ClientRole" yaml:"ClientRole,omitempty"`
|
||||||
ClientType string `gorm:"type:VARBINARY(16)" json:"ClientType" yaml:"ClientType,omitempty"`
|
ClientType string `gorm:"size:16" json:"ClientType" yaml:"ClientType,omitempty"`
|
||||||
ClientURL string `gorm:"type:VARBINARY(255);default:'';column:client_url;" json:"ClientURL" yaml:"ClientURL,omitempty"`
|
ClientURL string `gorm:"size:255;default:'';column:client_url;" json:"ClientURL" yaml:"ClientURL,omitempty"`
|
||||||
CallbackURL string `gorm:"type:VARBINARY(255);default:'';column:callback_url;" json:"CallbackURL" yaml:"CallbackURL,omitempty"`
|
CallbackURL string `gorm:"size:255;default:'';column:callback_url;" json:"CallbackURL" yaml:"CallbackURL,omitempty"`
|
||||||
AuthProvider string `gorm:"type:VARBINARY(128);default:'';" json:"AuthProvider" yaml:"AuthProvider,omitempty"`
|
AuthProvider string `gorm:"size:128;default:'';" json:"AuthProvider" yaml:"AuthProvider,omitempty"`
|
||||||
AuthMethod string `gorm:"type:VARBINARY(128);default:'';" json:"AuthMethod" yaml:"AuthMethod,omitempty"`
|
AuthMethod string `gorm:"size:128;default:'';" json:"AuthMethod" yaml:"AuthMethod,omitempty"`
|
||||||
AuthScope string `gorm:"size:1024;default:'';" json:"AuthScope" yaml:"AuthScope,omitempty"`
|
AuthScope string `gorm:"size:1024;default:'';" json:"AuthScope" yaml:"AuthScope,omitempty"`
|
||||||
AuthExpires int64 `json:"AuthExpires" yaml:"AuthExpires,omitempty"`
|
AuthExpires int64 `json:"AuthExpires" yaml:"AuthExpires,omitempty"`
|
||||||
AuthTokens int64 `json:"AuthTokens" yaml:"AuthTokens,omitempty"`
|
AuthTokens int64 `json:"AuthTokens" yaml:"AuthTokens,omitempty"`
|
||||||
|
@@ -36,33 +36,33 @@ type Sessions []Session
|
|||||||
|
|
||||||
// Session represents a User session.
|
// Session represents a User session.
|
||||||
type Session struct {
|
type Session struct {
|
||||||
ID string `gorm:"type:VARBINARY(2048);primaryKey;autoIncrement:false;" json:"-" yaml:"ID"`
|
ID string `gorm:"size:2048;primaryKey;autoIncrement:false;" json:"-" yaml:"ID"`
|
||||||
authToken string `gorm:"-" yaml:"-"`
|
authToken string `gorm:"-" yaml:"-"`
|
||||||
UserUID string `gorm:"type:VARBINARY(42);index;default:'';" json:"UserUID" yaml:"UserUID,omitempty"`
|
UserUID string `gorm:"size:42;index;default:'';" json:"UserUID" yaml:"UserUID,omitempty"`
|
||||||
UserName string `gorm:"size:200;index;" json:"UserName" yaml:"UserName,omitempty"`
|
UserName string `gorm:"size:200;index;" json:"UserName" yaml:"UserName,omitempty"`
|
||||||
user *User `gorm:"-" yaml:"-"`
|
user *User `gorm:"-" yaml:"-"`
|
||||||
ClientUID string `gorm:"type:VARBINARY(42);index;default:'';" json:"ClientUID" yaml:"ClientUID,omitempty"`
|
ClientUID string `gorm:"size:42;index;default:'';" json:"ClientUID" yaml:"ClientUID,omitempty"`
|
||||||
ClientName string `gorm:"size:200;default:'';" json:"ClientName" yaml:"ClientName,omitempty"`
|
ClientName string `gorm:"size:200;default:'';" json:"ClientName" yaml:"ClientName,omitempty"`
|
||||||
ClientIP string `gorm:"size:64;column:client_ip;index" json:"ClientIP" yaml:"ClientIP,omitempty"`
|
ClientIP string `gorm:"size:64;column:client_ip;index" json:"ClientIP" yaml:"ClientIP,omitempty"`
|
||||||
client *Client `gorm:"-" yaml:"-"`
|
client *Client `gorm:"-" yaml:"-"`
|
||||||
AuthProvider string `gorm:"type:VARBINARY(128);default:'';" json:"AuthProvider" yaml:"AuthProvider,omitempty"`
|
AuthProvider string `gorm:"size:128;default:'';" json:"AuthProvider" yaml:"AuthProvider,omitempty"`
|
||||||
AuthMethod string `gorm:"type:VARBINARY(128);default:'';" json:"AuthMethod" yaml:"AuthMethod,omitempty"`
|
AuthMethod string `gorm:"size:128;default:'';" json:"AuthMethod" yaml:"AuthMethod,omitempty"`
|
||||||
AuthDomain string `gorm:"type:VARBINARY(255);default:'';" json:"AuthDomain" yaml:"AuthDomain,omitempty"`
|
AuthDomain string `gorm:"size:255;default:'';" json:"AuthDomain" yaml:"AuthDomain,omitempty"`
|
||||||
AuthID string `gorm:"type:VARBINARY(255);index;default:'';" json:"-" yaml:"AuthID,omitempty"`
|
AuthID string `gorm:"size:255;index;default:'';" json:"-" yaml:"AuthID,omitempty"`
|
||||||
AuthScope string `gorm:"size:1024;default:'';" json:"AuthScope" yaml:"AuthScope,omitempty"`
|
AuthScope string `gorm:"size:1024;default:'';" json:"AuthScope" yaml:"AuthScope,omitempty"`
|
||||||
GrantType string `gorm:"type:VARBINARY(64);default:'';" json:"GrantType" yaml:"GrantType,omitempty"`
|
GrantType string `gorm:"size:64;default:'';" json:"GrantType" yaml:"GrantType,omitempty"`
|
||||||
LastActive int64 `json:"LastActive" yaml:"LastActive,omitempty"`
|
LastActive int64 `json:"LastActive" yaml:"LastActive,omitempty"`
|
||||||
SessExpires int64 `gorm:"index" json:"Expires" yaml:"Expires,omitempty"`
|
SessExpires int64 `gorm:"index" json:"Expires" yaml:"Expires,omitempty"`
|
||||||
SessTimeout int64 `json:"Timeout" yaml:"Timeout,omitempty"`
|
SessTimeout int64 `json:"Timeout" yaml:"Timeout,omitempty"`
|
||||||
PreviewToken string `gorm:"type:VARBINARY(64);column:preview_token;default:'';" json:"-" yaml:"-"`
|
PreviewToken string `gorm:"size:64;column:preview_token;default:'';" json:"-" yaml:"-"`
|
||||||
DownloadToken string `gorm:"type:VARBINARY(64);column:download_token;default:'';" json:"-" yaml:"-"`
|
DownloadToken string `gorm:"size:64;column:download_token;default:'';" json:"-" yaml:"-"`
|
||||||
AccessToken string `gorm:"type:VARBINARY(4096);column:access_token;default:'';" json:"-" yaml:"-"`
|
AccessToken string `gorm:"size:4096;column:access_token;default:'';" json:"-" yaml:"-"`
|
||||||
RefreshToken string `gorm:"type:VARBINARY(512);column:refresh_token;default:'';" json:"-" yaml:"-"`
|
RefreshToken string `gorm:"size:512;column:refresh_token;default:'';" json:"-" yaml:"-"`
|
||||||
IdToken string `gorm:"type:VARBINARY(1024);column:id_token;default:'';" json:"IdToken,omitempty" yaml:"IdToken,omitempty"`
|
IdToken string `gorm:"size:1024;column:id_token;default:'';" json:"IdToken,omitempty" yaml:"IdToken,omitempty"`
|
||||||
UserAgent string `gorm:"size:512;" json:"UserAgent" yaml:"UserAgent,omitempty"`
|
UserAgent string `gorm:"size:512;" json:"UserAgent" yaml:"UserAgent,omitempty"`
|
||||||
DataJSON json.RawMessage `gorm:"type:VARBINARY(4096);" json:"-" yaml:"Data,omitempty"`
|
DataJSON json.RawMessage `json:"-" yaml:"Data,omitempty"`
|
||||||
data *SessionData `gorm:"-" yaml:"-"`
|
data *SessionData `gorm:"-" yaml:"-"`
|
||||||
RefID string `gorm:"type:VARBINARY(16);default:'';" json:"ID" yaml:"-"`
|
RefID string `gorm:"size:16;default:'';" json:"ID" yaml:"-"`
|
||||||
LoginIP string `gorm:"size:64;column:login_ip" json:"LoginIP" yaml:"-"`
|
LoginIP string `gorm:"size:64;column:login_ip" json:"LoginIP" yaml:"-"`
|
||||||
LoginAt time.Time `json:"LoginAt" yaml:"-"`
|
LoginAt time.Time `json:"LoginAt" yaml:"-"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt"`
|
||||||
|
@@ -45,11 +45,11 @@ type Users []User
|
|||||||
// User represents a person that may optionally log in as user.
|
// User represents a person that may optionally log in as user.
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int `gorm:"primaryKey" json:"ID" yaml:"-"`
|
ID int `gorm:"primaryKey" json:"ID" yaml:"-"`
|
||||||
UUID string `gorm:"type:VARBINARY(64);column:user_uuid;index;" json:"UUID,omitempty" yaml:"UUID,omitempty"`
|
UUID string `gorm:"size:64;column:user_uuid;index;" json:"UUID,omitempty" yaml:"UUID,omitempty"`
|
||||||
UserUID string `gorm:"type:VARBINARY(42);column:user_uid;uniqueIndex;" json:"UID" yaml:"UID"`
|
UserUID string `gorm:"size:42;column:user_uid;uniqueIndex;" json:"UID" yaml:"UID"`
|
||||||
AuthProvider string `gorm:"type:VARBINARY(128);default:'';" json:"AuthProvider" yaml:"AuthProvider,omitempty"`
|
AuthProvider string `gorm:"size:128;default:'';" json:"AuthProvider" yaml:"AuthProvider,omitempty"`
|
||||||
AuthMethod string `gorm:"type:VARBINARY(128);default:'';" json:"AuthMethod" yaml:"AuthMethod,omitempty"`
|
AuthMethod string `gorm:"size:128;default:'';" json:"AuthMethod" yaml:"AuthMethod,omitempty"`
|
||||||
AuthID string `gorm:"type:VARBINARY(255);index;default:'';" json:"AuthID" yaml:"AuthID,omitempty"`
|
AuthID string `gorm:"size:255;index;default:'';" json:"AuthID" yaml:"AuthID,omitempty"`
|
||||||
UserName string `gorm:"size:200;index;" json:"Name" yaml:"Name,omitempty"`
|
UserName string `gorm:"size:200;index;" json:"Name" yaml:"Name,omitempty"`
|
||||||
DisplayName string `gorm:"size:200;" json:"DisplayName" yaml:"DisplayName,omitempty"`
|
DisplayName string `gorm:"size:200;" json:"DisplayName" yaml:"DisplayName,omitempty"`
|
||||||
UserEmail string `gorm:"size:255;index;" json:"Email" yaml:"Email,omitempty"`
|
UserEmail string `gorm:"size:255;index;" json:"Email" yaml:"Email,omitempty"`
|
||||||
@@ -61,24 +61,24 @@ type User struct {
|
|||||||
LoginAt *time.Time `json:"LoginAt" yaml:"LoginAt,omitempty"`
|
LoginAt *time.Time `json:"LoginAt" yaml:"LoginAt,omitempty"`
|
||||||
ExpiresAt *time.Time `sql:"index" json:"ExpiresAt,omitempty" yaml:"ExpiresAt,omitempty"`
|
ExpiresAt *time.Time `sql:"index" json:"ExpiresAt,omitempty" yaml:"ExpiresAt,omitempty"`
|
||||||
WebDAV bool `gorm:"column:webdav;" json:"WebDAV" yaml:"WebDAV,omitempty"`
|
WebDAV bool `gorm:"column:webdav;" json:"WebDAV" yaml:"WebDAV,omitempty"`
|
||||||
BasePath string `gorm:"type:VARBINARY(1024);" json:"BasePath" yaml:"BasePath,omitempty"`
|
BasePath string `gorm:"size:1024;" json:"BasePath" yaml:"BasePath,omitempty"`
|
||||||
UploadPath string `gorm:"type:VARBINARY(1024);" json:"UploadPath" yaml:"UploadPath,omitempty"`
|
UploadPath string `gorm:"size:1024;" json:"UploadPath" yaml:"UploadPath,omitempty"`
|
||||||
CanInvite bool `json:"CanInvite" yaml:"CanInvite,omitempty"`
|
CanInvite bool `json:"CanInvite" yaml:"CanInvite,omitempty"`
|
||||||
InviteToken string `gorm:"type:VARBINARY(64);index;" json:"-" yaml:"-"`
|
InviteToken string `gorm:"size:64;index;" json:"-" yaml:"-"`
|
||||||
InvitedBy string `gorm:"size:64;" json:"-" yaml:"-"`
|
InvitedBy string `gorm:"size:64;" json:"-" yaml:"-"`
|
||||||
VerifyToken string `gorm:"type:VARBINARY(64);" json:"-" yaml:"-"`
|
VerifyToken string `gorm:"size:64;" json:"-" yaml:"-"`
|
||||||
VerifiedAt *time.Time `json:"VerifiedAt,omitempty" yaml:"VerifiedAt,omitempty"`
|
VerifiedAt *time.Time `json:"VerifiedAt,omitempty" yaml:"VerifiedAt,omitempty"`
|
||||||
ConsentAt *time.Time `json:"ConsentAt,omitempty" yaml:"ConsentAt,omitempty"`
|
ConsentAt *time.Time `json:"ConsentAt,omitempty" yaml:"ConsentAt,omitempty"`
|
||||||
BornAt *time.Time `sql:"index" json:"BornAt,omitempty" yaml:"BornAt,omitempty"`
|
BornAt *time.Time `sql:"index" json:"BornAt,omitempty" yaml:"BornAt,omitempty"`
|
||||||
UserDetails *UserDetails `gorm:"foreignKey:UserUID;references:UserUID;" json:"Details,omitempty" yaml:"Details,omitempty"`
|
UserDetails *UserDetails `gorm:"foreignKey:UserUID;references:UserUID;constraint:OnDelete:CASCADE" json:"Details,omitempty" yaml:"Details,omitempty"`
|
||||||
UserSettings *UserSettings `gorm:"foreignKey:UserUID;references:UserUID" json:"Settings,omitempty" yaml:"Settings,omitempty"`
|
UserSettings *UserSettings `gorm:"foreignKey:UserUID;references:UserUID;constraint:OnDelete:CASCADE" json:"Settings,omitempty" yaml:"Settings,omitempty"`
|
||||||
UserShares UserShares `gorm:"-" json:"Shares,omitempty" yaml:"Shares,omitempty"`
|
UserShares []UserShare `gorm:"foreignKey:UserUID;references:UserUID" json:"Shares,omitempty" yaml:"Shares,omitempty"`
|
||||||
ResetToken string `gorm:"type:VARBINARY(64);" json:"-" yaml:"-"`
|
ResetToken string `gorm:"size:64;" json:"-" yaml:"-"`
|
||||||
PreviewToken string `gorm:"type:VARBINARY(64);column:preview_token;" json:"-" yaml:"-"`
|
PreviewToken string `gorm:"size:64;column:preview_token;" json:"-" yaml:"-"`
|
||||||
DownloadToken string `gorm:"type:VARBINARY(64);column:download_token;" json:"-" yaml:"-"`
|
DownloadToken string `gorm:"size:64;column:download_token;" json:"-" yaml:"-"`
|
||||||
Thumb string `gorm:"type:VARBINARY(128);index;default:'';" json:"Thumb" yaml:"Thumb,omitempty"`
|
Thumb string `gorm:"size:128;index;default:'';" json:"Thumb" yaml:"Thumb,omitempty"`
|
||||||
ThumbSrc string `gorm:"type:VARBINARY(8);default:'';" json:"ThumbSrc" yaml:"ThumbSrc,omitempty"`
|
ThumbSrc string `gorm:"size:8;default:'';" json:"ThumbSrc" yaml:"ThumbSrc,omitempty"`
|
||||||
RefID string `gorm:"type:VARBINARY(16);" json:"-" yaml:"-"`
|
RefID string `gorm:"size:16;" json:"-" yaml:"-"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
||||||
DeletedAt *time.Time `sql:"index" json:"DeletedAt,omitempty" yaml:"-"`
|
DeletedAt *time.Time `sql:"index" json:"DeletedAt,omitempty" yaml:"-"`
|
||||||
@@ -1090,7 +1090,7 @@ func (m *User) NoShares() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.UserShares.Empty()
|
return UserShares(m.UserShares).Empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasShares checks if the user has any shares.
|
// HasShares checks if the user has any shares.
|
||||||
@@ -1105,7 +1105,7 @@ func (m *User) HasShare(uid string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the share list contains the specified UID.
|
// Check if the share list contains the specified UID.
|
||||||
return m.UserShares.Contains(uid)
|
return UserShares(m.UserShares).Contains(uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SharedUIDs returns shared entity UIDs.
|
// SharedUIDs returns shared entity UIDs.
|
||||||
@@ -1114,7 +1114,7 @@ func (m *User) SharedUIDs() UIDs {
|
|||||||
m.RefreshShares()
|
m.RefreshShares()
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.UserShares.UIDs()
|
return UserShares(m.UserShares).UIDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedeemToken updates shared entity UIDs using the specified token.
|
// RedeemToken updates shared entity UIDs using the specified token.
|
||||||
|
@@ -17,12 +17,12 @@ const (
|
|||||||
|
|
||||||
// UserDetails represents user profile information.
|
// UserDetails represents user profile information.
|
||||||
type UserDetails struct {
|
type UserDetails struct {
|
||||||
UserUID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false;" json:"-" yaml:"-"`
|
UserUID string `gorm:"size:42;uniqueIndex;" json:"-" yaml:"-"`
|
||||||
SubjUID string `gorm:"type:VARBINARY(42);index;" json:"SubjUID,omitempty" yaml:"SubjUID,omitempty"`
|
SubjUID string `gorm:"size:42;index;" json:"SubjUID,omitempty" yaml:"SubjUID,omitempty"`
|
||||||
SubjSrc string `gorm:"type:VARBINARY(8);default:'';" json:"-" yaml:"SubjSrc,omitempty"`
|
SubjSrc string `gorm:"size:8;default:'';" json:"-" yaml:"SubjSrc,omitempty"`
|
||||||
PlaceID string `gorm:"type:VARBINARY(42);index;default:'zz'" json:"-" yaml:"-"`
|
PlaceID string `gorm:"size:42;index;default:'zz'" json:"-" yaml:"-"`
|
||||||
PlaceSrc string `gorm:"type:VARBINARY(8);" json:"-" yaml:"PlaceSrc,omitempty"`
|
PlaceSrc string `gorm:"size:8;" json:"-" yaml:"PlaceSrc,omitempty"`
|
||||||
CellID string `gorm:"type:VARBINARY(42);index;default:'zz'" json:"-" yaml:"CellID,omitempty"`
|
CellID string `gorm:"size:42;index;default:'zz'" json:"-" yaml:"CellID,omitempty"`
|
||||||
BirthYear int `json:"BirthYear" yaml:"BirthYear,omitempty"`
|
BirthYear int `json:"BirthYear" yaml:"BirthYear,omitempty"`
|
||||||
BirthMonth int `json:"BirthMonth" yaml:"BirthMonth,omitempty"`
|
BirthMonth int `json:"BirthMonth" yaml:"BirthMonth,omitempty"`
|
||||||
BirthDay int `json:"BirthDay" yaml:"BirthDay,omitempty"`
|
BirthDay int `json:"BirthDay" yaml:"BirthDay,omitempty"`
|
||||||
@@ -32,23 +32,23 @@ type UserDetails struct {
|
|||||||
FamilyName string `gorm:"size:64;" json:"FamilyName" yaml:"FamilyName,omitempty"`
|
FamilyName string `gorm:"size:64;" json:"FamilyName" yaml:"FamilyName,omitempty"`
|
||||||
NameSuffix string `gorm:"size:32;" json:"NameSuffix" yaml:"NameSuffix,omitempty"`
|
NameSuffix string `gorm:"size:32;" json:"NameSuffix" yaml:"NameSuffix,omitempty"`
|
||||||
NickName string `gorm:"size:64;" json:"NickName" yaml:"NickName,omitempty"`
|
NickName string `gorm:"size:64;" json:"NickName" yaml:"NickName,omitempty"`
|
||||||
NameSrc string `gorm:"type:VARBINARY(8);" json:"NameSrc" yaml:"NameSrc,omitempty"`
|
NameSrc string `gorm:"size:8;" json:"NameSrc" yaml:"NameSrc,omitempty"`
|
||||||
UserGender string `gorm:"size:16;" json:"Gender" yaml:"Gender,omitempty"`
|
UserGender string `gorm:"size:16;" json:"Gender" yaml:"Gender,omitempty"`
|
||||||
UserAbout string `gorm:"size:512;" json:"About" yaml:"About,omitempty"`
|
UserAbout string `gorm:"size:512;" json:"About" yaml:"About,omitempty"`
|
||||||
UserBio string `gorm:"size:2048;" json:"Bio" yaml:"Bio,omitempty"`
|
UserBio string `gorm:"size:2048;" json:"Bio" yaml:"Bio,omitempty"`
|
||||||
UserLocation string `gorm:"size:512;" json:"Location" yaml:"Location,omitempty"`
|
UserLocation string `gorm:"size:512;" json:"Location" yaml:"Location,omitempty"`
|
||||||
UserCountry string `gorm:"type:VARBINARY(2);" json:"Country" yaml:"Country,omitempty"`
|
UserCountry string `gorm:"size:2;" json:"Country" yaml:"Country,omitempty"`
|
||||||
UserPhone string `gorm:"size:32;" json:"Phone" yaml:"Phone,omitempty"`
|
UserPhone string `gorm:"size:32;" json:"Phone" yaml:"Phone,omitempty"`
|
||||||
SiteURL string `gorm:"type:VARBINARY(512);column:site_url" json:"SiteURL" yaml:"SiteURL,omitempty"`
|
SiteURL string `gorm:"size:512;column:site_url" json:"SiteURL" yaml:"SiteURL,omitempty"`
|
||||||
ProfileURL string `gorm:"type:VARBINARY(512);column:profile_url" json:"ProfileURL" yaml:"ProfileURL,omitempty"`
|
ProfileURL string `gorm:"size:512;column:profile_url" json:"ProfileURL" yaml:"ProfileURL,omitempty"`
|
||||||
FeedURL string `gorm:"type:VARBINARY(512);column:feed_url" json:"FeedURL,omitempty" yaml:"FeedURL,omitempty"`
|
FeedURL string `gorm:"size:512;column:feed_url" json:"FeedURL,omitempty" yaml:"FeedURL,omitempty"`
|
||||||
AvatarURL string `gorm:"type:VARBINARY(512);column:avatar_url" json:"AvatarURL,omitempty" yaml:"AvatarURL,omitempty"`
|
AvatarURL string `gorm:"size:512;column:avatar_url" json:"AvatarURL,omitempty" yaml:"AvatarURL,omitempty"`
|
||||||
OrgTitle string `gorm:"size:64;" json:"OrgTitle" yaml:"OrgTitle,omitempty"`
|
OrgTitle string `gorm:"size:64;" json:"OrgTitle" yaml:"OrgTitle,omitempty"`
|
||||||
OrgName string `gorm:"size:128;" json:"OrgName" yaml:"OrgName,omitempty"`
|
OrgName string `gorm:"size:128;" json:"OrgName" yaml:"OrgName,omitempty"`
|
||||||
OrgEmail string `gorm:"size:255;index;" json:"OrgEmail" yaml:"OrgEmail,omitempty"`
|
OrgEmail string `gorm:"size:255;index;" json:"OrgEmail" yaml:"OrgEmail,omitempty"`
|
||||||
OrgPhone string `gorm:"size:32;" json:"OrgPhone" yaml:"OrgPhone,omitempty"`
|
OrgPhone string `gorm:"size:32;" json:"OrgPhone" yaml:"OrgPhone,omitempty"`
|
||||||
OrgURL string `gorm:"type:VARBINARY(512);column:org_url" json:"OrgURL" yaml:"OrgURL,omitempty"`
|
OrgURL string `gorm:"size:512;column:org_url" json:"OrgURL" yaml:"OrgURL,omitempty"`
|
||||||
IdURL string `gorm:"type:VARBINARY(512);column:id_url;" json:"IdURL,omitempty" yaml:"IdURL,omitempty"`
|
IdURL string `gorm:"size:512;column:id_url;" json:"IdURL,omitempty" yaml:"IdURL,omitempty"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
||||||
}
|
}
|
||||||
|
@@ -10,21 +10,21 @@ import (
|
|||||||
|
|
||||||
// UserSettings represents user preferences.
|
// UserSettings represents user preferences.
|
||||||
type UserSettings struct {
|
type UserSettings struct {
|
||||||
UserUID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false" json:"-" yaml:"UserUID"`
|
UserUID string `gorm:"size:42;uniqueIndex;" json:"-" yaml:"UserUID"`
|
||||||
UITheme string `gorm:"type:VARBINARY(32);column:ui_theme;" json:"UITheme,omitempty" yaml:"UITheme,omitempty"`
|
UITheme string `gorm:"size:32;column:ui_theme;" json:"UITheme,omitempty" yaml:"UITheme,omitempty"`
|
||||||
UILanguage string `gorm:"type:VARBINARY(32);column:ui_language;" json:"UILanguage,omitempty" yaml:"UILanguage,omitempty"`
|
UILanguage string `gorm:"size:32;column:ui_language;" json:"UILanguage,omitempty" yaml:"UILanguage,omitempty"`
|
||||||
UITimeZone string `gorm:"type:VARBINARY(64);column:ui_time_zone;" json:"UITimeZone,omitempty" yaml:"UITimeZone,omitempty"`
|
UITimeZone string `gorm:"size:64;column:ui_time_zone;" json:"UITimeZone,omitempty" yaml:"UITimeZone,omitempty"`
|
||||||
MapsStyle string `gorm:"type:VARBINARY(32);" json:"MapsStyle,omitempty" yaml:"MapsStyle,omitempty"`
|
MapsStyle string `gorm:"size:32;" json:"MapsStyle,omitempty" yaml:"MapsStyle,omitempty"`
|
||||||
MapsAnimate int `gorm:"default:0;" json:"MapsAnimate,omitempty" yaml:"MapsAnimate,omitempty"`
|
MapsAnimate int `gorm:"default:0;" json:"MapsAnimate,omitempty" yaml:"MapsAnimate,omitempty"`
|
||||||
IndexPath string `gorm:"type:VARBINARY(1024);" json:"IndexPath,omitempty" yaml:"IndexPath,omitempty"`
|
IndexPath string `gorm:"size:1024;" json:"IndexPath,omitempty" yaml:"IndexPath,omitempty"`
|
||||||
IndexRescan int `gorm:"default:0;" json:"IndexRescan,omitempty" yaml:"IndexRescan,omitempty"`
|
IndexRescan int `gorm:"default:0;" json:"IndexRescan,omitempty" yaml:"IndexRescan,omitempty"`
|
||||||
ImportPath string `gorm:"type:VARBINARY(1024);" json:"ImportPath,omitempty" yaml:"ImportPath,omitempty"`
|
ImportPath string `gorm:"size:1024;" json:"ImportPath,omitempty" yaml:"ImportPath,omitempty"`
|
||||||
ImportMove int `gorm:"default:0;" json:"ImportMove,omitempty" yaml:"ImportMove,omitempty"`
|
ImportMove int `gorm:"default:0;" json:"ImportMove,omitempty" yaml:"ImportMove,omitempty"`
|
||||||
DownloadOriginals int `gorm:"default:0;" json:"DownloadOriginals,omitempty" yaml:"DownloadOriginals,omitempty"`
|
DownloadOriginals int `gorm:"default:0;" json:"DownloadOriginals,omitempty" yaml:"DownloadOriginals,omitempty"`
|
||||||
DownloadMediaRaw int `gorm:"default:0;" json:"DownloadMediaRaw,omitempty" yaml:"DownloadMediaRaw,omitempty"`
|
DownloadMediaRaw int `gorm:"default:0;" json:"DownloadMediaRaw,omitempty" yaml:"DownloadMediaRaw,omitempty"`
|
||||||
DownloadMediaSidecar int `gorm:"default:0;" json:"DownloadMediaSidecar,omitempty" yaml:"DownloadMediaSidecar,omitempty"`
|
DownloadMediaSidecar int `gorm:"default:0;" json:"DownloadMediaSidecar,omitempty" yaml:"DownloadMediaSidecar,omitempty"`
|
||||||
UploadPath string `gorm:"type:VARBINARY(1024);" json:"UploadPath,omitempty" yaml:"UploadPath,omitempty"`
|
UploadPath string `gorm:"size:1024;" json:"UploadPath,omitempty" yaml:"UploadPath,omitempty"`
|
||||||
DefaultPage string `gorm:"type:VARBINARY(128);" json:"DefaultPage,omitempty" yaml:"DefaultPage,omitempty"`
|
DefaultPage string `gorm:"size:128;" json:"DefaultPage,omitempty" yaml:"DefaultPage,omitempty"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
||||||
}
|
}
|
||||||
|
@@ -63,13 +63,13 @@ func (m UserShares) Contains(uid string) bool {
|
|||||||
|
|
||||||
// UserShare represents content shared with a user.
|
// UserShare represents content shared with a user.
|
||||||
type UserShare struct {
|
type UserShare struct {
|
||||||
UserUID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false;" json:"-" yaml:"UserUID"`
|
UserUID string `gorm:"size:42;primaryKey;autoIncrement:false;" json:"-" yaml:"UserUID"`
|
||||||
ShareUID string `gorm:"type:VARBINARY(42);primaryKey;index;" json:"ShareUID" yaml:"ShareUID"`
|
ShareUID string `gorm:"size:42;primaryKey;index;" json:"ShareUID" yaml:"ShareUID"`
|
||||||
LinkUID string `gorm:"type:VARBINARY(42);" json:"LinkUID,omitempty" yaml:"LinkUID,omitempty"`
|
LinkUID string `gorm:"size:42;" json:"LinkUID,omitempty" yaml:"LinkUID,omitempty"`
|
||||||
ExpiresAt *time.Time `sql:"index" json:"ExpiresAt,omitempty" yaml:"ExpiresAt,omitempty"`
|
ExpiresAt *time.Time `sql:"index" json:"ExpiresAt,omitempty" yaml:"ExpiresAt,omitempty"`
|
||||||
Comment string `gorm:"size:512;" json:"Comment,omitempty" yaml:"Comment,omitempty"`
|
Comment string `gorm:"size:512;" json:"Comment,omitempty" yaml:"Comment,omitempty"`
|
||||||
Perm uint `json:"Perm,omitempty" yaml:"Perm,omitempty"`
|
Perm uint `json:"Perm,omitempty" yaml:"Perm,omitempty"`
|
||||||
RefID string `gorm:"type:VARBINARY(16);" json:"-" yaml:"-"`
|
RefID string `gorm:"size:16;" json:"-" yaml:"-"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ type Cameras []Camera
|
|||||||
// Camera model and make (as extracted from UpdateExif metadata)
|
// Camera model and make (as extracted from UpdateExif metadata)
|
||||||
type Camera struct {
|
type Camera struct {
|
||||||
ID uint `gorm:"primaryKey" json:"ID" yaml:"ID"`
|
ID uint `gorm:"primaryKey" json:"ID" yaml:"ID"`
|
||||||
CameraSlug string `gorm:"type:VARBINARY(160);uniqueIndex;" json:"Slug" yaml:"-"`
|
CameraSlug string `gorm:"size:160;uniqueIndex;" json:"Slug" yaml:"-"`
|
||||||
CameraName string `gorm:"type:VARCHAR(160);" json:"Name" yaml:"Name"`
|
CameraName string `gorm:"type:VARCHAR(160);" json:"Name" yaml:"Name"`
|
||||||
CameraMake string `gorm:"type:VARCHAR(160);" json:"Make" yaml:"Make,omitempty"`
|
CameraMake string `gorm:"type:VARCHAR(160);" json:"Make" yaml:"Make,omitempty"`
|
||||||
CameraModel string `gorm:"type:VARCHAR(160);" json:"Model" yaml:"Model,omitempty"`
|
CameraModel string `gorm:"type:VARCHAR(160);" json:"Model" yaml:"Model,omitempty"`
|
||||||
|
@@ -15,13 +15,13 @@ var cellMutex = sync.Mutex{}
|
|||||||
|
|
||||||
// Cell represents an S2 cell with metadata and reference to a place.
|
// Cell represents an S2 cell with metadata and reference to a place.
|
||||||
type Cell struct {
|
type Cell struct {
|
||||||
ID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false;" json:"ID" yaml:"ID"`
|
ID string `gorm:"size:42;primaryKey;autoIncrement:false;" json:"ID" yaml:"ID"`
|
||||||
CellName string `gorm:"type:VARCHAR(200);" json:"Name" yaml:"Name,omitempty"`
|
CellName string `gorm:"type:VARCHAR(200);" json:"Name" yaml:"Name,omitempty"`
|
||||||
CellStreet string `gorm:"type:VARCHAR(100);" json:"Street" yaml:"Street,omitempty"`
|
CellStreet string `gorm:"type:VARCHAR(100);" json:"Street" yaml:"Street,omitempty"`
|
||||||
CellPostcode string `gorm:"type:VARCHAR(50);" json:"Postcode" yaml:"Postcode,omitempty"`
|
CellPostcode string `gorm:"type:VARCHAR(50);" json:"Postcode" yaml:"Postcode,omitempty"`
|
||||||
CellCategory string `gorm:"type:VARCHAR(50);" json:"Category" yaml:"Category,omitempty"`
|
CellCategory string `gorm:"type:VARCHAR(50);" json:"Category" yaml:"Category,omitempty"`
|
||||||
PlaceID string `gorm:"type:VARBINARY(42);default:'zz'" json:"-" yaml:"PlaceID"`
|
PlaceID string `gorm:"size:42;default:'zz'" json:"-" yaml:"PlaceID"`
|
||||||
Place *Place `gorm:"PRELOAD:true" json:"Place" yaml:"-"`
|
Place *Place `json:"Place" yaml:"-"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
||||||
}
|
}
|
||||||
|
@@ -19,13 +19,13 @@ type Countries []Country
|
|||||||
|
|
||||||
// Country represents a country location, used for labeling photos.
|
// Country represents a country location, used for labeling photos.
|
||||||
type Country struct {
|
type Country struct {
|
||||||
ID string `gorm:"type:VARBINARY(2);primaryKey" json:"ID" yaml:"ID"`
|
ID string `gorm:"size:2;primaryKey" json:"ID" yaml:"ID"`
|
||||||
CountrySlug string `gorm:"type:VARBINARY(160);uniqueIndex;" json:"Slug" yaml:"-"`
|
CountrySlug string `gorm:"size:160;uniqueIndex;" json:"Slug" yaml:"-"`
|
||||||
CountryName string `gorm:"type:VARCHAR(160);" json:"Name" yaml:"Name,omitempty"`
|
CountryName string `gorm:"type:VARCHAR(160);" json:"Name" yaml:"Name,omitempty"`
|
||||||
CountryDescription string `gorm:"type:VARCHAR(2048);" json:"Description,omitempty" yaml:"Description,omitempty"`
|
CountryDescription string `gorm:"type:VARCHAR(2048);" json:"Description,omitempty" yaml:"Description,omitempty"`
|
||||||
CountryNotes string `gorm:"type:VARCHAR(1024);" json:"Notes,omitempty" yaml:"Notes,omitempty"`
|
CountryNotes string `gorm:"type:VARCHAR(1024);" json:"Notes,omitempty" yaml:"Notes,omitempty"`
|
||||||
CountryPhoto *Photo `json:"-" yaml:"-"`
|
CountryPhoto *Photo `json:"-" yaml:"-"`
|
||||||
CountryPhotoID uint `json:"-" yaml:"-"`
|
CountryPhotoID *uint `json:"-" yaml:"-"`
|
||||||
New bool `gorm:"-" json:"-" yaml:"-"`
|
New bool `gorm:"-" json:"-" yaml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ var CountryFixtures = CountryMap{
|
|||||||
CountryDescription: "Country description",
|
CountryDescription: "Country description",
|
||||||
CountryNotes: "Country Notes",
|
CountryNotes: "Country Notes",
|
||||||
CountryPhoto: nil,
|
CountryPhoto: nil,
|
||||||
CountryPhotoID: 0,
|
CountryPhotoID: nil,
|
||||||
New: false,
|
New: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/logger"
|
"gorm.io/gorm/logger"
|
||||||
@@ -14,14 +15,16 @@ import (
|
|||||||
// Supported test databases.
|
// Supported test databases.
|
||||||
const (
|
const (
|
||||||
MySQL = "mysql"
|
MySQL = "mysql"
|
||||||
|
Postgres = "postgres"
|
||||||
SQLite3 = "sqlite"
|
SQLite3 = "sqlite"
|
||||||
SQLiteTestDB = ".test.db"
|
SQLiteTestDB = ".test.db"
|
||||||
SQLiteMemoryDSN = ":memory:?cache=shared"
|
SQLiteMemoryDSN = ":memory:?cache=shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
var drivers = map[string]func(string) gorm.Dialector{
|
var drivers = map[string]func(string) gorm.Dialector{
|
||||||
MySQL: mysql.Open,
|
MySQL: mysql.Open,
|
||||||
SQLite3: sqlite.Open,
|
Postgres: postgres.Open,
|
||||||
|
SQLite3: sqlite.Open,
|
||||||
}
|
}
|
||||||
|
|
||||||
// dbConn is the global gorm.DB connection provider.
|
// dbConn is the global gorm.DB connection provider.
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
// TestEntity is an entity dedicated to test database management functionality.
|
// TestEntity is an entity dedicated to test database management functionality.
|
||||||
type TestEntity struct {
|
type TestEntity struct {
|
||||||
ID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false;" json:"TestID" yaml:"TestID"`
|
ID string `gorm:"size:42;primaryKey;autoIncrement:false;" json:"TestID" yaml:"TestID"`
|
||||||
TestLabel string `gorm:"type:VARCHAR(400);uniqueIndex;" json:"Label" yaml:"Label"`
|
TestLabel string `gorm:"type:VARCHAR(400);uniqueIndex;" json:"Label" yaml:"Label"`
|
||||||
TestCount int `gorm:"default:1" json:"Count" yaml:"-"`
|
TestCount int `gorm:"default:1" json:"Count" yaml:"-"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
|
@@ -14,19 +14,19 @@ var photoDetailsMutex = sync.Mutex{}
|
|||||||
type Details struct {
|
type Details struct {
|
||||||
PhotoID uint `gorm:"primaryKey;autoIncrement:false" yaml:"-"`
|
PhotoID uint `gorm:"primaryKey;autoIncrement:false" yaml:"-"`
|
||||||
Keywords string `gorm:"type:VARCHAR(2048);" json:"Keywords" yaml:"Keywords"`
|
Keywords string `gorm:"type:VARCHAR(2048);" json:"Keywords" yaml:"Keywords"`
|
||||||
KeywordsSrc string `gorm:"type:VARBINARY(8);" json:"KeywordsSrc" yaml:"KeywordsSrc,omitempty"`
|
KeywordsSrc string `gorm:"size:8;" json:"KeywordsSrc" yaml:"KeywordsSrc,omitempty"`
|
||||||
Notes string `gorm:"type:VARCHAR(2048);" json:"Notes" yaml:"Notes,omitempty"`
|
Notes string `gorm:"type:VARCHAR(2048);" json:"Notes" yaml:"Notes,omitempty"`
|
||||||
NotesSrc string `gorm:"type:VARBINARY(8);" json:"NotesSrc" yaml:"NotesSrc,omitempty"`
|
NotesSrc string `gorm:"size:8;" json:"NotesSrc" yaml:"NotesSrc,omitempty"`
|
||||||
Subject string `gorm:"type:VARCHAR(1024);" json:"Subject" yaml:"Subject,omitempty"`
|
Subject string `gorm:"type:VARCHAR(1024);" json:"Subject" yaml:"Subject,omitempty"`
|
||||||
SubjectSrc string `gorm:"type:VARBINARY(8);" json:"SubjectSrc" yaml:"SubjectSrc,omitempty"`
|
SubjectSrc string `gorm:"size:8;" json:"SubjectSrc" yaml:"SubjectSrc,omitempty"`
|
||||||
Artist string `gorm:"type:VARCHAR(1024);" json:"Artist" yaml:"Artist,omitempty"`
|
Artist string `gorm:"type:VARCHAR(1024);" json:"Artist" yaml:"Artist,omitempty"`
|
||||||
ArtistSrc string `gorm:"type:VARBINARY(8);" json:"ArtistSrc" yaml:"ArtistSrc,omitempty"`
|
ArtistSrc string `gorm:"size:8;" json:"ArtistSrc" yaml:"ArtistSrc,omitempty"`
|
||||||
Copyright string `gorm:"type:VARCHAR(1024);" json:"Copyright" yaml:"Copyright,omitempty"`
|
Copyright string `gorm:"type:VARCHAR(1024);" json:"Copyright" yaml:"Copyright,omitempty"`
|
||||||
CopyrightSrc string `gorm:"type:VARBINARY(8);" json:"CopyrightSrc" yaml:"CopyrightSrc,omitempty"`
|
CopyrightSrc string `gorm:"size:8;" json:"CopyrightSrc" yaml:"CopyrightSrc,omitempty"`
|
||||||
License string `gorm:"type:VARCHAR(1024);" json:"License" yaml:"License,omitempty"`
|
License string `gorm:"type:VARCHAR(1024);" json:"License" yaml:"License,omitempty"`
|
||||||
LicenseSrc string `gorm:"type:VARBINARY(8);" json:"LicenseSrc" yaml:"LicenseSrc,omitempty"`
|
LicenseSrc string `gorm:"size:8;" json:"LicenseSrc" yaml:"LicenseSrc,omitempty"`
|
||||||
Software string `gorm:"type:VARCHAR(1024);" json:"Software" yaml:"Software,omitempty"`
|
Software string `gorm:"type:VARCHAR(1024);" json:"Software" yaml:"Software,omitempty"`
|
||||||
SoftwareSrc string `gorm:"type:VARBINARY(8);" json:"SoftwareSrc" yaml:"SoftwareSrc,omitempty"`
|
SoftwareSrc string `gorm:"size:8;" json:"SoftwareSrc" yaml:"SoftwareSrc,omitempty"`
|
||||||
CreatedAt time.Time `yaml:"-"`
|
CreatedAt time.Time `yaml:"-"`
|
||||||
UpdatedAt time.Time `yaml:"-"`
|
UpdatedAt time.Time `yaml:"-"`
|
||||||
}
|
}
|
||||||
|
@@ -11,9 +11,9 @@ type DuplicatesMap map[string]Duplicate
|
|||||||
|
|
||||||
// Duplicate represents an exact file duplicate.
|
// Duplicate represents an exact file duplicate.
|
||||||
type Duplicate struct {
|
type Duplicate struct {
|
||||||
FileName string `gorm:"type:VARBINARY(755);primaryKey;" json:"Name" yaml:"Name"`
|
FileName string `gorm:"size:755;primaryKey;" json:"Name" yaml:"Name"`
|
||||||
FileRoot string `gorm:"type:VARBINARY(16);primaryKey;default:'/';" json:"Root" yaml:"Root,omitempty"`
|
FileRoot string `gorm:"size:16;primaryKey;default:'/';" json:"Root" yaml:"Root,omitempty"`
|
||||||
FileHash string `gorm:"type:VARBINARY(128);default:'';index" json:"Hash" yaml:"Hash,omitempty"`
|
FileHash string `gorm:"size:128;default:'';index" json:"Hash" yaml:"Hash,omitempty"`
|
||||||
FileSize int64 `json:"Size" yaml:"Size,omitempty"`
|
FileSize int64 `json:"Size" yaml:"Size,omitempty"`
|
||||||
ModTime int64 `json:"ModTime" yaml:"-"`
|
ModTime int64 `json:"ModTime" yaml:"-"`
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ func LabelCounts() LabelPhotoCounts {
|
|||||||
JOIN photos ph ON pl.photo_id = ph.id
|
JOIN photos ph ON pl.photo_id = ph.id
|
||||||
WHERE pl.uncertainty < 100
|
WHERE pl.uncertainty < 100
|
||||||
AND ph.photo_quality > -1
|
AND ph.photo_quality > -1
|
||||||
AND ph.photo_private = 0
|
AND ph.photo_private = FALSE
|
||||||
AND ph.deleted_at IS NULL GROUP BY l.id
|
AND ph.deleted_at IS NULL GROUP BY l.id
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT l.id AS label_id, COUNT(*) AS photo_count FROM labels l
|
SELECT l.id AS label_id, COUNT(*) AS photo_count FROM labels l
|
||||||
@@ -38,7 +38,7 @@ func LabelCounts() LabelPhotoCounts {
|
|||||||
JOIN photos ph ON pl.photo_id = ph.id
|
JOIN photos ph ON pl.photo_id = ph.id
|
||||||
WHERE pl.uncertainty < 100
|
WHERE pl.uncertainty < 100
|
||||||
AND ph.photo_quality > -1
|
AND ph.photo_quality > -1
|
||||||
AND ph.photo_private = 0
|
AND ph.photo_private = FALSE
|
||||||
AND ph.deleted_at IS NULL GROUP BY l.id) counts GROUP BY label_id
|
AND ph.deleted_at IS NULL GROUP BY l.id) counts GROUP BY label_id
|
||||||
`).Scan(&result).Error; err != nil {
|
`).Scan(&result).Error; err != nil {
|
||||||
log.Errorf("label-count: %s", err.Error())
|
log.Errorf("label-count: %s", err.Error())
|
||||||
@@ -59,7 +59,7 @@ func UpdatePlacesCounts() (err error) {
|
|||||||
UpdateColumn("photo_count", gorm.Expr("(SELECT COUNT(*) FROM photos p "+
|
UpdateColumn("photo_count", gorm.Expr("(SELECT COUNT(*) FROM photos p "+
|
||||||
"WHERE places.id = p.place_id "+
|
"WHERE places.id = p.place_id "+
|
||||||
"AND p.photo_quality > -1 "+
|
"AND p.photo_quality > -1 "+
|
||||||
"AND p.photo_private = 0 "+
|
"AND p.photo_private = FALSE "+
|
||||||
"AND p.deleted_at IS NULL)"))
|
"AND p.deleted_at IS NULL)"))
|
||||||
|
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
@@ -87,7 +87,7 @@ func UpdateSubjectCounts() (err error) {
|
|||||||
condition := gorm.Expr("subj_type = ?", SubjPerson)
|
condition := gorm.Expr("subj_type = ?", SubjPerson)
|
||||||
|
|
||||||
switch DbDialect() {
|
switch DbDialect() {
|
||||||
case MySQL:
|
case MySQL, Postgres:
|
||||||
res = Db().Exec(`UPDATE ? LEFT JOIN (
|
res = Db().Exec(`UPDATE ? LEFT JOIN (
|
||||||
SELECT m.subj_uid, COUNT(DISTINCT f.id) AS subj_files, COUNT(DISTINCT f.photo_id) AS subj_photos FROM ? f
|
SELECT m.subj_uid, COUNT(DISTINCT f.id) AS subj_files, COUNT(DISTINCT f.photo_id) AS subj_photos FROM ? f
|
||||||
JOIN ? m ON f.file_uid = m.file_uid AND m.subj_uid IS NOT NULL AND m.subj_uid <> '' AND m.subj_uid IS NOT NULL
|
JOIN ? m ON f.file_uid = m.file_uid AND m.subj_uid IS NOT NULL AND m.subj_uid <> '' AND m.subj_uid IS NOT NULL
|
||||||
@@ -133,17 +133,17 @@ func UpdateLabelCounts() (err error) {
|
|||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
var res *gorm.DB
|
var res *gorm.DB
|
||||||
if IsDialect(MySQL) {
|
if IsDialect(MySQL) || IsDialect(Postgres) {
|
||||||
res = Db().Exec(`UPDATE labels LEFT JOIN (
|
res = Db().Exec(`UPDATE labels LEFT JOIN (
|
||||||
SELECT p2.label_id, COUNT(DISTINCT photo_id) AS label_photos FROM (
|
SELECT p2.label_id, COUNT(DISTINCT photo_id) AS label_photos FROM (
|
||||||
SELECT pl.label_id as label_id, p.id AS photo_id FROM photos p
|
SELECT pl.label_id as label_id, p.id AS photo_id FROM photos p
|
||||||
JOIN photos_labels pl ON pl.photo_id = p.id AND pl.uncertainty < 100
|
JOIN photos_labels pl ON pl.photo_id = p.id AND pl.uncertainty < 100
|
||||||
WHERE p.photo_quality > -1 AND p.photo_private = 0 AND p.deleted_at IS NULL
|
WHERE p.photo_quality > -1 AND p.photo_private = FALSE AND p.deleted_at IS NULL
|
||||||
UNION
|
UNION
|
||||||
SELECT c.category_id as label_id, p.id AS photo_id FROM photos p
|
SELECT c.category_id as label_id, p.id AS photo_id FROM photos p
|
||||||
JOIN photos_labels pl ON pl.photo_id = p.id AND pl.uncertainty < 100
|
JOIN photos_labels pl ON pl.photo_id = p.id AND pl.uncertainty < 100
|
||||||
JOIN categories c ON c.label_id = pl.label_id
|
JOIN categories c ON c.label_id = pl.label_id
|
||||||
WHERE p.photo_quality > -1 AND p.photo_private = 0 AND p.deleted_at IS NULL
|
WHERE p.photo_quality > -1 AND p.photo_private = FALSE AND p.deleted_at IS NULL
|
||||||
) p2 GROUP BY p2.label_id
|
) p2 GROUP BY p2.label_id
|
||||||
) b ON b.label_id = labels.id
|
) b ON b.label_id = labels.id
|
||||||
SET photo_count = CASE WHEN b.label_photos IS NULL THEN 0 ELSE b.label_photos END`)
|
SET photo_count = CASE WHEN b.label_photos IS NULL THEN 0 ELSE b.label_photos END`)
|
||||||
@@ -157,7 +157,7 @@ func UpdateLabelCounts() (err error) {
|
|||||||
JOIN photos ph ON pl.photo_id = ph.id
|
JOIN photos ph ON pl.photo_id = ph.id
|
||||||
WHERE pl.uncertainty < 100
|
WHERE pl.uncertainty < 100
|
||||||
AND ph.photo_quality > -1
|
AND ph.photo_quality > -1
|
||||||
AND ph.photo_private = 0
|
AND ph.photo_private = FALSE
|
||||||
AND ph.deleted_at IS NULL GROUP BY l.id
|
AND ph.deleted_at IS NULL GROUP BY l.id
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT l.id AS label_id, COUNT(*) AS photo_count FROM labels l
|
SELECT l.id AS label_id, COUNT(*) AS photo_count FROM labels l
|
||||||
@@ -166,7 +166,7 @@ func UpdateLabelCounts() (err error) {
|
|||||||
JOIN photos ph ON pl.photo_id = ph.id
|
JOIN photos ph ON pl.photo_id = ph.id
|
||||||
WHERE pl.uncertainty < 100
|
WHERE pl.uncertainty < 100
|
||||||
AND ph.photo_quality > -1
|
AND ph.photo_quality > -1
|
||||||
AND ph.photo_private = 0
|
AND ph.photo_private = FALSE
|
||||||
AND ph.deleted_at IS NULL GROUP BY l.id) counts GROUP BY label_id) label_counts WHERE label_id = labels.id)`))
|
AND ph.deleted_at IS NULL GROUP BY l.id) counts GROUP BY label_id) label_counts WHERE label_id = labels.id)`))
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("sql: unsupported dialect %s", DbDialect())
|
return fmt.Errorf("sql: unsupported dialect %s", DbDialect())
|
||||||
@@ -217,13 +217,13 @@ func UpdateCounts() (err error) {
|
|||||||
default:
|
default:
|
||||||
if err = UnscopedDb().Exec(`UPDATE albums SET deleted_at = ? WHERE album_type=? AND id NOT IN (
|
if err = UnscopedDb().Exec(`UPDATE albums SET deleted_at = ? WHERE album_type=? AND id NOT IN (
|
||||||
SELECT a.id FROM albums a JOIN photos p ON a.album_month = MONTH(p.taken_at) AND a.album_year = YEAR(p.taken_at)
|
SELECT a.id FROM albums a JOIN photos p ON a.album_month = MONTH(p.taken_at) AND a.album_year = YEAR(p.taken_at)
|
||||||
AND p.deleted_at IS NULL AND p.photo_quality > -1 AND p.photo_private = 0 WHERE album_type=? GROUP BY a.id)`,
|
AND p.deleted_at IS NULL AND p.photo_quality > -1 AND p.photo_private = FALSE WHERE album_type=? GROUP BY a.id)`,
|
||||||
TimeStamp(), AlbumMonth, AlbumMonth).Error; err != nil {
|
TimeStamp(), AlbumMonth, AlbumMonth).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = UnscopedDb().Exec(`UPDATE albums SET deleted_at = NULL WHERE album_type=? AND id IN (
|
if err = UnscopedDb().Exec(`UPDATE albums SET deleted_at = NULL WHERE album_type=? AND id IN (
|
||||||
SELECT a.id FROM albums a JOIN photos p ON a.album_month = MONTH(p.taken_at) AND a.album_year = YEAR(p.taken_at)
|
SELECT a.id FROM albums a JOIN photos p ON a.album_month = MONTH(p.taken_at) AND a.album_year = YEAR(p.taken_at)
|
||||||
AND p.deleted_at IS NULL AND p.photo_quality > -1 AND p.photo_private = 0 WHERE album_type=? GROUP BY a.id)`,
|
AND p.deleted_at IS NULL AND p.photo_quality > -1 AND p.photo_private = FALSE WHERE album_type=? GROUP BY a.id)`,
|
||||||
AlbumMonth, AlbumMonth).Error; err != nil {
|
AlbumMonth, AlbumMonth).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,7 @@ func (list Tables) WaitForMigration(db *gorm.DB) error {
|
|||||||
Count int
|
Count int
|
||||||
}
|
}
|
||||||
|
|
||||||
attempts := 100
|
const attempts = 100
|
||||||
for name := range list {
|
for name := range list {
|
||||||
for i := 0; i <= attempts; i++ {
|
for i := 0; i <= attempts; i++ {
|
||||||
count := RowCount{}
|
count := RowCount{}
|
||||||
@@ -105,7 +105,6 @@ func (list Tables) Truncate(db *gorm.DB) {
|
|||||||
// Migrate migrates all database tables of registered entities.
|
// Migrate migrates all database tables of registered entities.
|
||||||
func (list Tables) Migrate(db *gorm.DB, opt migrate.Options) {
|
func (list Tables) Migrate(db *gorm.DB, opt migrate.Options) {
|
||||||
var name string
|
var name string
|
||||||
var entity interface{}
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@@ -122,7 +121,37 @@ func (list Tables) Migrate(db *gorm.DB, opt migrate.Options) {
|
|||||||
|
|
||||||
// Run ORM auto migrations.
|
// Run ORM auto migrations.
|
||||||
if opt.AutoMigrate {
|
if opt.AutoMigrate {
|
||||||
|
// Setup required explicit join tables
|
||||||
|
err := db.SetupJoinTable(&Photo{}, "Albums", &PhotoAlbum{})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("migrate: could not setup join table for Photo - Albums: ", err)
|
||||||
|
}
|
||||||
|
err = db.SetupJoinTable(&Photo{}, "Keywords", &PhotoKeyword{})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("migrate: could not setup join table for Photo - Keywords: ", err)
|
||||||
|
}
|
||||||
|
err = db.SetupJoinTable(&Label{}, "LabelCategories", &Category{})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("migrate: could not setup join table for Label - Categories: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ifaces := make([]interface{}, len(list))
|
||||||
|
idx := 0
|
||||||
|
for _, value := range list {
|
||||||
|
ifaces[idx] = value
|
||||||
|
idx++
|
||||||
|
}
|
||||||
|
log.Debugf("migrate: auto-migrating %d entity tables", len(ifaces))
|
||||||
|
err = db.AutoMigrate(ifaces...)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("migrate: auto-migration of entities failed: ", err)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
var entity interface{}
|
||||||
|
|
||||||
for name, entity = range list {
|
for name, entity = range list {
|
||||||
|
log.Debugf("migrate: auto-migrating %s", name)
|
||||||
if err := db.AutoMigrate(entity); err != nil {
|
if err := db.AutoMigrate(entity); err != nil {
|
||||||
log.Debugf("migrate: %s (waiting 1s)", err.Error())
|
log.Debugf("migrate: %s (waiting 1s)", err.Error())
|
||||||
|
|
||||||
|
@@ -11,8 +11,8 @@ import (
|
|||||||
type Error struct {
|
type Error struct {
|
||||||
ID uint `gorm:"primaryKey" json:"ID" yaml:"ID"`
|
ID uint `gorm:"primaryKey" json:"ID" yaml:"ID"`
|
||||||
ErrorTime time.Time `sql:"index" json:"Time" yaml:"Time"`
|
ErrorTime time.Time `sql:"index" json:"Time" yaml:"Time"`
|
||||||
ErrorLevel string `gorm:"type:VARBINARY(32)" json:"Level" yaml:"Level"`
|
ErrorLevel string `gorm:"size:32" json:"Level" yaml:"Level"`
|
||||||
ErrorMessage string `gorm:"type:VARBINARY(2048)" json:"Message" yaml:"Message"`
|
ErrorMessage string `gorm:"size:2048" json:"Message" yaml:"Message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Errors represents a list of error log messages.
|
// Errors represents a list of error log messages.
|
||||||
|
@@ -19,16 +19,16 @@ var UpdateFaces = atomic.Bool{}
|
|||||||
|
|
||||||
// Face represents the face of a Subject.
|
// Face represents the face of a Subject.
|
||||||
type Face struct {
|
type Face struct {
|
||||||
ID string `gorm:"type:VARBINARY(64);primaryKey;autoIncrement:false;" json:"ID" yaml:"ID"`
|
ID string `gorm:"size:64;primaryKey;autoIncrement:false;" json:"ID" yaml:"ID"`
|
||||||
FaceSrc string `gorm:"type:VARBINARY(8);" json:"Src" yaml:"Src,omitempty"`
|
FaceSrc string `gorm:"size:8;" json:"Src" yaml:"Src,omitempty"`
|
||||||
FaceKind int `json:"Kind" yaml:"Kind,omitempty"`
|
FaceKind int `json:"Kind" yaml:"Kind,omitempty"`
|
||||||
FaceHidden bool `json:"Hidden" yaml:"Hidden,omitempty"`
|
FaceHidden bool `json:"Hidden" yaml:"Hidden,omitempty"`
|
||||||
SubjUID string `gorm:"type:VARBINARY(42);index;default:'';" json:"SubjUID" yaml:"SubjUID,omitempty"`
|
SubjUID string `gorm:"size:42;index;default:'';" json:"SubjUID" yaml:"SubjUID,omitempty"`
|
||||||
Samples int `json:"Samples" yaml:"Samples,omitempty"`
|
Samples int `json:"Samples" yaml:"Samples,omitempty"`
|
||||||
SampleRadius float64 `json:"SampleRadius" yaml:"SampleRadius,omitempty"`
|
SampleRadius float64 `json:"SampleRadius" yaml:"SampleRadius,omitempty"`
|
||||||
Collisions int `json:"Collisions" yaml:"Collisions,omitempty"`
|
Collisions int `json:"Collisions" yaml:"Collisions,omitempty"`
|
||||||
CollisionRadius float64 `json:"CollisionRadius" yaml:"CollisionRadius,omitempty"`
|
CollisionRadius float64 `json:"CollisionRadius" yaml:"CollisionRadius,omitempty"`
|
||||||
EmbeddingJSON json.RawMessage `gorm:"type:MEDIUMBLOB;" json:"-" yaml:"EmbeddingJSON,omitempty"`
|
EmbeddingJSON json.RawMessage `json:"-" yaml:"EmbeddingJSON,omitempty"`
|
||||||
embedding face.Embedding `gorm:"-" yaml:"-"`
|
embedding face.Embedding `gorm:"-" yaml:"-"`
|
||||||
MatchedAt *time.Time `json:"MatchedAt" yaml:"MatchedAt,omitempty"`
|
MatchedAt *time.Time `json:"MatchedAt" yaml:"MatchedAt,omitempty"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt,omitempty"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt,omitempty"`
|
||||||
|
@@ -42,22 +42,22 @@ type File struct {
|
|||||||
ID uint `gorm:"primaryKey" json:"-" yaml:"-"`
|
ID uint `gorm:"primaryKey" json:"-" yaml:"-"`
|
||||||
Photo *Photo `json:"-" yaml:"-"`
|
Photo *Photo `json:"-" yaml:"-"`
|
||||||
PhotoID uint `gorm:"index:idx_files_photo_id;" json:"-" yaml:"-"`
|
PhotoID uint `gorm:"index:idx_files_photo_id;" json:"-" yaml:"-"`
|
||||||
PhotoUID string `gorm:"type:VARBINARY(42);index;" json:"PhotoUID" yaml:"PhotoUID"`
|
PhotoUID string `gorm:"size:42;index;" json:"PhotoUID" yaml:"PhotoUID"`
|
||||||
PhotoTakenAt time.Time `gorm:"type:DATETIME;index;" json:"TakenAt" yaml:"TakenAt"`
|
PhotoTakenAt time.Time `gorm:"index;" json:"TakenAt" yaml:"TakenAt"`
|
||||||
TimeIndex *string `gorm:"type:VARBINARY(64);" json:"TimeIndex" yaml:"TimeIndex"`
|
TimeIndex *string `gorm:"size:64;" json:"TimeIndex" yaml:"TimeIndex"`
|
||||||
MediaID *string `gorm:"type:VARBINARY(32);" json:"MediaID" yaml:"MediaID"`
|
MediaID *string `gorm:"size:32;" json:"MediaID" yaml:"MediaID"`
|
||||||
MediaUTC int64 `gorm:"column:media_utc;index;" json:"MediaUTC" yaml:"MediaUTC,omitempty"`
|
MediaUTC int64 `gorm:"column:media_utc;index;" json:"MediaUTC" yaml:"MediaUTC,omitempty"`
|
||||||
InstanceID string `gorm:"type:VARBINARY(64);index;" json:"InstanceID,omitempty" yaml:"InstanceID,omitempty"`
|
InstanceID string `gorm:"size:64;index;" json:"InstanceID,omitempty" yaml:"InstanceID,omitempty"`
|
||||||
FileUID string `gorm:"type:VARBINARY(42);uniqueIndex;" json:"UID" yaml:"UID"`
|
FileUID string `gorm:"size:42;uniqueIndex;" json:"UID" yaml:"UID"`
|
||||||
FileName string `gorm:"type:VARBINARY(1024);uniqueIndex:idx_files_name_root;" json:"Name" yaml:"Name"`
|
FileName string `gorm:"size:1024;uniqueIndex:idx_files_name_root;" json:"Name" yaml:"Name"`
|
||||||
FileRoot string `gorm:"type:VARBINARY(16);default:'/';uniqueIndex:idx_files_name_root;" json:"Root" yaml:"Root,omitempty"`
|
FileRoot string `gorm:"size:16;default:'/';uniqueIndex:idx_files_name_root;" json:"Root" yaml:"Root,omitempty"`
|
||||||
OriginalName string `gorm:"type:VARBINARY(755);" json:"OriginalName" yaml:"OriginalName,omitempty"`
|
OriginalName string `gorm:"size:755;" json:"OriginalName" yaml:"OriginalName,omitempty"`
|
||||||
FileHash string `gorm:"type:VARBINARY(128);index" json:"Hash" yaml:"Hash,omitempty"`
|
FileHash string `gorm:"size:128;index" json:"Hash" yaml:"Hash,omitempty"`
|
||||||
FileSize int64 `json:"Size" yaml:"Size,omitempty"`
|
FileSize int64 `json:"Size" yaml:"Size,omitempty"`
|
||||||
FileCodec string `gorm:"type:VARBINARY(32)" json:"Codec" yaml:"Codec,omitempty"`
|
FileCodec string `gorm:"size:32" json:"Codec" yaml:"Codec,omitempty"`
|
||||||
FileType string `gorm:"type:VARBINARY(16)" json:"FileType" yaml:"FileType,omitempty"`
|
FileType string `gorm:"size:16" json:"FileType" yaml:"FileType,omitempty"`
|
||||||
MediaType string `gorm:"type:VARBINARY(16)" json:"MediaType" yaml:"MediaType,omitempty"`
|
MediaType string `gorm:"size:16" json:"MediaType" yaml:"MediaType,omitempty"`
|
||||||
FileMime string `gorm:"type:VARBINARY(64)" json:"Mime" yaml:"Mime,omitempty"`
|
FileMime string `gorm:"size:64" json:"Mime" yaml:"Mime,omitempty"`
|
||||||
FilePrimary bool `gorm:"index:idx_files_photo_id;" json:"Primary" yaml:"Primary,omitempty"`
|
FilePrimary bool `gorm:"index:idx_files_photo_id;" json:"Primary" yaml:"Primary,omitempty"`
|
||||||
FileSidecar bool `json:"Sidecar" yaml:"Sidecar,omitempty"`
|
FileSidecar bool `json:"Sidecar" yaml:"Sidecar,omitempty"`
|
||||||
FileMissing bool `json:"Missing" yaml:"Missing,omitempty"`
|
FileMissing bool `json:"Missing" yaml:"Missing,omitempty"`
|
||||||
@@ -69,19 +69,19 @@ type File struct {
|
|||||||
FileWidth int `gorm:"column:file_width;" json:"Width" yaml:"Width,omitempty"`
|
FileWidth int `gorm:"column:file_width;" json:"Width" yaml:"Width,omitempty"`
|
||||||
FileHeight int `gorm:"column:file_height;" json:"Height" yaml:"Height,omitempty"`
|
FileHeight int `gorm:"column:file_height;" json:"Height" yaml:"Height,omitempty"`
|
||||||
FileOrientation int `gorm:"column:file_orientation;" json:"Orientation" yaml:"Orientation,omitempty"`
|
FileOrientation int `gorm:"column:file_orientation;" json:"Orientation" yaml:"Orientation,omitempty"`
|
||||||
FileOrientationSrc string `gorm:"column:file_orientation_src;type:VARBINARY(8);default:'';" json:"OrientationSrc" yaml:"OrientationSrc,omitempty"`
|
FileOrientationSrc string `gorm:"column:file_orientation_src;size:8;default:'';" json:"OrientationSrc" yaml:"OrientationSrc,omitempty"`
|
||||||
FileProjection string `gorm:"column:file_projection;type:VARBINARY(64);" json:"Projection,omitempty" yaml:"Projection,omitempty"`
|
FileProjection string `gorm:"column:file_projection;size:64;" json:"Projection,omitempty" yaml:"Projection,omitempty"`
|
||||||
FileAspectRatio float32 `gorm:"column:file_aspect_ratio;type:FLOAT;" json:"AspectRatio" yaml:"AspectRatio,omitempty"`
|
FileAspectRatio float32 `gorm:"column:file_aspect_ratio;type:FLOAT;" json:"AspectRatio" yaml:"AspectRatio,omitempty"`
|
||||||
FileHDR bool `gorm:"column:file_hdr;" json:"HDR" yaml:"HDR,omitempty"`
|
FileHDR bool `gorm:"column:file_hdr;" json:"HDR" yaml:"HDR,omitempty"`
|
||||||
FileWatermark bool `gorm:"column:file_watermark;" json:"Watermark" yaml:"Watermark,omitempty"`
|
FileWatermark bool `gorm:"column:file_watermark;" json:"Watermark" yaml:"Watermark,omitempty"`
|
||||||
FileColorProfile string `gorm:"type:VARBINARY(64);" json:"ColorProfile,omitempty" yaml:"ColorProfile,omitempty"`
|
FileColorProfile string `gorm:"size:64;" json:"ColorProfile,omitempty" yaml:"ColorProfile,omitempty"`
|
||||||
FileMainColor string `gorm:"type:VARBINARY(16);" json:"MainColor" yaml:"MainColor,omitempty"`
|
FileMainColor string `gorm:"size:16;" json:"MainColor" yaml:"MainColor,omitempty"`
|
||||||
FileColors string `gorm:"type:VARBINARY(18);" json:"Colors" yaml:"Colors,omitempty"`
|
FileColors string `gorm:"size:18;" json:"Colors" yaml:"Colors,omitempty"`
|
||||||
FileLuminance string `gorm:"type:VARBINARY(18);" json:"Luminance" yaml:"Luminance,omitempty"`
|
FileLuminance string `gorm:"size:18;" json:"Luminance" yaml:"Luminance,omitempty"`
|
||||||
FileDiff int `json:"Diff" yaml:"Diff,omitempty"`
|
FileDiff int `json:"Diff" yaml:"Diff,omitempty"`
|
||||||
FileChroma int16 `json:"Chroma" yaml:"Chroma,omitempty"`
|
FileChroma int16 `json:"Chroma" yaml:"Chroma,omitempty"`
|
||||||
FileSoftware string `gorm:"type:VARCHAR(64)" json:"Software" yaml:"Software,omitempty"`
|
FileSoftware string `gorm:"type:VARCHAR(64)" json:"Software" yaml:"Software,omitempty"`
|
||||||
FileError string `gorm:"type:VARBINARY(512);index;" json:"Error" yaml:"Error,omitempty"`
|
FileError string `gorm:"size:512;index;" json:"Error" yaml:"Error,omitempty"`
|
||||||
ModTime int64 `json:"ModTime" yaml:"-"`
|
ModTime int64 `json:"ModTime" yaml:"-"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
CreatedIn int64 `json:"CreatedIn" yaml:"-"`
|
CreatedIn int64 `json:"CreatedIn" yaml:"-"`
|
||||||
@@ -89,8 +89,8 @@ type File struct {
|
|||||||
UpdatedIn int64 `json:"UpdatedIn" yaml:"-"`
|
UpdatedIn int64 `json:"UpdatedIn" yaml:"-"`
|
||||||
PublishedAt *time.Time `sql:"index" json:"PublishedAt,omitempty" yaml:"PublishedAt,omitempty"`
|
PublishedAt *time.Time `sql:"index" json:"PublishedAt,omitempty" yaml:"PublishedAt,omitempty"`
|
||||||
DeletedAt *time.Time `sql:"index" json:"DeletedAt,omitempty" yaml:"-"`
|
DeletedAt *time.Time `sql:"index" json:"DeletedAt,omitempty" yaml:"-"`
|
||||||
Share []FileShare `json:"-" yaml:"-"`
|
Share []FileShare `gorm:"foreignKey:FileID" json:"-" yaml:"-"`
|
||||||
Sync []FileSync `json:"-" yaml:"-"`
|
Sync []FileSync `gorm:"foreignKey:FileID" json:"-" yaml:"-"`
|
||||||
markers *Markers
|
markers *Markers
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,13 +126,13 @@ func (m File) RegenerateIndex() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch DbDialect() {
|
switch DbDialect() {
|
||||||
case MySQL:
|
case MySQL, Postgres:
|
||||||
Log("files", "regenerate photo_taken_at",
|
Log("files", "regenerate photo_taken_at",
|
||||||
Db().Exec("UPDATE files JOIN ? p ON p.id = files.photo_id SET files.photo_taken_at = p.taken_at_local WHERE ?",
|
Db().Exec("UPDATE files JOIN ? p ON p.id = files.photo_id SET files.photo_taken_at = p.taken_at_local WHERE ?",
|
||||||
gorm.Expr(photosTable), updateWhere).Error)
|
gorm.Expr(photosTable), updateWhere).Error)
|
||||||
|
|
||||||
Log("files", "regenerate media_id",
|
Log("files", "regenerate media_id",
|
||||||
Db().Exec("UPDATE files SET media_id = CASE WHEN file_missing = 0 AND deleted_at IS NULL THEN CONCAT((10000000000 - photo_id), '-', 1 + file_sidecar - file_primary, '-', file_uid) ELSE NULL END WHERE ?",
|
Db().Exec("UPDATE files SET media_id = CASE WHEN file_missing = FALSE AND deleted_at IS NULL THEN CONCAT((10000000000 - photo_id), '-', 1 + file_sidecar - file_primary, '-', file_uid) ELSE NULL END WHERE ?",
|
||||||
updateWhere).Error)
|
updateWhere).Error)
|
||||||
|
|
||||||
Log("files", "regenerate time_index",
|
Log("files", "regenerate time_index",
|
||||||
@@ -144,7 +144,7 @@ func (m File) RegenerateIndex() {
|
|||||||
gorm.Expr(photosTable), updateWhere).Error)
|
gorm.Expr(photosTable), updateWhere).Error)
|
||||||
|
|
||||||
Log("files", "regenerate media_id",
|
Log("files", "regenerate media_id",
|
||||||
Db().Exec("UPDATE files SET media_id = CASE WHEN file_missing = 0 AND deleted_at IS NULL THEN ((10000000000 - photo_id) || '-' || (1 + file_sidecar - file_primary) || '-' || file_uid) ELSE NULL END WHERE ?",
|
Db().Exec("UPDATE files SET media_id = CASE WHEN file_missing = FALSE AND deleted_at IS NULL THEN ((10000000000 - photo_id) || '-' || (1 + file_sidecar - file_primary) || '-' || file_uid) ELSE NULL END WHERE ?",
|
||||||
updateWhere).Error)
|
updateWhere).Error)
|
||||||
|
|
||||||
Log("files", "regenerate time_index",
|
Log("files", "regenerate time_index",
|
||||||
@@ -170,7 +170,7 @@ func FirstFileByHash(fileHash string) (File, error) {
|
|||||||
func PrimaryFile(photoUid string) (*File, error) {
|
func PrimaryFile(photoUid string) (*File, error) {
|
||||||
file := File{}
|
file := File{}
|
||||||
|
|
||||||
res := Db().Unscoped().First(&file, "file_primary = 1 AND photo_uid = ?", photoUid)
|
res := Db().Unscoped().First(&file, "file_primary = TRUE AND photo_uid = ?", photoUid)
|
||||||
|
|
||||||
return &file, res.Error
|
return &file, res.Error
|
||||||
}
|
}
|
||||||
@@ -369,14 +369,14 @@ func (m *File) Purge() error {
|
|||||||
m.FileMissing = true
|
m.FileMissing = true
|
||||||
m.FilePrimary = false
|
m.FilePrimary = false
|
||||||
m.DeletedAt = &deletedAt
|
m.DeletedAt = &deletedAt
|
||||||
return UnscopedDb().Exec("UPDATE files SET file_missing = 1, file_primary = 0, deleted_at = ? WHERE id = ?", &deletedAt, m.ID).Error
|
return UnscopedDb().Exec("UPDATE files SET file_missing = TRUE, file_primary = FALSE, deleted_at = ? WHERE id = ?", &deletedAt, m.ID).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Found restores a previously purged file.
|
// Found restores a previously purged file.
|
||||||
func (m *File) Found() error {
|
func (m *File) Found() error {
|
||||||
m.FileMissing = false
|
m.FileMissing = false
|
||||||
m.DeletedAt = nil
|
m.DeletedAt = nil
|
||||||
return UnscopedDb().Exec("UPDATE files SET file_missing = 0, deleted_at = NULL WHERE id = ?", m.ID).Error
|
return UnscopedDb().Exec("UPDATE files SET file_missing = FALSE, deleted_at = NULL WHERE id = ?", m.ID).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllFilesMissing returns true, if all files for the photo of this file are missing.
|
// AllFilesMissing returns true, if all files for the photo of this file are missing.
|
||||||
@@ -384,7 +384,7 @@ func (m *File) AllFilesMissing() bool {
|
|||||||
count := int64(0)
|
count := int64(0)
|
||||||
|
|
||||||
if err := Db().Model(&File{}).
|
if err := Db().Model(&File{}).
|
||||||
Where("photo_id = ? AND file_missing = 0", m.PhotoID).
|
Where("photo_id = ? AND file_missing = FALSE", m.PhotoID).
|
||||||
Count(&count).Error; err != nil {
|
Count(&count).Error; err != nil {
|
||||||
log.Errorf("file: %s", err.Error())
|
log.Errorf("file: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
@@ -15,11 +15,11 @@ const (
|
|||||||
type FileShare struct {
|
type FileShare struct {
|
||||||
FileID uint `gorm:"primaryKey;autoIncrement:false"`
|
FileID uint `gorm:"primaryKey;autoIncrement:false"`
|
||||||
ServiceID uint `gorm:"primaryKey;autoIncrement:false"`
|
ServiceID uint `gorm:"primaryKey;autoIncrement:false"`
|
||||||
RemoteName string `gorm:"primaryKey;autoIncrement:false;type:VARBINARY(255)"`
|
RemoteName string `gorm:"primaryKey;autoIncrement:false;size:255"`
|
||||||
Status string `gorm:"type:VARBINARY(16);"`
|
Status string `gorm:"size:16;"`
|
||||||
Error string `gorm:"type:VARBINARY(512);"`
|
Error string `gorm:"size:512;"`
|
||||||
Errors int
|
Errors int
|
||||||
File *File
|
File *File `gorm:"foreignKey:FileID"`
|
||||||
Account *Service `gorm:"foreignKey:ServiceID"`
|
Account *Service `gorm:"foreignKey:ServiceID"`
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
|
@@ -14,13 +14,13 @@ const (
|
|||||||
|
|
||||||
// FileSync represents a one-to-many relation between File and Account for syncing with remote services.
|
// FileSync represents a one-to-many relation between File and Account for syncing with remote services.
|
||||||
type FileSync struct {
|
type FileSync struct {
|
||||||
RemoteName string `gorm:"primaryKey;autoIncrement:false;type:VARBINARY(255)"`
|
RemoteName string `gorm:"primaryKey;autoIncrement:false;size:255"`
|
||||||
ServiceID uint `gorm:"primaryKey;autoIncrement:false"`
|
ServiceID uint `gorm:"primaryKey;autoIncrement:false"`
|
||||||
FileID uint `gorm:"index;"`
|
FileID uint `gorm:"index;"`
|
||||||
RemoteDate time.Time
|
RemoteDate time.Time
|
||||||
RemoteSize int64
|
RemoteSize int64
|
||||||
Status string `gorm:"type:VARBINARY(16);"`
|
Status string `gorm:"size:16;"`
|
||||||
Error string `gorm:"type:VARBINARY(512);"`
|
Error string `gorm:"size:512;"`
|
||||||
Errors int
|
Errors int
|
||||||
File *File `gorm:"foreignKey:FileID"`
|
File *File `gorm:"foreignKey:FileID"`
|
||||||
Account *Service `gorm:"foreignKey:ServiceID"`
|
Account *Service `gorm:"foreignKey:ServiceID"`
|
||||||
|
@@ -23,15 +23,15 @@ type Folders []Folder
|
|||||||
|
|
||||||
// Folder represents a file system directory.
|
// Folder represents a file system directory.
|
||||||
type Folder struct {
|
type Folder struct {
|
||||||
Path string `gorm:"type:VARBINARY(1024);uniqueIndex:idx_folders_path_root;" json:"Path" yaml:"Path"`
|
Path string `gorm:"size:1024;uniqueIndex:idx_folders_path_root;" json:"Path" yaml:"Path"`
|
||||||
Root string `gorm:"type:VARBINARY(16);default:'';uniqueIndex:idx_folders_path_root;" json:"Root" yaml:"Root,omitempty"`
|
Root string `gorm:"size:16;default:'';uniqueIndex:idx_folders_path_root;" json:"Root" yaml:"Root,omitempty"`
|
||||||
FolderUID string `gorm:"type:VARBINARY(42);primaryKey;" json:"UID,omitempty" yaml:"UID,omitempty"`
|
FolderUID string `gorm:"size:42;primaryKey;" json:"UID,omitempty" yaml:"UID,omitempty"`
|
||||||
FolderType string `gorm:"type:VARBINARY(16);" json:"Type" yaml:"Type,omitempty"`
|
FolderType string `gorm:"size:16;" json:"Type" yaml:"Type,omitempty"`
|
||||||
FolderTitle string `gorm:"type:VARCHAR(200);" json:"Title" yaml:"Title,omitempty"`
|
FolderTitle string `gorm:"type:VARCHAR(200);" json:"Title" yaml:"Title,omitempty"`
|
||||||
FolderCategory string `gorm:"type:VARCHAR(100);index;" json:"Category" yaml:"Category,omitempty"`
|
FolderCategory string `gorm:"type:VARCHAR(100);index;" json:"Category" yaml:"Category,omitempty"`
|
||||||
FolderDescription string `gorm:"type:VARCHAR(2048);" json:"Description,omitempty" yaml:"Description,omitempty"`
|
FolderDescription string `gorm:"type:VARCHAR(2048);" json:"Description,omitempty" yaml:"Description,omitempty"`
|
||||||
FolderOrder string `gorm:"type:VARBINARY(32);" json:"Order" yaml:"Order,omitempty"`
|
FolderOrder string `gorm:"size:32;" json:"Order" yaml:"Order,omitempty"`
|
||||||
FolderCountry string `gorm:"type:VARBINARY(2);index:idx_folders_country_year_month;default:'zz'" json:"Country" yaml:"Country,omitempty"`
|
FolderCountry string `gorm:"size:2;index:idx_folders_country_year_month;default:'zz'" json:"Country" yaml:"Country,omitempty"`
|
||||||
FolderYear int `gorm:"index:idx_folders_country_year_month;" json:"Year" yaml:"Year,omitempty"`
|
FolderYear int `gorm:"index:idx_folders_country_year_month;" json:"Year" yaml:"Year,omitempty"`
|
||||||
FolderMonth int `gorm:"index:idx_folders_country_year_month;" json:"Month" yaml:"Month,omitempty"`
|
FolderMonth int `gorm:"index:idx_folders_country_year_month;" json:"Month" yaml:"Month,omitempty"`
|
||||||
FolderDay int `json:"Day" yaml:"Day,omitempty"`
|
FolderDay int `json:"Day" yaml:"Day,omitempty"`
|
||||||
|
@@ -26,18 +26,18 @@ type Labels []Label
|
|||||||
// Label is used for photo, album and location categorization
|
// Label is used for photo, album and location categorization
|
||||||
type Label struct {
|
type Label struct {
|
||||||
ID uint `gorm:"primaryKey" json:"ID" yaml:"-"`
|
ID uint `gorm:"primaryKey" json:"ID" yaml:"-"`
|
||||||
LabelUID string `gorm:"type:VARBINARY(42);uniqueIndex;" json:"UID" yaml:"UID"`
|
LabelUID string `gorm:"size:42;uniqueIndex;" json:"UID" yaml:"UID"`
|
||||||
LabelSlug string `gorm:"type:VARBINARY(160);uniqueIndex;" json:"Slug" yaml:"-"`
|
LabelSlug string `gorm:"size:160;uniqueIndex;" json:"Slug" yaml:"-"`
|
||||||
CustomSlug string `gorm:"type:VARBINARY(160);index;" json:"CustomSlug" yaml:"-"`
|
CustomSlug string `gorm:"size:160;index;" json:"CustomSlug" yaml:"-"`
|
||||||
LabelName string `gorm:"type:VARCHAR(160);" json:"Name" yaml:"Name"`
|
LabelName string `gorm:"type:VARCHAR(160);" json:"Name" yaml:"Name"`
|
||||||
LabelPriority int `json:"Priority" yaml:"Priority,omitempty"`
|
LabelPriority int `json:"Priority" yaml:"Priority,omitempty"`
|
||||||
LabelFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
LabelFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
||||||
LabelDescription string `gorm:"type:VARCHAR(2048);" json:"Description" yaml:"Description,omitempty"`
|
LabelDescription string `gorm:"type:VARCHAR(2048);" json:"Description" yaml:"Description,omitempty"`
|
||||||
LabelNotes string `gorm:"type:VARCHAR(1024);" json:"Notes" yaml:"Notes,omitempty"`
|
LabelNotes string `gorm:"type:VARCHAR(1024);" json:"Notes" yaml:"Notes,omitempty"`
|
||||||
LabelCategories []*Label `gorm:"many2many:categories;joinForeignKey:category_id" json:"-" yaml:"-"`
|
LabelCategories []*Label `gorm:"many2many:categories;foreignKey:ID;joinForeignKey:LabelID;References:ID;joinReferences:CategoryID" json:"-" yaml:"-"`
|
||||||
PhotoCount int `gorm:"default:1" json:"PhotoCount" yaml:"-"`
|
PhotoCount int `gorm:"default:1" json:"PhotoCount" yaml:"-"`
|
||||||
Thumb string `gorm:"type:VARBINARY(128);index;default:''" json:"Thumb" yaml:"Thumb,omitempty"`
|
Thumb string `gorm:"size:128;index;default:''" json:"Thumb" yaml:"Thumb,omitempty"`
|
||||||
ThumbSrc string `gorm:"type:VARBINARY(8);default:''" json:"ThumbSrc,omitempty" yaml:"ThumbSrc,omitempty"`
|
ThumbSrc string `gorm:"size:8;default:''" json:"ThumbSrc,omitempty" yaml:"ThumbSrc,omitempty"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
||||||
PublishedAt *time.Time `sql:"index" json:"PublishedAt,omitempty" yaml:"PublishedAt,omitempty"`
|
PublishedAt *time.Time `sql:"index" json:"PublishedAt,omitempty" yaml:"PublishedAt,omitempty"`
|
||||||
|
@@ -13,10 +13,10 @@ type Users []User
|
|||||||
type User struct {
|
type User struct {
|
||||||
ID int `gorm:"primaryKey" json:"-" yaml:"-"`
|
ID int `gorm:"primaryKey" json:"-" yaml:"-"`
|
||||||
AddressID int `gorm:"default:1" json:"-" yaml:"-"`
|
AddressID int `gorm:"default:1" json:"-" yaml:"-"`
|
||||||
UserUID string `gorm:"type:VARBINARY(42);uniqueIndex;" json:"UID" yaml:"UID"`
|
UserUID string `gorm:"size:42;uniqueIndex;" json:"UID" yaml:"UID"`
|
||||||
MotherUID string `gorm:"type:VARBINARY(42);" json:"MotherUID" yaml:"MotherUID,omitempty"`
|
MotherUID string `gorm:"size:42;" json:"MotherUID" yaml:"MotherUID,omitempty"`
|
||||||
FatherUID string `gorm:"type:VARBINARY(42);" json:"FatherUID" yaml:"FatherUID,omitempty"`
|
FatherUID string `gorm:"size:42;" json:"FatherUID" yaml:"FatherUID,omitempty"`
|
||||||
GlobalUID string `gorm:"type:VARBINARY(42);index;" json:"GlobalUID" yaml:"GlobalUID,omitempty"`
|
GlobalUID string `gorm:"size:42;index;" json:"GlobalUID" yaml:"GlobalUID,omitempty"`
|
||||||
FullName string `gorm:"size:128;" json:"FullName" yaml:"FullName,omitempty"`
|
FullName string `gorm:"size:128;" json:"FullName" yaml:"FullName,omitempty"`
|
||||||
NickName string `gorm:"size:64;" json:"NickName" yaml:"NickName,omitempty"`
|
NickName string `gorm:"size:64;" json:"NickName" yaml:"NickName,omitempty"`
|
||||||
MaidenName string `gorm:"size:64;" json:"MaidenName" yaml:"MaidenName,omitempty"`
|
MaidenName string `gorm:"size:64;" json:"MaidenName" yaml:"MaidenName,omitempty"`
|
||||||
@@ -28,14 +28,14 @@ type User struct {
|
|||||||
PrimaryEmail string `gorm:"size:255;index;" json:"PrimaryEmail" yaml:"PrimaryEmail,omitempty"`
|
PrimaryEmail string `gorm:"size:255;index;" json:"PrimaryEmail" yaml:"PrimaryEmail,omitempty"`
|
||||||
EmailConfirmed bool `json:"EmailConfirmed" yaml:"EmailConfirmed,omitempty"`
|
EmailConfirmed bool `json:"EmailConfirmed" yaml:"EmailConfirmed,omitempty"`
|
||||||
BackupEmail string `gorm:"size:255;" json:"BackupEmail" yaml:"BackupEmail,omitempty"`
|
BackupEmail string `gorm:"size:255;" json:"BackupEmail" yaml:"BackupEmail,omitempty"`
|
||||||
PersonURL string `gorm:"type:VARBINARY(255);" json:"PersonURL" yaml:"PersonURL,omitempty"`
|
PersonURL string `gorm:"size:255;" json:"PersonURL" yaml:"PersonURL,omitempty"`
|
||||||
PersonPhone string `gorm:"size:32;" json:"PersonPhone" yaml:"PersonPhone,omitempty"`
|
PersonPhone string `gorm:"size:32;" json:"PersonPhone" yaml:"PersonPhone,omitempty"`
|
||||||
PersonStatus string `gorm:"size:32;" json:"PersonStatus" yaml:"PersonStatus,omitempty"`
|
PersonStatus string `gorm:"size:32;" json:"PersonStatus" yaml:"PersonStatus,omitempty"`
|
||||||
PersonAvatar string `gorm:"type:VARBINARY(255);" json:"PersonAvatar" yaml:"PersonAvatar,omitempty"`
|
PersonAvatar string `gorm:"size:255;" json:"PersonAvatar" yaml:"PersonAvatar,omitempty"`
|
||||||
PersonLocation string `gorm:"size:128;" json:"PersonLocation" yaml:"PersonLocation,omitempty"`
|
PersonLocation string `gorm:"size:128;" json:"PersonLocation" yaml:"PersonLocation,omitempty"`
|
||||||
PersonBio string `gorm:"type:TEXT;" json:"PersonBio" yaml:"PersonBio,omitempty"`
|
PersonBio string `gorm:"type:TEXT;" json:"PersonBio" yaml:"PersonBio,omitempty"`
|
||||||
PersonAccounts string `gorm:"type:LONGTEXT;" json:"-" yaml:"-"`
|
PersonAccounts string `gorm:"type:LONGTEXT;" json:"-" yaml:"-"`
|
||||||
BusinessURL string `gorm:"type:VARBINARY(255);" json:"BusinessURL" yaml:"BusinessURL,omitempty"`
|
BusinessURL string `gorm:"size:255;" json:"BusinessURL" yaml:"BusinessURL,omitempty"`
|
||||||
BusinessPhone string `gorm:"size:32;" json:"BusinessPhone" yaml:"BusinessPhone,omitempty"`
|
BusinessPhone string `gorm:"size:32;" json:"BusinessPhone" yaml:"BusinessPhone,omitempty"`
|
||||||
BusinessEmail string `gorm:"size:255;" json:"BusinessEmail" yaml:"BusinessEmail,omitempty"`
|
BusinessEmail string `gorm:"size:255;" json:"BusinessEmail" yaml:"BusinessEmail,omitempty"`
|
||||||
CompanyName string `gorm:"size:128;" json:"CompanyName" yaml:"CompanyName,omitempty"`
|
CompanyName string `gorm:"size:128;" json:"CompanyName" yaml:"CompanyName,omitempty"`
|
||||||
@@ -53,14 +53,14 @@ type User struct {
|
|||||||
RoleFamily bool `json:"RoleFamily" yaml:"RoleFamily,omitempty"`
|
RoleFamily bool `json:"RoleFamily" yaml:"RoleFamily,omitempty"`
|
||||||
RoleFriend bool `json:"RoleFriend" yaml:"RoleFriend,omitempty"`
|
RoleFriend bool `json:"RoleFriend" yaml:"RoleFriend,omitempty"`
|
||||||
WebDAV bool `gorm:"column:webdav" json:"WebDAV" yaml:"WebDAV,omitempty"`
|
WebDAV bool `gorm:"column:webdav" json:"WebDAV" yaml:"WebDAV,omitempty"`
|
||||||
StoragePath string `gorm:"column:storage_path;type:VARBINARY(500);" json:"StoragePath" yaml:"StoragePath,omitempty"`
|
StoragePath string `gorm:"column:storage_path;size:500;" json:"StoragePath" yaml:"StoragePath,omitempty"`
|
||||||
CanInvite bool `json:"CanInvite" yaml:"CanInvite,omitempty"`
|
CanInvite bool `json:"CanInvite" yaml:"CanInvite,omitempty"`
|
||||||
InviteToken string `gorm:"type:VARBINARY(32);" json:"-" yaml:"-"`
|
InviteToken string `gorm:"size:32;" json:"-" yaml:"-"`
|
||||||
InvitedBy string `gorm:"type:VARBINARY(32);" json:"-" yaml:"-"`
|
InvitedBy string `gorm:"size:32;" json:"-" yaml:"-"`
|
||||||
ConfirmToken string `gorm:"type:VARBINARY(64);" json:"-" yaml:"-"`
|
ConfirmToken string `gorm:"size:64;" json:"-" yaml:"-"`
|
||||||
ResetToken string `gorm:"type:VARBINARY(64);" json:"-" yaml:"-"`
|
ResetToken string `gorm:"size:64;" json:"-" yaml:"-"`
|
||||||
ApiToken string `gorm:"column:api_token;type:VARBINARY(128);" json:"-" yaml:"-"`
|
ApiToken string `gorm:"column:api_token;size:128;" json:"-" yaml:"-"`
|
||||||
ApiSecret string `gorm:"column:api_secret;type:VARBINARY(128);" json:"-" yaml:"-"`
|
ApiSecret string `gorm:"column:api_secret;size:128;" json:"-" yaml:"-"`
|
||||||
LoginAttempts int `json:"-" yaml:"-"`
|
LoginAttempts int `json:"-" yaml:"-"`
|
||||||
LoginAt *time.Time `json:"-" yaml:"-"`
|
LoginAt *time.Time `json:"-" yaml:"-"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
|
@@ -18,7 +18,7 @@ type Lenses []Lens
|
|||||||
// Lens represents camera lens (as extracted from UpdateExif metadata)
|
// Lens represents camera lens (as extracted from UpdateExif metadata)
|
||||||
type Lens struct {
|
type Lens struct {
|
||||||
ID uint `gorm:"primaryKey" json:"ID" yaml:"ID"`
|
ID uint `gorm:"primaryKey" json:"ID" yaml:"ID"`
|
||||||
LensSlug string `gorm:"type:VARBINARY(160);uniqueIndex;" json:"Slug" yaml:"Slug,omitempty"`
|
LensSlug string `gorm:"size:160;uniqueIndex;" json:"Slug" yaml:"Slug,omitempty"`
|
||||||
LensName string `gorm:"type:VARCHAR(160);" json:"Name" yaml:"Name"`
|
LensName string `gorm:"type:VARCHAR(160);" json:"Name" yaml:"Name"`
|
||||||
LensMake string `gorm:"type:VARCHAR(160);" json:"Make" yaml:"Make,omitempty"`
|
LensMake string `gorm:"type:VARCHAR(160);" json:"Make" yaml:"Make,omitempty"`
|
||||||
LensModel string `gorm:"type:VARCHAR(160);" json:"Model" yaml:"Model,omitempty"`
|
LensModel string `gorm:"type:VARCHAR(160);" json:"Model" yaml:"Model,omitempty"`
|
||||||
|
@@ -22,18 +22,18 @@ type Links []Link
|
|||||||
|
|
||||||
// Link represents a link to share content.
|
// Link represents a link to share content.
|
||||||
type Link struct {
|
type Link struct {
|
||||||
LinkUID string `gorm:"type:VARBINARY(42);primaryKey;" json:"UID,omitempty" yaml:"UID,omitempty"`
|
LinkUID string `gorm:"size:42;primaryKey;" json:"UID,omitempty" yaml:"UID,omitempty"`
|
||||||
ShareUID string `gorm:"type:VARBINARY(42);uniqueIndex:idx_links_uid_token;" json:"ShareUID" yaml:"ShareUID"`
|
ShareUID string `gorm:"size:42;uniqueIndex:idx_links_uid_token;" json:"ShareUID" yaml:"ShareUID"`
|
||||||
ShareSlug string `gorm:"type:VARBINARY(160);index;" json:"Slug" yaml:"Slug,omitempty"`
|
ShareSlug string `gorm:"size:160;index;" json:"Slug" yaml:"Slug,omitempty"`
|
||||||
LinkToken string `gorm:"type:VARBINARY(160);uniqueIndex:idx_links_uid_token;" json:"Token" yaml:"Token,omitempty"`
|
LinkToken string `gorm:"size:160;uniqueIndex:idx_links_uid_token;" json:"Token" yaml:"Token,omitempty"`
|
||||||
LinkExpires int `json:"Expires" yaml:"Expires,omitempty"`
|
LinkExpires int `json:"Expires" yaml:"Expires,omitempty"`
|
||||||
LinkViews uint `json:"Views" yaml:"-"`
|
LinkViews uint `json:"Views" yaml:"-"`
|
||||||
MaxViews uint `json:"MaxViews" yaml:"-"`
|
MaxViews uint `json:"MaxViews" yaml:"-"`
|
||||||
HasPassword bool `json:"VerifyPassword" yaml:"VerifyPassword,omitempty"`
|
HasPassword bool `json:"VerifyPassword" yaml:"VerifyPassword,omitempty"`
|
||||||
Comment string `gorm:"size:512;" json:"Comment,omitempty" yaml:"Comment,omitempty"`
|
Comment string `gorm:"size:512;" json:"Comment,omitempty" yaml:"Comment,omitempty"`
|
||||||
Perm uint `json:"Perm,omitempty" yaml:"Perm,omitempty"`
|
Perm uint `json:"Perm,omitempty" yaml:"Perm,omitempty"`
|
||||||
RefID string `gorm:"type:VARBINARY(16);" json:"-" yaml:"-"`
|
RefID string `gorm:"size:16;" json:"-" yaml:"-"`
|
||||||
CreatedBy string `gorm:"type:VARBINARY(42);index" json:"CreatedBy,omitempty" yaml:"CreatedBy,omitempty"`
|
CreatedBy string `gorm:"size:42;index" json:"CreatedBy,omitempty" yaml:"CreatedBy,omitempty"`
|
||||||
CreatedAt time.Time `deepcopier:"skip" json:"CreatedAt" yaml:"CreatedAt"`
|
CreatedAt time.Time `deepcopier:"skip" json:"CreatedAt" yaml:"CreatedAt"`
|
||||||
ModifiedAt time.Time `deepcopier:"skip" json:"ModifiedAt" yaml:"ModifiedAt"`
|
ModifiedAt time.Time `deepcopier:"skip" json:"ModifiedAt" yaml:"ModifiedAt"`
|
||||||
}
|
}
|
||||||
|
@@ -25,22 +25,22 @@ const (
|
|||||||
|
|
||||||
// Marker represents an image marker point.
|
// Marker represents an image marker point.
|
||||||
type Marker struct {
|
type Marker struct {
|
||||||
MarkerUID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false;" json:"UID" yaml:"UID"`
|
MarkerUID string `gorm:"size:42;primaryKey;autoIncrement:false;" json:"UID" yaml:"UID"`
|
||||||
FileUID string `gorm:"type:VARBINARY(42);index;default:'';" json:"FileUID" yaml:"FileUID"`
|
FileUID string `gorm:"size:42;index;default:'';" json:"FileUID" yaml:"FileUID"`
|
||||||
MarkerType string `gorm:"type:VARBINARY(8);default:'';" json:"Type" yaml:"Type"`
|
MarkerType string `gorm:"size:8;default:'';" json:"Type" yaml:"Type"`
|
||||||
MarkerSrc string `gorm:"type:VARBINARY(8);default:'';" json:"Src" yaml:"Src,omitempty"`
|
MarkerSrc string `gorm:"size:8;default:'';" json:"Src" yaml:"Src,omitempty"`
|
||||||
MarkerName string `gorm:"type:VARCHAR(160);" json:"Name" yaml:"Name,omitempty"`
|
MarkerName string `gorm:"type:VARCHAR(160);" json:"Name" yaml:"Name,omitempty"`
|
||||||
MarkerReview bool `json:"Review" yaml:"Review,omitempty"`
|
MarkerReview bool `json:"Review" yaml:"Review,omitempty"`
|
||||||
MarkerInvalid bool `json:"Invalid" yaml:"Invalid,omitempty"`
|
MarkerInvalid bool `json:"Invalid" yaml:"Invalid,omitempty"`
|
||||||
SubjUID string `gorm:"type:VARBINARY(42);index:idx_markers_subj_uid_src;" json:"SubjUID" yaml:"SubjUID,omitempty"`
|
SubjUID string `gorm:"size:42;index:idx_markers_subj_uid_src;" json:"SubjUID" yaml:"SubjUID,omitempty"`
|
||||||
SubjSrc string `gorm:"type:VARBINARY(8);index:idx_markers_subj_uid_src;default:'';" json:"SubjSrc" yaml:"SubjSrc,omitempty"`
|
SubjSrc string `gorm:"size:8;index:idx_markers_subj_uid_src;default:'';" json:"SubjSrc" yaml:"SubjSrc,omitempty"`
|
||||||
subject *Subject `gorm:"foreignKey:SubjUID;"`
|
subject *Subject `gorm:"foreignKey:SubjUID;"`
|
||||||
FaceID string `gorm:"type:VARBINARY(64);index;" json:"FaceID" yaml:"FaceID,omitempty"`
|
FaceID string `gorm:"size:64;index;" json:"FaceID" yaml:"FaceID,omitempty"`
|
||||||
FaceDist float64 `gorm:"default:-1;" json:"FaceDist" yaml:"FaceDist,omitempty"`
|
FaceDist float64 `gorm:"default:-1;" json:"FaceDist" yaml:"FaceDist,omitempty"`
|
||||||
face *Face `gorm:"foreignKey:FaceID;"`
|
face *Face `gorm:"foreignKey:FaceID;"`
|
||||||
EmbeddingsJSON json.RawMessage `gorm:"type:MEDIUMBLOB;" json:"-" yaml:"EmbeddingsJSON,omitempty"`
|
EmbeddingsJSON json.RawMessage `json:"-" yaml:"EmbeddingsJSON,omitempty"`
|
||||||
embeddings face.Embeddings `gorm:"-" yaml:"-"`
|
embeddings face.Embeddings `gorm:"-" yaml:"-"`
|
||||||
LandmarksJSON json.RawMessage `gorm:"type:MEDIUMBLOB;" json:"-" yaml:"LandmarksJSON,omitempty"`
|
LandmarksJSON json.RawMessage `json:"-" yaml:"LandmarksJSON,omitempty"`
|
||||||
X float32 `gorm:"type:FLOAT;" json:"X" yaml:"X,omitempty"`
|
X float32 `gorm:"type:FLOAT;" json:"X" yaml:"X,omitempty"`
|
||||||
Y float32 `gorm:"type:FLOAT;" json:"Y" yaml:"Y,omitempty"`
|
Y float32 `gorm:"type:FLOAT;" json:"Y" yaml:"Y,omitempty"`
|
||||||
W float32 `gorm:"type:FLOAT;" json:"W" yaml:"W,omitempty"`
|
W float32 `gorm:"type:FLOAT;" json:"W" yaml:"W,omitempty"`
|
||||||
@@ -48,7 +48,7 @@ type Marker struct {
|
|||||||
Q int `json:"Q" yaml:"Q,omitempty"`
|
Q int `json:"Q" yaml:"Q,omitempty"`
|
||||||
Size int `gorm:"default:-1;" json:"Size" yaml:"Size,omitempty"`
|
Size int `gorm:"default:-1;" json:"Size" yaml:"Size,omitempty"`
|
||||||
Score int `gorm:"type:SMALLINT;" json:"Score" yaml:"Score,omitempty"`
|
Score int `gorm:"type:SMALLINT;" json:"Score" yaml:"Score,omitempty"`
|
||||||
Thumb string `gorm:"type:VARBINARY(128);index;default:'';" json:"Thumb" yaml:"Thumb,omitempty"`
|
Thumb string `gorm:"size:128;index;default:'';" json:"Thumb" yaml:"Thumb,omitempty"`
|
||||||
MatchedAt *time.Time `sql:"index" json:"MatchedAt" yaml:"MatchedAt,omitempty"`
|
MatchedAt *time.Time `sql:"index" json:"MatchedAt" yaml:"MatchedAt,omitempty"`
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
|
@@ -18,7 +18,7 @@ import (
|
|||||||
|
|
||||||
// Passcode represents a two-factor authentication key.
|
// Passcode represents a two-factor authentication key.
|
||||||
type Passcode struct {
|
type Passcode struct {
|
||||||
UID string `gorm:"type:VARBINARY(255);primaryKey;" json:"UID"`
|
UID string `gorm:"size:255;primaryKey;" json:"UID"`
|
||||||
KeyType string `gorm:"size:64;default:'';primaryKey;" json:"Type" yaml:"Type"`
|
KeyType string `gorm:"size:64;default:'';primaryKey;" json:"Type" yaml:"Type"`
|
||||||
KeyURL string `gorm:"size:2048;default:'';column:key_url;" json:"-" yaml:"-"`
|
KeyURL string `gorm:"size:2048;default:'';column:key_url;" json:"-" yaml:"-"`
|
||||||
key *otp.Key `gorm:"-" yaml:"-"`
|
key *otp.Key `gorm:"-" yaml:"-"`
|
||||||
|
@@ -16,8 +16,8 @@ var DefaultPasswordCost = 12
|
|||||||
|
|
||||||
// Password represents a password hash.
|
// Password represents a password hash.
|
||||||
type Password struct {
|
type Password struct {
|
||||||
UID string `gorm:"type:VARBINARY(255);primaryKey;" json:"UID"`
|
UID string `gorm:"size:255;primaryKey;" json:"UID"`
|
||||||
Hash string `deepcopier:"skip" gorm:"type:VARBINARY(255);" json:"Hash"`
|
Hash string `deepcopier:"skip" gorm:"size:255;" json:"Hash"`
|
||||||
CreatedAt time.Time `deepcopier:"skip" json:"CreatedAt"`
|
CreatedAt time.Time `deepcopier:"skip" json:"CreatedAt"`
|
||||||
UpdatedAt time.Time `deepcopier:"skip" json:"UpdatedAt"`
|
UpdatedAt time.Time `deepcopier:"skip" json:"UpdatedAt"`
|
||||||
}
|
}
|
||||||
|
@@ -53,39 +53,39 @@ func MapKey(takenAt time.Time, cellId string) string {
|
|||||||
// Photo represents a photo, all its properties, and link to all its images and sidecar files.
|
// Photo represents a photo, all its properties, and link to all its images and sidecar files.
|
||||||
type Photo struct {
|
type Photo struct {
|
||||||
ID uint `gorm:"primaryKey" yaml:"-"`
|
ID uint `gorm:"primaryKey" yaml:"-"`
|
||||||
UUID string `gorm:"type:VARBINARY(64);index;" json:"DocumentID,omitempty" yaml:"DocumentID,omitempty"`
|
UUID string `gorm:"size:64;index;" json:"DocumentID,omitempty" yaml:"DocumentID,omitempty"`
|
||||||
TakenAt time.Time `gorm:"type:DATETIME;index:idx_photos_taken_uid;" json:"TakenAt" yaml:"TakenAt"`
|
TakenAt time.Time `gorm:"index:idx_photos_taken_uid;" json:"TakenAt" yaml:"TakenAt"`
|
||||||
TakenAtLocal time.Time `gorm:"type:DATETIME;" json:"TakenAtLocal" yaml:"TakenAtLocal"`
|
TakenAtLocal time.Time `json:"TakenAtLocal" yaml:"TakenAtLocal"`
|
||||||
TakenSrc string `gorm:"type:VARBINARY(8);" json:"TakenSrc" yaml:"TakenSrc,omitempty"`
|
TakenSrc string `gorm:"size:8;" json:"TakenSrc" yaml:"TakenSrc,omitempty"`
|
||||||
PhotoUID string `gorm:"type:VARBINARY(42);uniqueIndex;index:idx_photos_taken_uid;" json:"UID" yaml:"UID"`
|
PhotoUID string `gorm:"size:42;uniqueIndex;index:idx_photos_taken_uid;" json:"UID" yaml:"UID"`
|
||||||
PhotoType string `gorm:"type:VARBINARY(8);default:'image';" json:"Type" yaml:"Type"`
|
PhotoType string `gorm:"size:8;default:'image';" json:"Type" yaml:"Type"`
|
||||||
TypeSrc string `gorm:"type:VARBINARY(8);" json:"TypeSrc" yaml:"TypeSrc,omitempty"`
|
TypeSrc string `gorm:"size:8;" json:"TypeSrc" yaml:"TypeSrc,omitempty"`
|
||||||
PhotoTitle string `gorm:"type:VARCHAR(200);" json:"Title" yaml:"Title"`
|
PhotoTitle string `gorm:"type:VARCHAR(200);" json:"Title" yaml:"Title"`
|
||||||
TitleSrc string `gorm:"type:VARBINARY(8);" json:"TitleSrc" yaml:"TitleSrc,omitempty"`
|
TitleSrc string `gorm:"size:8;" json:"TitleSrc" yaml:"TitleSrc,omitempty"`
|
||||||
PhotoDescription string `gorm:"type:VARCHAR(4096);" json:"Description" yaml:"Description,omitempty"`
|
PhotoDescription string `gorm:"type:VARCHAR(4096);" json:"Description" yaml:"Description,omitempty"`
|
||||||
DescriptionSrc string `gorm:"type:VARBINARY(8);" json:"DescriptionSrc" yaml:"DescriptionSrc,omitempty"`
|
DescriptionSrc string `gorm:"size:8;" json:"DescriptionSrc" yaml:"DescriptionSrc,omitempty"`
|
||||||
PhotoPath string `gorm:"type:VARBINARY(1024);index:idx_photos_path_name;" json:"Path" yaml:"-"`
|
PhotoPath string `gorm:"size:1024;index:idx_photos_path_name;" json:"Path" yaml:"-"`
|
||||||
PhotoName string `gorm:"type:VARBINARY(255);index:idx_photos_path_name;" json:"Name" yaml:"-"`
|
PhotoName string `gorm:"size:255;index:idx_photos_path_name;" json:"Name" yaml:"-"`
|
||||||
OriginalName string `gorm:"type:VARBINARY(755);" json:"OriginalName" yaml:"OriginalName,omitempty"`
|
OriginalName string `gorm:"size:755;" json:"OriginalName" yaml:"OriginalName,omitempty"`
|
||||||
PhotoStack int8 `json:"Stack" yaml:"Stack,omitempty"`
|
PhotoStack int8 `json:"Stack" yaml:"Stack,omitempty"`
|
||||||
PhotoFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
PhotoFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
||||||
PhotoPrivate bool `json:"Private" yaml:"Private,omitempty"`
|
PhotoPrivate bool `json:"Private" yaml:"Private,omitempty"`
|
||||||
PhotoScan bool `json:"Scan" yaml:"Scan,omitempty"`
|
PhotoScan bool `json:"Scan" yaml:"Scan,omitempty"`
|
||||||
PhotoPanorama bool `json:"Panorama" yaml:"Panorama,omitempty"`
|
PhotoPanorama bool `json:"Panorama" yaml:"Panorama,omitempty"`
|
||||||
TimeZone string `gorm:"type:VARBINARY(64);" json:"TimeZone" yaml:"TimeZone,omitempty"`
|
TimeZone string `gorm:"size:64;" json:"TimeZone" yaml:"TimeZone,omitempty"`
|
||||||
PlaceID string `gorm:"type:VARBINARY(42);index;default:'zz'" json:"PlaceID" yaml:"-"`
|
PlaceID string `gorm:"size:42;index;default:'zz'" json:"PlaceID" yaml:"-"`
|
||||||
PlaceSrc string `gorm:"type:VARBINARY(8);" json:"PlaceSrc" yaml:"PlaceSrc,omitempty"`
|
PlaceSrc string `gorm:"size:8;" json:"PlaceSrc" yaml:"PlaceSrc,omitempty"`
|
||||||
CellID string `gorm:"type:VARBINARY(42);index;default:'zz'" json:"CellID" yaml:"-"`
|
CellID string `gorm:"size:42;index;default:'zz'" json:"CellID" yaml:"-"`
|
||||||
CellAccuracy int `json:"CellAccuracy" yaml:"CellAccuracy,omitempty"`
|
CellAccuracy int `json:"CellAccuracy" yaml:"CellAccuracy,omitempty"`
|
||||||
PhotoAltitude int `json:"Altitude" yaml:"Altitude,omitempty"`
|
PhotoAltitude int `json:"Altitude" yaml:"Altitude,omitempty"`
|
||||||
PhotoLat float32 `gorm:"type:FLOAT;index;" json:"Lat" yaml:"Lat,omitempty"`
|
PhotoLat float32 `gorm:"type:FLOAT;index;" json:"Lat" yaml:"Lat,omitempty"`
|
||||||
PhotoLng float32 `gorm:"type:FLOAT;index;" json:"Lng" yaml:"Lng,omitempty"`
|
PhotoLng float32 `gorm:"type:FLOAT;index;" json:"Lng" yaml:"Lng,omitempty"`
|
||||||
PhotoCountry string `gorm:"type:VARBINARY(2);index:idx_photos_country_year_month;default:'zz'" json:"Country" yaml:"-"`
|
PhotoCountry string `gorm:"size:2;index:idx_photos_country_year_month;default:'zz'" json:"Country" yaml:"-"`
|
||||||
PhotoYear int `gorm:"index:idx_photos_ymd;index:idx_photos_country_year_month;" json:"Year" yaml:"Year"`
|
PhotoYear int `gorm:"index:idx_photos_ymd;index:idx_photos_country_year_month;" json:"Year" yaml:"Year"`
|
||||||
PhotoMonth int `gorm:"index:idx_photos_ymd;index:idx_photos_country_year_month;" json:"Month" yaml:"Month"`
|
PhotoMonth int `gorm:"index:idx_photos_ymd;index:idx_photos_country_year_month;" json:"Month" yaml:"Month"`
|
||||||
PhotoDay int `gorm:"index:idx_photos_ymd" json:"Day" yaml:"Day"`
|
PhotoDay int `gorm:"index:idx_photos_ymd" json:"Day" yaml:"Day"`
|
||||||
PhotoIso int `json:"Iso" yaml:"ISO,omitempty"`
|
PhotoIso int `json:"Iso" yaml:"ISO,omitempty"`
|
||||||
PhotoExposure string `gorm:"type:VARBINARY(64);" json:"Exposure" yaml:"Exposure,omitempty"`
|
PhotoExposure string `gorm:"size:64;" json:"Exposure" yaml:"Exposure,omitempty"`
|
||||||
PhotoFNumber float32 `gorm:"type:FLOAT;" json:"FNumber" yaml:"FNumber,omitempty"`
|
PhotoFNumber float32 `gorm:"type:FLOAT;" json:"FNumber" yaml:"FNumber,omitempty"`
|
||||||
PhotoFocalLength int `json:"FocalLength" yaml:"FocalLength,omitempty"`
|
PhotoFocalLength int `json:"FocalLength" yaml:"FocalLength,omitempty"`
|
||||||
PhotoQuality int `gorm:"type:SMALLINT" json:"Quality" yaml:"Quality,omitempty"`
|
PhotoQuality int `gorm:"type:SMALLINT" json:"Quality" yaml:"Quality,omitempty"`
|
||||||
@@ -94,19 +94,19 @@ type Photo struct {
|
|||||||
PhotoDuration time.Duration `json:"Duration,omitempty" yaml:"Duration,omitempty"`
|
PhotoDuration time.Duration `json:"Duration,omitempty" yaml:"Duration,omitempty"`
|
||||||
PhotoColor int16 `json:"Color" yaml:"-"`
|
PhotoColor int16 `json:"Color" yaml:"-"`
|
||||||
CameraID uint `gorm:"index:idx_photos_camera_lens;default:1" json:"CameraID" yaml:"-"`
|
CameraID uint `gorm:"index:idx_photos_camera_lens;default:1" json:"CameraID" yaml:"-"`
|
||||||
CameraSerial string `gorm:"type:VARBINARY(160);" json:"CameraSerial" yaml:"CameraSerial,omitempty"`
|
CameraSerial string `gorm:"size:160;" json:"CameraSerial" yaml:"CameraSerial,omitempty"`
|
||||||
CameraSrc string `gorm:"type:VARBINARY(8);" json:"CameraSrc" yaml:"-"`
|
CameraSrc string `gorm:"size:8;" json:"CameraSrc" yaml:"-"`
|
||||||
LensID uint `gorm:"index:idx_photos_camera_lens;default:1" json:"LensID" yaml:"-"`
|
LensID uint `gorm:"index:idx_photos_camera_lens;default:1" json:"LensID" yaml:"-"`
|
||||||
Details *Details `json:"Details" yaml:"Details"`
|
Details *Details `gorm:"foreignKey:PhotoID" json:"Details" yaml:"Details"`
|
||||||
Camera *Camera `json:"Camera" yaml:"-"`
|
Camera *Camera `json:"Camera" yaml:"-"`
|
||||||
Lens *Lens `json:"Lens" yaml:"-"`
|
Lens *Lens `json:"Lens" yaml:"-"`
|
||||||
Cell *Cell `json:"Cell" yaml:"-"`
|
Cell *Cell `json:"Cell" yaml:"-"`
|
||||||
Place *Place `json:"Place" yaml:"-"`
|
Place *Place `json:"Place" yaml:"-"`
|
||||||
Keywords []Keyword `gorm:"many2many:photos_keywords;foreignKey:ID;joinForeignKey:PhotoID;References:ID;joinReferences:KeywordID" json:"-" yaml:"-"`
|
Keywords []Keyword `gorm:"many2many:photos_keywords;foreignKey:ID;joinForeignKey:PhotoID;References:ID;joinReferences:KeywordID" json:"-" yaml:"-"`
|
||||||
Albums []Album `gorm:"many2many:photos_albums;foreignKey:PhotoUID;References:AlbumUID" json:"Albums" yaml:"-"`
|
Albums []Album `gorm:"many2many:photos_albums;foreignKey:PhotoUID;joinForeignKey:photo_uid;References:AlbumUID;joinReferences:album_uid" json:"Albums" yaml:"-"`
|
||||||
Files []File `yaml:"-"`
|
Files []File `yaml:"-"`
|
||||||
Labels []PhotoLabel `gorm:"foreignKey:PhotoID" yaml:"-"`
|
Labels []PhotoLabel `yaml:"-"`
|
||||||
CreatedBy string `gorm:"type:VARBINARY(42);index" json:"CreatedBy,omitempty" yaml:"CreatedBy,omitempty"`
|
CreatedBy string `gorm:"size:42;index" json:"CreatedBy,omitempty" yaml:"CreatedBy,omitempty"`
|
||||||
CreatedAt time.Time `yaml:"CreatedAt,omitempty"`
|
CreatedAt time.Time `yaml:"CreatedAt,omitempty"`
|
||||||
UpdatedAt time.Time `yaml:"UpdatedAt,omitempty"`
|
UpdatedAt time.Time `yaml:"UpdatedAt,omitempty"`
|
||||||
EditedAt *time.Time `yaml:"EditedAt,omitempty"`
|
EditedAt *time.Time `yaml:"EditedAt,omitempty"`
|
||||||
@@ -503,7 +503,7 @@ func (m *Photo) PreloadAlbums() {
|
|||||||
q := Db().
|
q := Db().
|
||||||
Table("albums").
|
Table("albums").
|
||||||
Select(`albums.*`).
|
Select(`albums.*`).
|
||||||
Joins("JOIN photos_albums pa ON pa.album_uid = albums.album_uid AND pa.photo_uid = ? AND pa.hidden = 0", m.PhotoUID).
|
Joins("JOIN photos_albums pa ON pa.album_uid = albums.album_uid AND pa.photo_uid = ? AND pa.hidden = FALSE", m.PhotoUID).
|
||||||
Where("albums.deleted_at IS NULL").
|
Where("albums.deleted_at IS NULL").
|
||||||
Order("albums.album_title ASC")
|
Order("albums.album_title ASC")
|
||||||
|
|
||||||
@@ -702,7 +702,7 @@ func (m *Photo) AllFilesMissing() bool {
|
|||||||
count := int64(0)
|
count := int64(0)
|
||||||
|
|
||||||
if err := Db().Model(&File{}).
|
if err := Db().Model(&File{}).
|
||||||
Where("photo_id = ? AND file_missing = 0", m.ID).
|
Where("photo_id = ? AND file_missing = FALSE", m.ID).
|
||||||
Count(&count).Error; err != nil {
|
Count(&count).Error; err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
@@ -922,7 +922,7 @@ func (m *Photo) SetPrimary(fileUid string) (err error) {
|
|||||||
if fileUid != "" {
|
if fileUid != "" {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
} else if err = Db().Model(File{}).
|
} else if err = Db().Model(File{}).
|
||||||
Where("photo_uid = ? AND file_type IN (?) AND file_missing = 0 AND file_error = ''", m.PhotoUID, media.PreviewExpr).
|
Where("photo_uid = ? AND file_type IN (?) AND file_missing = FALSE AND file_error = ''", m.PhotoUID, media.PreviewExpr).
|
||||||
Order("file_width DESC, file_hdr DESC").Limit(1).
|
Order("file_width DESC, file_hdr DESC").Limit(1).
|
||||||
Pluck("file_uid", &files).Error; err != nil {
|
Pluck("file_uid", &files).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -4,19 +4,17 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PhotoAlbums []PhotoAlbum
|
type PhotoAlbums = []PhotoAlbum
|
||||||
|
|
||||||
// PhotoAlbum represents the many_to_many relation between Photo and Album
|
// PhotoAlbum represents the many_to_many relation between Photo and Album
|
||||||
type PhotoAlbum struct {
|
type PhotoAlbum struct {
|
||||||
PhotoUID string `gorm:"type:VARBINARY(42);primaryKey;" json:"PhotoUID" yaml:"UID"`
|
PhotoUID string `gorm:"size:42;primaryKey:pk_pa" json:"PhotoUID" yaml:"UID"`
|
||||||
AlbumUID string `gorm:"type:VARBINARY(42);primaryKey;" json:"AlbumUID" yaml:"-"`
|
AlbumUID string `gorm:"size:42;primaryKey:pk_pa" json:"AlbumUID" yaml:"-"`
|
||||||
Order int `json:"Order" yaml:"Order,omitempty"`
|
Order int `json:"Order" yaml:"Order,omitempty"`
|
||||||
Hidden bool `json:"Hidden" yaml:"Hidden,omitempty"`
|
Hidden bool `json:"Hidden" yaml:"Hidden,omitempty"`
|
||||||
Missing bool `json:"Missing" yaml:"Missing,omitempty"`
|
Missing bool `json:"Missing" yaml:"Missing,omitempty"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt,omitempty"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt,omitempty"`
|
||||||
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
||||||
Photo *Photo `gorm:"foreignKey:PhotoUID;references:PhotoUID;" yaml:"-"`
|
|
||||||
Album *Album `gorm:"foreignKey:AlbumUID;references:AlbumUID;" yaml:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the entity table name.
|
// TableName returns the entity table name.
|
||||||
|
@@ -29,8 +29,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 3, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 3, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 3, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 3, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("19800101_000002_D640C559"),
|
|
||||||
Album: AlbumFixtures.Pointer("holiday-2030"),
|
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
PhotoUID: "ps6sg6be2lvl0y11",
|
PhotoUID: "ps6sg6be2lvl0y11",
|
||||||
@@ -40,8 +38,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo04"),
|
|
||||||
Album: AlbumFixtures.Pointer("berlin-2019"),
|
|
||||||
},
|
},
|
||||||
"3": {
|
"3": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh8",
|
PhotoUID: "ps6sg6be2lvl0yh8",
|
||||||
@@ -51,8 +47,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo01"),
|
|
||||||
Album: AlbumFixtures.Pointer("berlin-2019"),
|
|
||||||
},
|
},
|
||||||
"4": {
|
"4": {
|
||||||
PhotoUID: "ps6sg6bexxvl0yh0",
|
PhotoUID: "ps6sg6bexxvl0yh0",
|
||||||
@@ -62,8 +56,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo19"),
|
|
||||||
Album: AlbumFixtures.Pointer("april-1990"),
|
|
||||||
},
|
},
|
||||||
"5": {
|
"5": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -73,8 +65,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("berlin-2019"),
|
|
||||||
},
|
},
|
||||||
"6": {
|
"6": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -84,8 +74,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("berlin-2019"),
|
|
||||||
},
|
},
|
||||||
"7": {
|
"7": {
|
||||||
PhotoUID: "ps6sg6be2lvl0y21",
|
PhotoUID: "ps6sg6be2lvl0y21",
|
||||||
@@ -95,8 +83,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 1,
|
Order: 1,
|
||||||
CreatedAt: time.Date(2020, 3, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 3, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 5, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 5, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo14"),
|
|
||||||
Album: AlbumFixtures.Pointer("berlin-2019"),
|
|
||||||
},
|
},
|
||||||
"8": {
|
"8": {
|
||||||
PhotoUID: "ps6sg6be2lvl0y21",
|
PhotoUID: "ps6sg6be2lvl0y21",
|
||||||
@@ -106,8 +92,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 1,
|
Order: 1,
|
||||||
CreatedAt: time.Date(2020, 3, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 3, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 5, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 5, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo14"),
|
|
||||||
Album: AlbumFixtures.Pointer("berlin-2019"),
|
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -117,8 +101,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("light&"),
|
|
||||||
},
|
},
|
||||||
"10": {
|
"10": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -128,8 +110,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("pets&dogs"),
|
|
||||||
},
|
},
|
||||||
"11": {
|
"11": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -139,8 +119,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("&ilikefood"),
|
|
||||||
},
|
},
|
||||||
"12": {
|
"12": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -150,8 +128,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("sale%"),
|
|
||||||
},
|
},
|
||||||
"13": {
|
"13": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -161,8 +137,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("%gold"),
|
|
||||||
},
|
},
|
||||||
"14": {
|
"14": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -172,8 +146,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("i-love-%-dog"),
|
|
||||||
},
|
},
|
||||||
"15": {
|
"15": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -183,8 +155,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("'family"),
|
|
||||||
},
|
},
|
||||||
"16": {
|
"16": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -194,8 +164,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("father's-day"),
|
|
||||||
},
|
},
|
||||||
"17": {
|
"17": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -205,8 +173,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("ice-cream'"),
|
|
||||||
},
|
},
|
||||||
"18": {
|
"18": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -216,8 +182,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("*forrest"),
|
|
||||||
},
|
},
|
||||||
"19": {
|
"19": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -227,8 +191,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("my*kids"),
|
|
||||||
},
|
},
|
||||||
"20": {
|
"20": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -238,8 +200,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("yoga***"),
|
|
||||||
},
|
},
|
||||||
"21": {
|
"21": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -249,8 +209,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("|banana"),
|
|
||||||
},
|
},
|
||||||
"22": {
|
"22": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -260,8 +218,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("red|green"),
|
|
||||||
},
|
},
|
||||||
"23": {
|
"23": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -271,8 +227,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("blue|"),
|
|
||||||
},
|
},
|
||||||
"24": {
|
"24": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -282,8 +236,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("345-shirt"),
|
|
||||||
},
|
},
|
||||||
"25": {
|
"25": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -293,8 +245,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("color-555-blue"),
|
|
||||||
},
|
},
|
||||||
"26": {
|
"26": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh0",
|
PhotoUID: "ps6sg6be2lvl0yh0",
|
||||||
@@ -304,8 +254,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo03"),
|
|
||||||
Album: AlbumFixtures.Pointer("route-66"),
|
|
||||||
},
|
},
|
||||||
"27": {
|
"27": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh9",
|
PhotoUID: "ps6sg6be2lvl0yh9",
|
||||||
@@ -315,8 +263,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo02"),
|
|
||||||
Album: AlbumFixtures.Pointer("father's-day"),
|
|
||||||
},
|
},
|
||||||
"28": {
|
"28": {
|
||||||
PhotoUID: "ps6sg6be2lvl0yh9",
|
PhotoUID: "ps6sg6be2lvl0yh9",
|
||||||
@@ -326,8 +272,6 @@ var PhotoAlbumFixtures = PhotoAlbumMap{
|
|||||||
Order: 0,
|
Order: 0,
|
||||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||||
Photo: PhotoFixtures.Pointer("Photo02"),
|
|
||||||
Album: AlbumFixtures.Pointer("light&"),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,10 +11,10 @@ type PhotoLabels []PhotoLabel
|
|||||||
type PhotoLabel struct {
|
type PhotoLabel struct {
|
||||||
PhotoID uint `gorm:"primaryKey;autoIncrement:false"`
|
PhotoID uint `gorm:"primaryKey;autoIncrement:false"`
|
||||||
LabelID uint `gorm:"primaryKey;autoIncrement:false"`
|
LabelID uint `gorm:"primaryKey;autoIncrement:false"`
|
||||||
LabelSrc string `gorm:"type:VARBINARY(8);"`
|
LabelSrc string `gorm:"size:8;"`
|
||||||
Uncertainty int `gorm:"type:SMALLINT"`
|
Uncertainty int `gorm:"type:SMALLINT"`
|
||||||
Photo *Photo
|
Photo *Photo `gorm:"foreignKey:PhotoID;references:ID;" yaml:"-"`
|
||||||
Label *Label
|
Label *Label `gorm:"foreignKey:LabelID;references:ID;"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the entity table name.
|
// TableName returns the entity table name.
|
||||||
|
@@ -13,7 +13,7 @@ var photoMergeMutex = sync.Mutex{}
|
|||||||
func (m *Photo) ResolvePrimary() error {
|
func (m *Photo) ResolvePrimary() error {
|
||||||
var file File
|
var file File
|
||||||
|
|
||||||
if err := Db().Where("file_primary = 1 AND photo_id = ?", m.ID).
|
if err := Db().Where("file_primary = TRUE AND photo_id = ?", m.ID).
|
||||||
Order("file_width DESC, file_hdr DESC").
|
Order("file_width DESC, file_hdr DESC").
|
||||||
First(&file).Error; err == nil && file.ID > 0 {
|
First(&file).Error; err == nil && file.ID > 0 {
|
||||||
return file.ResolvePrimary()
|
return file.ResolvePrimary()
|
||||||
@@ -103,7 +103,7 @@ func (m *Photo) Merge(mergeMeta, mergeUuid bool) (original Photo, merged Photos,
|
|||||||
|
|
||||||
deleted := TimeStamp()
|
deleted := TimeStamp()
|
||||||
|
|
||||||
logResult(UnscopedDb().Exec("UPDATE files SET photo_id = ?, photo_uid = ?, file_primary = 0 WHERE photo_id = ?", original.ID, original.PhotoUID, merge.ID))
|
logResult(UnscopedDb().Exec("UPDATE files SET photo_id = ?, photo_uid = ?, file_primary = FALSE WHERE photo_id = ?", original.ID, original.PhotoUID, merge.ID))
|
||||||
logResult(UnscopedDb().Exec("UPDATE photos SET photo_quality = -1, deleted_at = ? WHERE id = ?", TimeStamp(), merge.ID))
|
logResult(UnscopedDb().Exec("UPDATE photos SET photo_quality = -1, deleted_at = ? WHERE id = ?", TimeStamp(), merge.ID))
|
||||||
|
|
||||||
switch DbDialect() {
|
switch DbDialect() {
|
||||||
|
@@ -4,9 +4,9 @@ import "github.com/photoprism/photoprism/internal/event"
|
|||||||
|
|
||||||
// PhotoUser represents the user and group ownership of a Photo and the corresponding permissions.
|
// PhotoUser represents the user and group ownership of a Photo and the corresponding permissions.
|
||||||
type PhotoUser struct {
|
type PhotoUser struct {
|
||||||
UID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false" json:"UID" yaml:"UID"`
|
UID string `gorm:"size:42;primaryKey;autoIncrement:false" json:"UID" yaml:"UID"`
|
||||||
UserUID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false;index" json:"UserUID,omitempty" yaml:"UserUID,omitempty"`
|
UserUID string `gorm:"size:42;primaryKey;autoIncrement:false;index" json:"UserUID,omitempty" yaml:"UserUID,omitempty"`
|
||||||
TeamUID string `gorm:"type:VARBINARY(42);index" json:"TeamUID,omitempty" yaml:"TeamUID,omitempty"`
|
TeamUID string `gorm:"size:42;index" json:"TeamUID,omitempty" yaml:"TeamUID,omitempty"`
|
||||||
Perm uint `json:"Perm,omitempty" yaml:"Perm,omitempty"`
|
Perm uint `json:"Perm,omitempty" yaml:"Perm,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,12 +13,12 @@ var placeMutex = sync.Mutex{}
|
|||||||
|
|
||||||
// Place represents a distinct region identified by city, district, state, and country.
|
// Place represents a distinct region identified by city, district, state, and country.
|
||||||
type Place struct {
|
type Place struct {
|
||||||
ID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false;" json:"PlaceID" yaml:"PlaceID"`
|
ID string `gorm:"size:42;primaryKey;autoIncrement:false;" json:"PlaceID" yaml:"PlaceID"`
|
||||||
PlaceLabel string `gorm:"type:VARCHAR(400);" json:"Label" yaml:"Label"`
|
PlaceLabel string `gorm:"type:VARCHAR(400);" json:"Label" yaml:"Label"`
|
||||||
PlaceDistrict string `gorm:"type:VARCHAR(100);index;" json:"District" yaml:"District,omitempty"`
|
PlaceDistrict string `gorm:"type:VARCHAR(100);index;" json:"District" yaml:"District,omitempty"`
|
||||||
PlaceCity string `gorm:"type:VARCHAR(100);index;" json:"City" yaml:"City,omitempty"`
|
PlaceCity string `gorm:"type:VARCHAR(100);index;" json:"City" yaml:"City,omitempty"`
|
||||||
PlaceState string `gorm:"type:VARCHAR(100);index;" json:"State" yaml:"State,omitempty"`
|
PlaceState string `gorm:"type:VARCHAR(100);index;" json:"State" yaml:"State,omitempty"`
|
||||||
PlaceCountry string `gorm:"type:VARBINARY(2);" json:"Country" yaml:"Country,omitempty"`
|
PlaceCountry string `gorm:"size:2;" json:"Country" yaml:"Country,omitempty"`
|
||||||
PlaceKeywords string `gorm:"type:VARCHAR(300);" json:"Keywords" yaml:"Keywords,omitempty"`
|
PlaceKeywords string `gorm:"type:VARCHAR(300);" json:"Keywords" yaml:"Keywords,omitempty"`
|
||||||
PlaceFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
PlaceFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
||||||
PhotoCount int `gorm:"default:1" json:"PhotoCount" yaml:"-"`
|
PhotoCount int `gorm:"default:1" json:"PhotoCount" yaml:"-"`
|
||||||
|
@@ -11,9 +11,9 @@ import (
|
|||||||
|
|
||||||
// Reaction represents a human response to content such as photos and albums.
|
// Reaction represents a human response to content such as photos and albums.
|
||||||
type Reaction struct {
|
type Reaction struct {
|
||||||
UID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false" json:"UID,omitempty" yaml:"UID,omitempty"`
|
UID string `gorm:"size:42;primaryKey;autoIncrement:false" json:"UID,omitempty" yaml:"UID,omitempty"`
|
||||||
UserUID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false" json:"UserUID,omitempty" yaml:"UserUID,omitempty"`
|
UserUID string `gorm:"size:42;primaryKey;autoIncrement:false" json:"UserUID,omitempty" yaml:"UserUID,omitempty"`
|
||||||
Reaction string `gorm:"type:VARBINARY(64);primaryKey;autoIncrement:false" json:"Reaction,omitempty" yaml:"Reaction,omitempty"`
|
Reaction string `gorm:"size:64;primaryKey;autoIncrement:false" json:"Reaction,omitempty" yaml:"Reaction,omitempty"`
|
||||||
Reacted int `json:"Reacted,omitempty" yaml:"Reacted,omitempty"`
|
Reacted int `json:"Reacted,omitempty" yaml:"Reacted,omitempty"`
|
||||||
ReactedAt *time.Time `sql:"index" json:"ReactedAt,omitempty" yaml:"ReactedAt,omitempty"`
|
ReactedAt *time.Time `sql:"index" json:"ReactedAt,omitempty" yaml:"ReactedAt,omitempty"`
|
||||||
}
|
}
|
||||||
|
@@ -37,21 +37,21 @@ type Service struct {
|
|||||||
AccName string `gorm:"type:VARCHAR(160);"`
|
AccName string `gorm:"type:VARCHAR(160);"`
|
||||||
AccOwner string `gorm:"type:VARCHAR(160);"`
|
AccOwner string `gorm:"type:VARCHAR(160);"`
|
||||||
AccURL string `gorm:"type:VARCHAR(255);"`
|
AccURL string `gorm:"type:VARCHAR(255);"`
|
||||||
AccType string `gorm:"type:VARBINARY(255);"`
|
AccType string `gorm:"size:255;"`
|
||||||
AccKey string `gorm:"type:VARBINARY(255);"`
|
AccKey string `gorm:"size:255;"`
|
||||||
AccUser string `gorm:"type:VARBINARY(255);"`
|
AccUser string `gorm:"size:255;"`
|
||||||
AccPass string `gorm:"type:VARBINARY(255);"`
|
AccPass string `gorm:"size:255;"`
|
||||||
AccTimeout string `gorm:"type:VARBINARY(16);"`
|
AccTimeout string `gorm:"size:16;"`
|
||||||
AccError string `gorm:"type:VARBINARY(512);"`
|
AccError string `gorm:"size:512;"`
|
||||||
AccErrors int
|
AccErrors int
|
||||||
AccShare bool
|
AccShare bool
|
||||||
AccSync bool
|
AccSync bool
|
||||||
RetryLimit int
|
RetryLimit int
|
||||||
SharePath string `gorm:"type:VARBINARY(1024);"`
|
SharePath string `gorm:"size:1024;"`
|
||||||
ShareSize string `gorm:"type:VARBINARY(16);"`
|
ShareSize string `gorm:"size:16;"`
|
||||||
ShareExpires int
|
ShareExpires int
|
||||||
SyncPath string `gorm:"type:VARBINARY(1024);"`
|
SyncPath string `gorm:"size:1024;"`
|
||||||
SyncStatus string `gorm:"type:VARBINARY(16);"`
|
SyncStatus string `gorm:"size:16;"`
|
||||||
SyncInterval int
|
SyncInterval int
|
||||||
SyncDate sql.NullTime `deepcopier:"skip"`
|
SyncDate sql.NullTime `deepcopier:"skip"`
|
||||||
SyncUpload bool
|
SyncUpload bool
|
||||||
|
@@ -19,10 +19,10 @@ var subjectMutex = sync.Mutex{}
|
|||||||
|
|
||||||
// Subject represents a named photo subject, typically a person.
|
// Subject represents a named photo subject, typically a person.
|
||||||
type Subject struct {
|
type Subject struct {
|
||||||
SubjUID string `gorm:"type:VARBINARY(42);primaryKey;autoIncrement:false;" json:"UID" yaml:"UID"`
|
SubjUID string `gorm:"size:42;primaryKey;autoIncrement:false;" json:"UID" yaml:"UID"`
|
||||||
SubjType string `gorm:"type:VARBINARY(8);default:'';" json:"Type,omitempty" yaml:"Type,omitempty"`
|
SubjType string `gorm:"size:8;default:'';" json:"Type,omitempty" yaml:"Type,omitempty"`
|
||||||
SubjSrc string `gorm:"type:VARBINARY(8);default:'';" json:"Src,omitempty" yaml:"Src,omitempty"`
|
SubjSrc string `gorm:"size:8;default:'';" json:"Src,omitempty" yaml:"Src,omitempty"`
|
||||||
SubjSlug string `gorm:"type:VARBINARY(160);index;default:'';" json:"Slug" yaml:"-"`
|
SubjSlug string `gorm:"size:160;index;default:'';" json:"Slug" yaml:"-"`
|
||||||
SubjName string `gorm:"size:160;uniqueIndex;default:'';" json:"Name" yaml:"Name"`
|
SubjName string `gorm:"size:160;uniqueIndex;default:'';" json:"Name" yaml:"Name"`
|
||||||
SubjAlias string `gorm:"size:160;default:'';" json:"Alias" yaml:"Alias"`
|
SubjAlias string `gorm:"size:160;default:'';" json:"Alias" yaml:"Alias"`
|
||||||
SubjAbout string `gorm:"size:512;" json:"About" yaml:"About,omitempty"`
|
SubjAbout string `gorm:"size:512;" json:"About" yaml:"About,omitempty"`
|
||||||
@@ -34,8 +34,8 @@ type Subject struct {
|
|||||||
SubjExcluded bool `gorm:"default:false;" json:"Excluded" yaml:"Excluded,omitempty"`
|
SubjExcluded bool `gorm:"default:false;" json:"Excluded" yaml:"Excluded,omitempty"`
|
||||||
FileCount int `gorm:"default:0;" json:"FileCount" yaml:"-"`
|
FileCount int `gorm:"default:0;" json:"FileCount" yaml:"-"`
|
||||||
PhotoCount int `gorm:"default:0;" json:"PhotoCount" yaml:"-"`
|
PhotoCount int `gorm:"default:0;" json:"PhotoCount" yaml:"-"`
|
||||||
Thumb string `gorm:"type:VARBINARY(128);index;default:'';" json:"Thumb" yaml:"Thumb,omitempty"`
|
Thumb string `gorm:"size:128;index;default:'';" json:"Thumb" yaml:"Thumb,omitempty"`
|
||||||
ThumbSrc string `gorm:"type:VARBINARY(8);default:'';" json:"ThumbSrc,omitempty" yaml:"ThumbSrc,omitempty"`
|
ThumbSrc string `gorm:"size:8;default:'';" json:"ThumbSrc,omitempty" yaml:"ThumbSrc,omitempty"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
|
||||||
DeletedAt *time.Time `sql:"index" json:"DeletedAt,omitempty" yaml:"-"`
|
DeletedAt *time.Time `sql:"index" json:"DeletedAt,omitempty" yaml:"-"`
|
||||||
|
@@ -73,7 +73,7 @@ var DialectMySQL = Migrations{
|
|||||||
ID: "20220329-083000",
|
ID: "20220329-083000",
|
||||||
Dialect: "mysql",
|
Dialect: "mysql",
|
||||||
Stage: "main",
|
Stage: "main",
|
||||||
Statements: []string{"UPDATE files SET media_id = CASE WHEN file_missing = 0 AND deleted_at IS NULL THEN CONCAT((10000000000 - photo_id), '-', 1 + file_sidecar - file_primary, '-', file_uid) END;"},
|
Statements: []string{"UPDATE files SET media_id = CASE WHEN file_missing = FALSE AND deleted_at IS NULL THEN CONCAT((10000000000 - photo_id), '-', 1 + file_sidecar - file_primary, '-', file_uid) END;"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "20220329-090000",
|
ID: "20220329-090000",
|
||||||
@@ -91,7 +91,7 @@ var DialectMySQL = Migrations{
|
|||||||
ID: "20220329-093000",
|
ID: "20220329-093000",
|
||||||
Dialect: "mysql",
|
Dialect: "mysql",
|
||||||
Stage: "main",
|
Stage: "main",
|
||||||
Statements: []string{"UPDATE files SET time_index = CASE WHEN file_missing = 0 AND deleted_at IS NULL THEN CONCAT(100000000000000 - CAST(photo_taken_at AS UNSIGNED), '-', media_id) END;"},
|
Statements: []string{"UPDATE files SET time_index = CASE WHEN file_missing = FALSE AND deleted_at IS NULL THEN CONCAT(100000000000000 - CAST(photo_taken_at AS UNSIGNED), '-', media_id) END;"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "20220421-200000",
|
ID: "20220421-200000",
|
||||||
|
5
internal/migrate/dialect_postgres.go
Normal file
5
internal/migrate/dialect_postgres.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package migrate
|
||||||
|
|
||||||
|
// Generated code, do not edit.
|
||||||
|
|
||||||
|
var DialectPostgres = Migrations{}
|
102
internal/migrate/dialect_sqlite.go
Normal file
102
internal/migrate/dialect_sqlite.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package migrate
|
||||||
|
|
||||||
|
// Generated code, do not edit.
|
||||||
|
|
||||||
|
var DialectSQLite = Migrations{
|
||||||
|
{
|
||||||
|
ID: "20211121-094727",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"DROP INDEX IF EXISTS idx_places_place_label;"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20211124-120008",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"DROP INDEX IF EXISTS uix_places_place_label;", "DROP INDEX IF EXISTS uix_places_label;"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20220329-040000",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"DROP INDEX IF EXISTS idx_albums_album_filter;"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20220329-050000",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"CREATE INDEX IF NOT EXISTS idx_albums_album_filter ON albums (album_filter);"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20220329-061000",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"CREATE INDEX IF NOT EXISTS idx_files_photo_id ON files (photo_id, file_primary);"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20220329-071000",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"UPDATE files SET photo_taken_at = (SELECT taken_at_local FROM photos WHERE photos.id = photo_id) WHERE photo_id IS NOT NULL;"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20220329-081000",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"CREATE UNIQUE INDEX IF NOT EXISTS idx_files_search_media ON files (media_id);"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20220329-083000",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"UPDATE files SET media_id = CASE WHEN photo_id IS NOT NULL AND file_missing = FALSE AND deleted_at IS NULL THEN ((10000000000 - photo_id) || '-' || (1 + file_sidecar - file_primary) || '-' || file_uid) END WHERE 1;"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20220329-091000",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"CREATE UNIQUE INDEX IF NOT EXISTS idx_files_search_timeline ON files (time_index);"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20220329-093000",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"UPDATE files SET time_index = CASE WHEN media_id IS NOT NULL AND photo_taken_at IS NOT NULL THEN ((100000000000000 - strftime('%Y%m%d%H%M%S', photo_taken_at)) || '-' || media_id) ELSE NULL END WHERE photo_id IS NOT NULL;"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20220421-200000",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"CREATE INDEX IF NOT EXISTS idx_files_missing_root ON files (file_missing, file_root);"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20221015-100000",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "pre",
|
||||||
|
Statements: []string{"ALTER TABLE accounts RENAME TO services;"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20221015-100100",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "pre",
|
||||||
|
Statements: []string{"ALTER TABLE files_sync RENAME COLUMN account_id TO service_id;", "ALTER TABLE files_share RENAME COLUMN account_id TO service_id;"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20230309-000001",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"UPDATE auth_users SET auth_provider = 'local' WHERE id = 1;", "UPDATE auth_users SET auth_provider = 'none' WHERE id = -1;", "UPDATE auth_users SET auth_provider = 'token' WHERE id = -2;", "UPDATE auth_users SET auth_provider = 'default' WHERE auth_provider = '' OR auth_provider = 'password' OR auth_provider IS NULL;"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20230313-000001",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"UPDATE auth_users SET user_role = 'contributor' WHERE user_role = 'uploader';", "UPDATE auth_sessions SET auth_provider = 'link' WHERE auth_provider = 'token';"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "20240112-000001",
|
||||||
|
Dialect: "sqlite",
|
||||||
|
Stage: "main",
|
||||||
|
Statements: []string{"DELETE FROM auth_sessions;"},
|
||||||
|
},
|
||||||
|
}
|
@@ -49,7 +49,7 @@ var DialectSQLite3 = Migrations{
|
|||||||
ID: "20220329-083000",
|
ID: "20220329-083000",
|
||||||
Dialect: "sqlite",
|
Dialect: "sqlite",
|
||||||
Stage: "main",
|
Stage: "main",
|
||||||
Statements: []string{"UPDATE files SET media_id = CASE WHEN photo_id IS NOT NULL AND file_missing = 0 AND deleted_at IS NULL THEN ((10000000000 - photo_id) || '-' || (1 + file_sidecar - file_primary) || '-' || file_uid) END WHERE 1;"},
|
Statements: []string{"UPDATE files SET media_id = CASE WHEN photo_id IS NOT NULL AND file_missing = FALSE AND deleted_at IS NULL THEN ((10000000000 - photo_id) || '-' || (1 + file_sidecar - file_primary) || '-' || file_uid) END WHERE 1;"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "20220329-091000",
|
ID: "20220329-091000",
|
||||||
|
@@ -4,16 +4,19 @@ import "sync"
|
|||||||
|
|
||||||
// Supported database dialects.
|
// Supported database dialects.
|
||||||
const (
|
const (
|
||||||
MySQL = "mysql"
|
MySQL = "mysql"
|
||||||
SQLite3 = "sqlite"
|
SQLite3 = "sqlite"
|
||||||
|
Postgres = "postgres"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Dialects = map[string]Migrations{
|
var Dialects = map[string]Migrations{
|
||||||
MySQL: DialectMySQL,
|
MySQL: DialectMySQL,
|
||||||
SQLite3: DialectSQLite3,
|
SQLite3: DialectSQLite3,
|
||||||
|
Postgres: DialectPostgres,
|
||||||
}
|
}
|
||||||
|
|
||||||
var once = map[string]*sync.Once{
|
var once = map[string]*sync.Once{
|
||||||
MySQL: {},
|
MySQL: {},
|
||||||
SQLite3: {},
|
SQLite3: {},
|
||||||
|
Postgres: {},
|
||||||
}
|
}
|
||||||
|
@@ -117,6 +117,7 @@ func gen_migrations(name string) {
|
|||||||
func main() {
|
func main() {
|
||||||
gen_migrations("MySQL")
|
gen_migrations("MySQL")
|
||||||
gen_migrations("SQLite")
|
gen_migrations("SQLite")
|
||||||
|
gen_migrations("Postgres")
|
||||||
}
|
}
|
||||||
|
|
||||||
var migrationsTemplate = template.Must(template.New("").Parse(`
|
var migrationsTemplate = template.Must(template.New("").Parse(`
|
||||||
|
@@ -21,6 +21,7 @@ func Run(db *gorm.DB, opt Options) (err error) {
|
|||||||
|
|
||||||
// Make sure a "migrations" table exists.
|
// Make sure a "migrations" table exists.
|
||||||
once[name].Do(func() {
|
once[name].Do(func() {
|
||||||
|
|
||||||
err = db.AutoMigrate(&Migration{})
|
err = db.AutoMigrate(&Migration{})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -29,8 +30,10 @@ func Run(db *gorm.DB, opt Options) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run migrations for dialect.
|
// Run migrations for dialect.
|
||||||
if migrations, ok := Dialects[name]; ok && len(migrations) > 0 {
|
if migrations, ok := Dialects[name]; ok {
|
||||||
migrations.Start(db, opt)
|
if len(migrations) > 0 {
|
||||||
|
migrations.Start(db, opt)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("migrate: no migrations found for %s", name)
|
return fmt.Errorf("migrate: no migrations found for %s", name)
|
||||||
|
@@ -60,7 +60,7 @@ func (m *Version) Migrated(db *gorm.DB) error {
|
|||||||
m.MigratedAt = &timeStamp
|
m.MigratedAt = &timeStamp
|
||||||
m.Error = ""
|
m.Error = ""
|
||||||
|
|
||||||
return db.Model(m).Updates(Map{"MigratedAt": m.MigratedAt, "Error": m.Error}).Error
|
return db.Save(m).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVersion creates a Version entity from a model name and a make name.
|
// NewVersion creates a Version entity from a model name and a make name.
|
||||||
|
@@ -152,7 +152,7 @@ func (ind *Index) UserMediaFile(m *MediaFile, o IndexOptions, originalName, phot
|
|||||||
} else if photoQuery = entity.UnscopedDb().First(&photo, "photo_path = ? AND photo_name = ? AND photo_stack > -1", filePath, fileBase); photoQuery.Error == nil {
|
} else if photoQuery = entity.UnscopedDb().First(&photo, "photo_path = ? AND photo_name = ? AND photo_stack > -1", filePath, fileBase); photoQuery.Error == nil {
|
||||||
// Found.
|
// Found.
|
||||||
fileStacked = true
|
fileStacked = true
|
||||||
} else if photoQuery = entity.UnscopedDb().First(&photo, "id IN (SELECT photo_id FROM files WHERE file_name = LIKE ? AND file_root = ? AND file_sidecar = 0 AND file_missing = 0) AND photo_path = ? AND photo_stack > -1", fs.StripKnownExt(fileName)+".%", entity.RootOriginals, filePath); photoQuery.Error == nil {
|
} else if photoQuery = entity.UnscopedDb().First(&photo, "id IN (SELECT photo_id FROM files WHERE file_name = LIKE ? AND file_root = ? AND file_sidecar = FALSE AND file_missing = FALSE) AND photo_path = ? AND photo_stack > -1", fs.StripKnownExt(fileName)+".%", entity.RootOriginals, filePath); photoQuery.Error == nil {
|
||||||
// Found.
|
// Found.
|
||||||
fileStacked = true
|
fileStacked = true
|
||||||
}
|
}
|
||||||
@@ -287,7 +287,7 @@ func (ind *Index) UserMediaFile(m *MediaFile, o IndexOptions, originalName, phot
|
|||||||
// Flag first JPEG as primary file for this photo.
|
// Flag first JPEG as primary file for this photo.
|
||||||
if !file.FilePrimary {
|
if !file.FilePrimary {
|
||||||
if photoExists {
|
if photoExists {
|
||||||
if res := entity.UnscopedDb().Where("photo_id = ? AND file_primary = 1 AND file_type IN (?) AND file_error = ''", photo.ID, media.PreviewExpr).First(&primaryFile); res.Error != nil {
|
if res := entity.UnscopedDb().Where("photo_id = ? AND file_primary = TRUE AND file_type IN (?) AND file_error = ''", photo.ID, media.PreviewExpr).First(&primaryFile); res.Error != nil {
|
||||||
file.FilePrimary = m.IsPreviewImage()
|
file.FilePrimary = m.IsPreviewImage()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
// AccountUploads a list of files for uploading to a remote account.
|
// AccountUploads a list of files for uploading to a remote account.
|
||||||
func AccountUploads(a entity.Service, limit int) (results entity.Files, err error) {
|
func AccountUploads(a entity.Service, limit int) (results entity.Files, err error) {
|
||||||
s := Db().Where("files.file_missing = 0").
|
s := Db().Where("files.file_missing = FALSE").
|
||||||
Where("files.id NOT IN (SELECT file_id FROM files_sync WHERE file_id > 0 AND service_id = ?)", a.ID)
|
Where("files.id NOT IN (SELECT file_id FROM files_sync WHERE file_id > 0 AND service_id = ?)", a.ID)
|
||||||
|
|
||||||
if !a.SyncRaw {
|
if !a.SyncRaw {
|
||||||
|
@@ -62,7 +62,7 @@ func AlbumCoverByUID(uid string, public bool) (file entity.File, err error) {
|
|||||||
return file, err
|
return file, err
|
||||||
} else if len(photos) > 0 {
|
} else if len(photos) > 0 {
|
||||||
for _, photo := range photos {
|
for _, photo := range photos {
|
||||||
if err := Db().Where("photo_uid = ? AND file_primary = 1", photo.PhotoUID).First(&file).Error; err != nil {
|
if err := Db().Where("photo_uid = ? AND file_primary = TRUE", photo.PhotoUID).First(&file).Error; err != nil {
|
||||||
return file, err
|
return file, err
|
||||||
} else {
|
} else {
|
||||||
return file, nil
|
return file, nil
|
||||||
@@ -85,14 +85,14 @@ func AlbumCoverByUID(uid string, public bool) (file entity.File, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build query.
|
// Build query.
|
||||||
stmt := Db().Where("files.file_primary = 1 AND files.file_missing = 0 AND files.file_type IN (?) AND files.deleted_at IS NULL", media.PreviewExpr).
|
stmt := Db().Where("files.file_primary = TRUE AND files.file_missing = FALSE AND files.file_type IN (?) AND files.deleted_at IS NULL", media.PreviewExpr).
|
||||||
Joins("JOIN albums a ON a.album_uid = ?", uid).
|
Joins("JOIN albums a ON a.album_uid = ?", uid).
|
||||||
Joins("JOIN photos_albums pa ON pa.album_uid = a.album_uid AND pa.photo_uid = files.photo_uid AND pa.hidden = 0 AND pa.missing = 0").
|
Joins("JOIN photos_albums pa ON pa.album_uid = a.album_uid AND pa.photo_uid = files.photo_uid AND pa.hidden = FALSE AND pa.missing = FALSE").
|
||||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.deleted_at IS NULL")
|
Joins("JOIN photos ON photos.id = files.photo_id AND photos.deleted_at IS NULL")
|
||||||
|
|
||||||
// Public pictures only?
|
// Public pictures only?
|
||||||
if public {
|
if public {
|
||||||
stmt = stmt.Where("photos.photo_private = 0")
|
stmt = stmt.Where("photos.photo_private = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find first picture.
|
// Find first picture.
|
||||||
@@ -130,7 +130,7 @@ func UpdateMissingAlbumEntries() error {
|
|||||||
|
|
||||||
switch DbDialect() {
|
switch DbDialect() {
|
||||||
default:
|
default:
|
||||||
return UnscopedDb().Exec(`UPDATE photos_albums SET missing = 1
|
return UnscopedDb().Exec(`UPDATE photos_albums SET missing = TRUE
|
||||||
WHERE photo_uid IN (SELECT photo_uid FROM photos WHERE deleted_at IS NOT NULL OR photo_quality < 0)
|
WHERE photo_uid IN (SELECT photo_uid FROM photos WHERE deleted_at IS NOT NULL OR photo_quality < 0)
|
||||||
OR photo_uid IN (SELECT pa.photo_uid FROM photos_albums pa LEFT JOIN photos p ON pa.photo_uid = p.photo_uid WHERE p.photo_uid IS NULL)`).Error
|
OR photo_uid IN (SELECT pa.photo_uid FROM photos_albums pa LEFT JOIN photos p ON pa.photo_uid = p.photo_uid WHERE p.photo_uid IS NULL)`).Error
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ func AlbumEntryFound(uid string) error {
|
|||||||
|
|
||||||
switch DbDialect() {
|
switch DbDialect() {
|
||||||
default:
|
default:
|
||||||
return UnscopedDb().Exec(`UPDATE photos_albums SET missing = 0 WHERE photo_uid = ?`, uid).Error
|
return UnscopedDb().Exec(`UPDATE photos_albums SET missing = FALSE WHERE photo_uid = ?`, uid).Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,13 +35,13 @@ func (c *Counts) Refresh() {
|
|||||||
Take(c)
|
Take(c)
|
||||||
|
|
||||||
Db().Table("photos").
|
Db().Table("photos").
|
||||||
Select("SUM(photo_type = 'video' AND photo_quality > -1 AND photo_private = 0) AS videos, " +
|
Select("COUNT(CASE WHEN photo_type = 'video' AND photo_quality > -1 AND photo_private = FALSE THEN 1 END) AS videos, " +
|
||||||
"SUM(photo_quality > -1 AND photo_quality < 3 AND photo_private = 0) AS review, " +
|
"COUNT(CASE WHEN photo_quality > -1 AND photo_quality < 3 AND photo_private = FALSE THEN 1 END) AS review, " +
|
||||||
"SUM(photo_quality = -1) AS hidden, " +
|
"COUNT(CASE WHEN photo_quality = -1 THEN 1 END) AS hidden, " +
|
||||||
"SUM(photo_type NOT IN ('live', 'video') AND photo_quality > -1 AND photo_private = 0) AS photos, " +
|
"COUNT(CASE WHEN photo_type NOT IN ('live', 'video') AND photo_quality > -1 AND photo_private = FALSE THEN 1 END) AS photos, " +
|
||||||
"SUM(photo_favorite = 1 AND photo_private = 0 AND photo_quality > -1) AS favorites, " +
|
"COUNT(CASE WHEN photo_favorite = TRUE AND photo_private = FALSE AND photo_quality > -1 THEN 1 END) AS favorites, " +
|
||||||
"SUM(photo_private = 1 AND photo_quality > -1) AS private").
|
"COUNT(CASE WHEN photo_private = TRUE AND photo_quality > -1 THEN 1 END) AS private").
|
||||||
Where("photos.id NOT IN (SELECT photo_id FROM files WHERE file_primary = 1 AND (file_missing = 1 OR file_error <> ''))").
|
Where("photos.id NOT IN (SELECT photo_id FROM files WHERE file_primary = TRUE AND (file_missing = TRUE OR file_error <> ''))").
|
||||||
Where("deleted_at IS NULL").
|
Where("deleted_at IS NULL").
|
||||||
Take(c)
|
Take(c)
|
||||||
|
|
||||||
@@ -49,19 +49,19 @@ func (c *Counts) Refresh() {
|
|||||||
Select("MAX(photo_count) as label_max_photos, COUNT(*) AS labels").
|
Select("MAX(photo_count) as label_max_photos, COUNT(*) AS labels").
|
||||||
Where("photo_count > 0").
|
Where("photo_count > 0").
|
||||||
Where("deleted_at IS NULL").
|
Where("deleted_at IS NULL").
|
||||||
Where("(label_priority >= 0 OR label_favorite = 1)").
|
Where("(label_priority >= 0 OR label_favorite = TRUE)").
|
||||||
Take(c)
|
Take(c)
|
||||||
|
|
||||||
Db().Table("albums").
|
Db().Table("albums").
|
||||||
Select("SUM(album_type = ?) AS albums, SUM(album_type = ?) AS moments, "+
|
Select("COUNT(CASE WHEN album_type = ? THEN 1 END) AS albums, COUNT(CASE WHEN album_type = ? THEN 1 END) AS moments, "+
|
||||||
"SUM(album_type = ?) AS folders",
|
"COUNT(CASE WHEN album_type = ? THEN 1 END) AS folders",
|
||||||
entity.AlbumManual, entity.AlbumMoment, entity.AlbumFolder).
|
entity.AlbumManual, entity.AlbumMoment, entity.AlbumFolder).
|
||||||
Where("deleted_at IS NULL").
|
Where("deleted_at IS NULL").
|
||||||
Take(c)
|
Take(c)
|
||||||
|
|
||||||
Db().Table("files").
|
Db().Table("files").
|
||||||
Select("COUNT(*) AS files").
|
Select("COUNT(*) AS files").
|
||||||
Where("file_missing = 0 AND file_root = ?", entity.RootOriginals).
|
Where("file_missing = FALSE AND file_root = ?", entity.RootOriginals).
|
||||||
Take(c)
|
Take(c)
|
||||||
|
|
||||||
Db().Table("countries").
|
Db().Table("countries").
|
||||||
@@ -69,7 +69,7 @@ func (c *Counts) Refresh() {
|
|||||||
Take(c)
|
Take(c)
|
||||||
|
|
||||||
Db().Table("places").
|
Db().Table("places").
|
||||||
Select("SUM(photo_count > 0) AS places").
|
Select("COUNT(CASE WHEN photo_count > 0 THEN 1 END) AS places").
|
||||||
Where("id <> 'zz'").
|
Where("id <> 'zz'").
|
||||||
Take(c)
|
Take(c)
|
||||||
}
|
}
|
||||||
|
@@ -29,18 +29,18 @@ func UpdateAlbumDefaultCovers() (err error) {
|
|||||||
res = Db().Exec(`UPDATE albums LEFT JOIN (
|
res = Db().Exec(`UPDATE albums LEFT JOIN (
|
||||||
SELECT p2.album_uid, f.file_hash FROM files f, (
|
SELECT p2.album_uid, f.file_hash FROM files f, (
|
||||||
SELECT pa.album_uid, max(p.id) AS photo_id FROM photos p
|
SELECT pa.album_uid, max(p.id) AS photo_id FROM photos p
|
||||||
JOIN photos_albums pa ON pa.photo_uid = p.photo_uid AND pa.hidden = 0 AND pa.missing = 0
|
JOIN photos_albums pa ON pa.photo_uid = p.photo_uid AND pa.hidden = FALSE AND pa.missing = FALSE
|
||||||
WHERE p.photo_quality > 0 AND p.photo_private = 0 AND p.deleted_at IS NULL
|
WHERE p.photo_quality > 0 AND p.photo_private = FALSE AND p.deleted_at IS NULL
|
||||||
GROUP BY pa.album_uid) p2 WHERE p2.photo_id = f.photo_id AND f.file_primary = 1 AND f.file_error = '' AND f.file_type IN (?)
|
GROUP BY pa.album_uid) p2 WHERE p2.photo_id = f.photo_id AND f.file_primary = TRUE AND f.file_error = '' AND f.file_type IN (?)
|
||||||
) b ON b.album_uid = albums.album_uid
|
) b ON b.album_uid = albums.album_uid
|
||||||
SET thumb = b.file_hash WHERE ?`, media.PreviewExpr, condition)
|
SET thumb = b.file_hash WHERE ?`, media.PreviewExpr, condition)
|
||||||
case SQLite3:
|
case SQLite3:
|
||||||
res = Db().Table(entity.Album{}.TableName()).
|
res = Db().Table(entity.Album{}.TableName()).
|
||||||
UpdateColumn("thumb", gorm.Expr(`(
|
UpdateColumn("thumb", gorm.Expr(`(
|
||||||
SELECT f.file_hash FROM files f
|
SELECT f.file_hash FROM files f
|
||||||
JOIN photos_albums pa ON pa.album_uid = albums.album_uid AND pa.photo_uid = f.photo_uid AND pa.hidden = 0 AND pa.missing = 0
|
JOIN photos_albums pa ON pa.album_uid = albums.album_uid AND pa.photo_uid = f.photo_uid AND pa.hidden = FALSE AND pa.missing = FALSE
|
||||||
JOIN photos p ON p.id = f.photo_id AND p.photo_private = 0 AND p.deleted_at IS NULL AND p.photo_quality > 0
|
JOIN photos p ON p.id = f.photo_id AND p.photo_private = FALSE AND p.deleted_at IS NULL AND p.photo_quality > 0
|
||||||
WHERE f.deleted_at IS NULL AND f.file_missing = 0 AND f.file_hash <> '' AND f.file_primary = 1 AND f.file_error = '' AND f.file_type IN (?)
|
WHERE f.deleted_at IS NULL AND f.file_missing = FALSE AND f.file_hash <> '' AND f.file_primary = TRUE AND f.file_error = '' AND f.file_type IN (?)
|
||||||
ORDER BY p.taken_at DESC LIMIT 1
|
ORDER BY p.taken_at DESC LIMIT 1
|
||||||
) WHERE ?`, media.PreviewExpr, condition))
|
) WHERE ?`, media.PreviewExpr, condition))
|
||||||
default:
|
default:
|
||||||
@@ -77,18 +77,18 @@ func UpdateAlbumFolderCovers() (err error) {
|
|||||||
res = Db().Exec(`UPDATE albums LEFT JOIN (
|
res = Db().Exec(`UPDATE albums LEFT JOIN (
|
||||||
SELECT p2.photo_path, f.file_hash FROM files f, (
|
SELECT p2.photo_path, f.file_hash FROM files f, (
|
||||||
SELECT p.photo_path, max(p.id) AS photo_id FROM photos p
|
SELECT p.photo_path, max(p.id) AS photo_id FROM photos p
|
||||||
WHERE p.photo_quality > 0 AND p.photo_private = 0 AND p.deleted_at IS NULL
|
WHERE p.photo_quality > 0 AND p.photo_private = FALSE AND p.deleted_at IS NULL
|
||||||
GROUP BY p.photo_path) p2 WHERE p2.photo_id = f.photo_id AND f.file_primary = 1 AND f.file_error = '' AND f.file_type IN (?)
|
GROUP BY p.photo_path) p2 WHERE p2.photo_id = f.photo_id AND f.file_primary = TRUE AND f.file_error = '' AND f.file_type IN (?)
|
||||||
) b ON b.photo_path = albums.album_path
|
) b ON b.photo_path = albums.album_path
|
||||||
SET thumb = b.file_hash WHERE ?`, media.PreviewExpr, condition)
|
SET thumb = b.file_hash WHERE ?`, media.PreviewExpr, condition)
|
||||||
case SQLite3:
|
case SQLite3:
|
||||||
res = Db().Table(entity.Album{}.TableName()).UpdateColumn("thumb", gorm.Expr(`(
|
res = Db().Table(entity.Album{}.TableName()).UpdateColumn("thumb", gorm.Expr(`(
|
||||||
SELECT f.file_hash FROM files f,(
|
SELECT f.file_hash FROM files f,(
|
||||||
SELECT p.photo_path, max(p.id) AS photo_id FROM photos p
|
SELECT p.photo_path, max(p.id) AS photo_id FROM photos p
|
||||||
WHERE p.photo_quality > 0 AND p.photo_private = 0 AND p.deleted_at IS NULL
|
WHERE p.photo_quality > 0 AND p.photo_private = FALSE AND p.deleted_at IS NULL
|
||||||
GROUP BY p.photo_path
|
GROUP BY p.photo_path
|
||||||
) b
|
) b
|
||||||
WHERE f.photo_id = b.photo_id AND f.file_primary = 1 AND f.file_error = '' AND f.file_type IN (?)
|
WHERE f.photo_id = b.photo_id AND f.file_primary = TRUE AND f.file_error = '' AND f.file_type IN (?)
|
||||||
AND b.photo_path = albums.album_path LIMIT 1)
|
AND b.photo_path = albums.album_path LIMIT 1)
|
||||||
WHERE ?`, media.PreviewExpr, condition))
|
WHERE ?`, media.PreviewExpr, condition))
|
||||||
default:
|
default:
|
||||||
@@ -125,18 +125,18 @@ func UpdateAlbumMonthCovers() (err error) {
|
|||||||
res = Db().Exec(`UPDATE albums LEFT JOIN (
|
res = Db().Exec(`UPDATE albums LEFT JOIN (
|
||||||
SELECT p2.photo_year, p2.photo_month, f.file_hash FROM files f, (
|
SELECT p2.photo_year, p2.photo_month, f.file_hash FROM files f, (
|
||||||
SELECT p.photo_year, p.photo_month, max(p.id) AS photo_id FROM photos p
|
SELECT p.photo_year, p.photo_month, max(p.id) AS photo_id FROM photos p
|
||||||
WHERE p.photo_quality > 0 AND p.photo_private = 0 AND p.deleted_at IS NULL
|
WHERE p.photo_quality > 0 AND p.photo_private = FALSE AND p.deleted_at IS NULL
|
||||||
GROUP BY p.photo_year, p.photo_month) p2 WHERE p2.photo_id = f.photo_id AND f.file_primary = 1 AND f.file_error = '' AND f.file_type IN (?)
|
GROUP BY p.photo_year, p.photo_month) p2 WHERE p2.photo_id = f.photo_id AND f.file_primary = TRUE AND f.file_error = '' AND f.file_type IN (?)
|
||||||
) b ON b.photo_year = albums.album_year AND b.photo_month = albums.album_month
|
) b ON b.photo_year = albums.album_year AND b.photo_month = albums.album_month
|
||||||
SET thumb = b.file_hash WHERE ?`, media.PreviewExpr, condition)
|
SET thumb = b.file_hash WHERE ?`, media.PreviewExpr, condition)
|
||||||
case SQLite3:
|
case SQLite3:
|
||||||
res = Db().Table(entity.Album{}.TableName()).UpdateColumn("thumb", gorm.Expr(`(
|
res = Db().Table(entity.Album{}.TableName()).UpdateColumn("thumb", gorm.Expr(`(
|
||||||
SELECT f.file_hash FROM files f,(
|
SELECT f.file_hash FROM files f,(
|
||||||
SELECT p.photo_year, p.photo_month, max(p.id) AS photo_id FROM photos p
|
SELECT p.photo_year, p.photo_month, max(p.id) AS photo_id FROM photos p
|
||||||
WHERE p.photo_quality > 0 AND p.photo_private = 0 AND p.deleted_at IS NULL
|
WHERE p.photo_quality > 0 AND p.photo_private = FALSE AND p.deleted_at IS NULL
|
||||||
GROUP BY p.photo_year, p.photo_month
|
GROUP BY p.photo_year, p.photo_month
|
||||||
) b
|
) b
|
||||||
WHERE f.photo_id = b.photo_id AND f.file_primary = 1 AND f.file_error = '' AND f.file_type IN (?)
|
WHERE f.photo_id = b.photo_id AND f.file_primary = TRUE AND f.file_error = '' AND f.file_type IN (?)
|
||||||
AND b.photo_year = albums.album_year AND b.photo_month = albums.album_month LIMIT 1)
|
AND b.photo_year = albums.album_year AND b.photo_month = albums.album_month LIMIT 1)
|
||||||
WHERE ?`, media.PreviewExpr, condition))
|
WHERE ?`, media.PreviewExpr, condition))
|
||||||
default:
|
default:
|
||||||
@@ -194,23 +194,23 @@ func UpdateLabelCovers() (err error) {
|
|||||||
SELECT p2.label_id, f.file_hash FROM files f, (
|
SELECT p2.label_id, f.file_hash FROM files f, (
|
||||||
SELECT pl.label_id as label_id, max(p.id) AS photo_id FROM photos p
|
SELECT pl.label_id as label_id, max(p.id) AS photo_id FROM photos p
|
||||||
JOIN photos_labels pl ON pl.photo_id = p.id AND pl.uncertainty < 100
|
JOIN photos_labels pl ON pl.photo_id = p.id AND pl.uncertainty < 100
|
||||||
WHERE p.photo_quality > 0 AND p.photo_private = 0 AND p.deleted_at IS NULL
|
WHERE p.photo_quality > 0 AND p.photo_private = FALSE AND p.deleted_at IS NULL
|
||||||
GROUP BY pl.label_id
|
GROUP BY pl.label_id
|
||||||
UNION
|
UNION
|
||||||
SELECT c.category_id as label_id, max(p.id) AS photo_id FROM photos p
|
SELECT c.category_id as label_id, max(p.id) AS photo_id FROM photos p
|
||||||
JOIN photos_labels pl ON pl.photo_id = p.id AND pl.uncertainty < 100
|
JOIN photos_labels pl ON pl.photo_id = p.id AND pl.uncertainty < 100
|
||||||
JOIN categories c ON c.label_id = pl.label_id
|
JOIN categories c ON c.label_id = pl.label_id
|
||||||
WHERE p.photo_quality > 0 AND p.photo_private = 0 AND p.deleted_at IS NULL
|
WHERE p.photo_quality > 0 AND p.photo_private = FALSE AND p.deleted_at IS NULL
|
||||||
GROUP BY c.category_id
|
GROUP BY c.category_id
|
||||||
) p2 WHERE p2.photo_id = f.photo_id AND f.file_primary = 1 AND f.file_error = '' AND f.file_type IN (?) AND f.file_missing = 0
|
) p2 WHERE p2.photo_id = f.photo_id AND f.file_primary = TRUE AND f.file_error = '' AND f.file_type IN (?) AND f.file_missing = FALSE
|
||||||
) b ON b.label_id = labels.id
|
) b ON b.label_id = labels.id
|
||||||
SET thumb = b.file_hash WHERE ?`, media.PreviewExpr, condition)
|
SET thumb = b.file_hash WHERE ?`, media.PreviewExpr, condition)
|
||||||
case SQLite3:
|
case SQLite3:
|
||||||
res = Db().Table(entity.Label{}.TableName()).UpdateColumn("thumb", gorm.Expr(`(
|
res = Db().Table(entity.Label{}.TableName()).UpdateColumn("thumb", gorm.Expr(`(
|
||||||
SELECT f.file_hash FROM files f
|
SELECT f.file_hash FROM files f
|
||||||
JOIN photos_labels pl ON pl.label_id = labels.id AND pl.photo_id = f.photo_id AND pl.uncertainty < 100
|
JOIN photos_labels pl ON pl.label_id = labels.id AND pl.photo_id = f.photo_id AND pl.uncertainty < 100
|
||||||
JOIN photos p ON p.id = f.photo_id AND p.photo_private = 0 AND p.deleted_at IS NULL AND p.photo_quality > 0
|
JOIN photos p ON p.id = f.photo_id AND p.photo_private = FALSE AND p.deleted_at IS NULL AND p.photo_quality > 0
|
||||||
WHERE f.deleted_at IS NULL AND f.file_hash <> '' AND f.file_missing = 0 AND f.file_primary = 1 AND f.file_error = '' AND f.file_type IN (?)
|
WHERE f.deleted_at IS NULL AND f.file_hash <> '' AND f.file_missing = FALSE AND f.file_primary = TRUE AND f.file_error = '' AND f.file_type IN (?)
|
||||||
ORDER BY p.photo_quality DESC, pl.uncertainty ASC, p.taken_at DESC LIMIT 1
|
ORDER BY p.photo_quality DESC, pl.uncertainty ASC, p.taken_at DESC LIMIT 1
|
||||||
) WHERE ?`, media.PreviewExpr, condition))
|
) WHERE ?`, media.PreviewExpr, condition))
|
||||||
|
|
||||||
@@ -219,8 +219,8 @@ func UpdateLabelCovers() (err error) {
|
|||||||
SELECT f.file_hash FROM files f
|
SELECT f.file_hash FROM files f
|
||||||
JOIN photos_labels pl ON pl.photo_id = f.photo_id AND pl.uncertainty < 100
|
JOIN photos_labels pl ON pl.photo_id = f.photo_id AND pl.uncertainty < 100
|
||||||
JOIN categories c ON c.label_id = pl.label_id AND c.category_id = labels.id
|
JOIN categories c ON c.label_id = pl.label_id AND c.category_id = labels.id
|
||||||
JOIN photos p ON p.id = f.photo_id AND p.photo_private = 0 AND p.deleted_at IS NULL AND p.photo_quality > 0
|
JOIN photos p ON p.id = f.photo_id AND p.photo_private = FALSE AND p.deleted_at IS NULL AND p.photo_quality > 0
|
||||||
WHERE f.deleted_at IS NULL AND f.file_hash <> '' AND f.file_missing = 0 AND f.file_primary = 1 AND f.file_error = '' AND f.file_type IN (?)
|
WHERE f.deleted_at IS NULL AND f.file_hash <> '' AND f.file_missing = FALSE AND f.file_primary = TRUE AND f.file_error = '' AND f.file_type IN (?)
|
||||||
ORDER BY p.photo_quality DESC, pl.uncertainty ASC, p.taken_at DESC LIMIT 1
|
ORDER BY p.photo_quality DESC, pl.uncertainty ASC, p.taken_at DESC LIMIT 1
|
||||||
) WHERE thumb IS NULL`, media.PreviewExpr))
|
) WHERE thumb IS NULL`, media.PreviewExpr))
|
||||||
|
|
||||||
|
@@ -112,7 +112,7 @@ func SelectedFiles(f form.Selection, o FileSelection) (results entity.Files, err
|
|||||||
OR photos.photo_path IN (
|
OR photos.photo_path IN (
|
||||||
SELECT a.path FROM folders a WHERE a.folder_uid IN (?) UNION
|
SELECT a.path FROM folders a WHERE a.folder_uid IN (?) UNION
|
||||||
SELECT b.path FROM folders a JOIN folders b ON b.path LIKE %s WHERE a.folder_uid IN (?))
|
SELECT b.path FROM folders a JOIN folders b ON b.path LIKE %s WHERE a.folder_uid IN (?))
|
||||||
OR photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = 0 AND album_uid IN (?))
|
OR photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = FALSE AND album_uid IN (?))
|
||||||
OR files.file_uid IN (SELECT file_uid FROM %s m WHERE m.subj_uid IN (?))
|
OR files.file_uid IN (SELECT file_uid FROM %s m WHERE m.subj_uid IN (?))
|
||||||
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN labels l ON pl.label_id = l.id AND pl.uncertainty < 100 AND l.deleted_at IS NULL WHERE l.label_uid IN (?))
|
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN labels l ON pl.label_id = l.id AND pl.uncertainty < 100 AND l.deleted_at IS NULL WHERE l.label_uid IN (?))
|
||||||
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN categories c ON c.label_id = pl.label_id AND pl.uncertainty < 100 JOIN labels lc ON lc.id = c.category_id AND lc.deleted_at IS NULL WHERE lc.label_uid IN (?))`,
|
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN categories c ON c.label_id = pl.label_id AND pl.uncertainty < 100 JOIN labels lc ON lc.id = c.category_id AND lc.deleted_at IS NULL WHERE lc.label_uid IN (?))`,
|
||||||
@@ -122,7 +122,7 @@ func SelectedFiles(f form.Selection, o FileSelection) (results entity.Files, err
|
|||||||
s := UnscopedDb().Table("files").
|
s := UnscopedDb().Table("files").
|
||||||
Select("files.*").
|
Select("files.*").
|
||||||
Joins("JOIN photos ON photos.id = files.photo_id").
|
Joins("JOIN photos ON photos.id = files.photo_id").
|
||||||
Where("files.file_missing = 0 AND files.file_name <> '' AND files.file_hash <> ''").
|
Where("files.file_missing = FALSE AND files.file_name <> '' AND files.file_hash <> ''").
|
||||||
Where(where, f.Photos, f.Places, f.Files, f.Files, f.Files, f.Albums, f.Subjects, f.Labels, f.Labels).
|
Where(where, f.Photos, f.Places, f.Files, f.Files, f.Files, f.Albums, f.Subjects, f.Labels, f.Labels).
|
||||||
Group("files.id")
|
Group("files.id")
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ func SelectedFiles(f form.Selection, o FileSelection) (results entity.Files, err
|
|||||||
|
|
||||||
// Previews files only?
|
// Previews files only?
|
||||||
if o.Primary {
|
if o.Primary {
|
||||||
s = s.Where("files.file_primary = 1")
|
s = s.Where("files.file_primary = TRUE")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Files in originals only?
|
// Files in originals only?
|
||||||
|
@@ -19,11 +19,11 @@ func FilesByPath(limit, offset int, rootName, pathName string, public bool) (fil
|
|||||||
stmt := Db().
|
stmt := Db().
|
||||||
Table("files").Select("files.*").
|
Table("files").Select("files.*").
|
||||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.deleted_at IS NULL").
|
Joins("JOIN photos ON photos.id = files.photo_id AND photos.deleted_at IS NULL").
|
||||||
Where("files.file_missing = 0 AND files.file_root = ?", rootName).
|
Where("files.file_missing = FALSE AND files.file_root = ?", rootName).
|
||||||
Where("photos.photo_path = ?", pathName)
|
Where("photos.photo_path = ?", pathName)
|
||||||
|
|
||||||
if public {
|
if public {
|
||||||
stmt = stmt.Where("photos.photo_private = 0")
|
stmt = stmt.Where("photos.photo_private = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = stmt.Order("files.file_name").
|
err = stmt.Order("files.file_name").
|
||||||
@@ -42,7 +42,7 @@ func Files(limit, offset int, pathName string, includeMissing bool) (files entit
|
|||||||
stmt := Db()
|
stmt := Db()
|
||||||
|
|
||||||
if !includeMissing {
|
if !includeMissing {
|
||||||
stmt = stmt.Where("file_missing = 0")
|
stmt = stmt.Where("file_missing = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
if pathName != "" {
|
if pathName != "" {
|
||||||
@@ -56,7 +56,7 @@ func Files(limit, offset int, pathName string, includeMissing bool) (files entit
|
|||||||
|
|
||||||
// FilesByUID finds files for the given UIDs.
|
// FilesByUID finds files for the given UIDs.
|
||||||
func FilesByUID(u []string, limit int, offset int) (files entity.Files, err error) {
|
func FilesByUID(u []string, limit int, offset int) (files entity.Files, err error) {
|
||||||
if err = Db().Where("(photo_uid IN (?) AND file_primary = 1) OR file_uid IN (?)", u, u).Preload("Photo").Limit(limit).Offset(offset).Find(&files).Error; err != nil {
|
if err = Db().Where("(photo_uid IN (?) AND file_primary = TRUE) OR file_uid IN (?)", u, u).Preload("Photo").Limit(limit).Offset(offset).Find(&files).Error; err != nil {
|
||||||
return files, err
|
return files, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ func FileByPhotoUID(photoUID string) (*entity.File, error) {
|
|||||||
return &f, fmt.Errorf("photo uid required")
|
return &f, fmt.Errorf("photo uid required")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := Db().Where("photo_uid = ? AND file_primary = 1", photoUID).Preload("Photo").First(&f).Error
|
err := Db().Where("photo_uid = ? AND file_primary = TRUE", photoUID).Preload("Photo").First(&f).Error
|
||||||
|
|
||||||
return &f, err
|
return &f, err
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ func VideoByPhotoUID(photoUID string) (*entity.File, error) {
|
|||||||
return &f, fmt.Errorf("photo uid required")
|
return &f, fmt.Errorf("photo uid required")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := Db().Where("photo_uid = ? AND file_missing = 0", photoUID).
|
err := Db().Where("photo_uid = ? AND file_missing = FALSE", photoUID).
|
||||||
Where("file_video = 1 OR file_duration > 0 OR file_frames > 0 OR file_type = ?", fs.ImageGIF).
|
Where("file_video = 1 OR file_duration > 0 OR file_frames > 0 OR file_type = ?", fs.ImageGIF).
|
||||||
Order("file_error ASC, file_video DESC, file_duration DESC, file_frames DESC").
|
Order("file_error ASC, file_video DESC, file_duration DESC, file_frames DESC").
|
||||||
Preload("Photo").First(&f).Error
|
Preload("Photo").First(&f).Error
|
||||||
@@ -124,7 +124,7 @@ func RenameFile(srcRoot, srcName, destRoot, destName string) error {
|
|||||||
return fmt.Errorf("cannot rename %s/%s to %s/%s", srcRoot, srcName, destRoot, destName)
|
return fmt.Errorf("cannot rename %s/%s to %s/%s", srcRoot, srcName, destRoot, destName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Db().Exec("UPDATE files SET file_root = ?, file_name = ?, file_missing = 0, deleted_at = NULL WHERE file_root = ? AND file_name = ?", destRoot, destName, srcRoot, srcName).Error
|
return Db().Exec("UPDATE files SET file_root = ?, file_name = ?, file_missing = FALSE, deleted_at = NULL WHERE file_root = ? AND file_name = ?", destRoot, destName, srcRoot, srcName).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPhotoPrimary sets a new primary image file for a photo.
|
// SetPhotoPrimary sets a new primary image file for a photo.
|
||||||
@@ -138,7 +138,7 @@ func SetPhotoPrimary(photoUID, fileUID string) (err error) {
|
|||||||
if fileUID != "" {
|
if fileUID != "" {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
} else if err = Db().Model(entity.File{}).
|
} else if err = Db().Model(entity.File{}).
|
||||||
Where("photo_uid = ? AND file_missing = 0 AND file_type IN (?)", photoUID, media.PreviewExpr).
|
Where("photo_uid = ? AND file_missing = FALSE AND file_type IN (?)", photoUID, media.PreviewExpr).
|
||||||
Order("file_width DESC, file_hdr DESC").Limit(1).Pluck("file_uid", &files).Error; err != nil {
|
Order("file_width DESC, file_hdr DESC").Limit(1).Pluck("file_uid", &files).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
} else if len(files) == 0 {
|
} else if len(files) == 0 {
|
||||||
@@ -199,7 +199,7 @@ func IndexedFiles() (result FileMap, err error) {
|
|||||||
// Query indexed files.
|
// Query indexed files.
|
||||||
var files []File
|
var files []File
|
||||||
|
|
||||||
if err := UnscopedDb().Raw("SELECT file_root, file_name, mod_time FROM files WHERE file_missing = 0 AND deleted_at IS NULL").Scan(&files).Error; err != nil {
|
if err := UnscopedDb().Raw("SELECT file_root, file_name, mod_time FROM files WHERE file_missing = FALSE AND deleted_at IS NULL").Scan(&files).Error; err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@ type HashMap map[string]bool
|
|||||||
func CountFileHashes() (count int64) {
|
func CountFileHashes() (count int64) {
|
||||||
if err := UnscopedDb().
|
if err := UnscopedDb().
|
||||||
Table(entity.File{}.TableName()).
|
Table(entity.File{}.TableName()).
|
||||||
Where("file_missing = 0 AND deleted_at IS NULL").
|
Where("file_missing = FALSE AND deleted_at IS NULL").
|
||||||
Select("COUNT(DISTINCT(file_hash))").Count(&count).Error; err != nil {
|
Select("COUNT(DISTINCT(file_hash))").Count(&count).Error; err != nil {
|
||||||
log.Errorf("files: %s (count hashes)", err)
|
log.Errorf("files: %s (count hashes)", err)
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ func FileHashMap() (result HashMap, err error) {
|
|||||||
|
|
||||||
if rows, err := UnscopedDb().
|
if rows, err := UnscopedDb().
|
||||||
Table(entity.File{}.TableName()).
|
Table(entity.File{}.TableName()).
|
||||||
Where("file_missing = 0 AND deleted_at IS NULL").
|
Where("file_missing = FALSE AND deleted_at IS NULL").
|
||||||
Where("file_hash IS NOT NULL AND file_hash <> ''").
|
Where("file_hash IS NOT NULL AND file_hash <> ''").
|
||||||
Select("file_hash").Rows(); err != nil {
|
Select("file_hash").Rows(); err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
|
@@ -42,8 +42,8 @@ func FoldersByPath(rootName, rootPath, path string, recursive bool) (folders ent
|
|||||||
|
|
||||||
// FolderCoverByUID returns a folder cover file based on the uid.
|
// FolderCoverByUID returns a folder cover file based on the uid.
|
||||||
func FolderCoverByUID(uid string) (file entity.File, err error) {
|
func FolderCoverByUID(uid string) (file entity.File, err error) {
|
||||||
if err = Db().Where("files.file_primary = 1 AND files.file_missing = 0 AND files.file_type IN (?) AND files.deleted_at IS NULL", media.PreviewExpr).
|
if err = Db().Where("files.file_primary = TRUE AND files.file_missing = FALSE AND files.file_type IN (?) AND files.deleted_at IS NULL", media.PreviewExpr).
|
||||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.deleted_at IS NULL AND photos.photo_quality > -1 AND photos.photo_private = 0").
|
Joins("JOIN photos ON photos.id = files.photo_id AND photos.deleted_at IS NULL AND photos.photo_quality > -1 AND photos.photo_private = FALSE").
|
||||||
Joins("JOIN folders ON photos.photo_path = folders.path AND folders.folder_uid = ?", uid).
|
Joins("JOIN folders ON photos.photo_path = folders.path AND folders.folder_uid = ?", uid).
|
||||||
Order("photos.photo_quality DESC").
|
Order("photos.photo_quality DESC").
|
||||||
Limit(1).
|
Limit(1).
|
||||||
@@ -58,7 +58,7 @@ func FolderCoverByUID(uid string) (file entity.File, err error) {
|
|||||||
func AlbumFolders(threshold int) (folders entity.Folders, err error) {
|
func AlbumFolders(threshold int) (folders entity.Folders, err error) {
|
||||||
db := UnscopedDb().Table("folders").
|
db := UnscopedDb().Table("folders").
|
||||||
Select("folders.path, folders.root, folders.folder_uid, folders.folder_title, folders.folder_country, folders.folder_year, folders.folder_month, COUNT(photos.id) AS photo_count").
|
Select("folders.path, folders.root, folders.folder_uid, folders.folder_title, folders.folder_country, folders.folder_year, folders.folder_month, COUNT(photos.id) AS photo_count").
|
||||||
Joins("JOIN photos ON photos.photo_path = folders.path AND photos.deleted_at IS NULL AND photos.photo_quality >= 3 AND photos.photo_private = 0").
|
Joins("JOIN photos ON photos.photo_path = folders.path AND photos.deleted_at IS NULL AND photos.photo_quality >= 3 AND photos.photo_private = FALSE").
|
||||||
Group("folders.path, folders.root, folders.folder_uid, folders.folder_title, folders.folder_country, folders.folder_year, folders.folder_month").
|
Group("folders.path, folders.root, folders.folder_uid, folders.folder_title, folders.folder_country, folders.folder_year, folders.folder_month").
|
||||||
Having("photo_count >= ?", threshold)
|
Having("photo_count >= ?", threshold)
|
||||||
|
|
||||||
|
@@ -37,7 +37,7 @@ func LabelThumbBySlug(labelSlug string) (file entity.File, err error) {
|
|||||||
if err := Db().Where("files.file_primary AND files.file_type IN (?) AND files.deleted_at IS NULL", media.PreviewExpr).
|
if err := Db().Where("files.file_primary AND files.file_type IN (?) AND files.deleted_at IS NULL", media.PreviewExpr).
|
||||||
Joins("JOIN labels ON labels.label_slug = ?", labelSlug).
|
Joins("JOIN labels ON labels.label_slug = ?", labelSlug).
|
||||||
Joins("JOIN photos_labels ON photos_labels.label_id = labels.id AND photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
Joins("JOIN photos_labels ON photos_labels.label_id = labels.id AND photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
||||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = 0 AND photos.deleted_at IS NULL").
|
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = FALSE AND photos.deleted_at IS NULL").
|
||||||
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
||||||
First(&file).Error; err != nil {
|
First(&file).Error; err != nil {
|
||||||
return file, err
|
return file, err
|
||||||
@@ -52,7 +52,7 @@ func LabelThumbByUID(labelUID string) (file entity.File, err error) {
|
|||||||
err = Db().Where("files.file_primary AND files.deleted_at IS NULL").
|
err = Db().Where("files.file_primary AND files.deleted_at IS NULL").
|
||||||
Joins("JOIN labels ON labels.label_uid = ?", labelUID).
|
Joins("JOIN labels ON labels.label_uid = ?", labelUID).
|
||||||
Joins("JOIN photos_labels ON photos_labels.label_id = labels.id AND photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
Joins("JOIN photos_labels ON photos_labels.label_id = labels.id AND photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
||||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = 0 AND photos.deleted_at IS NULL").
|
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = FALSE AND photos.deleted_at IS NULL").
|
||||||
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
||||||
First(&file).Error
|
First(&file).Error
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ func LabelThumbByUID(labelUID string) (file entity.File, err error) {
|
|||||||
Joins("JOIN photos_labels ON photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
Joins("JOIN photos_labels ON photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
||||||
Joins("JOIN categories c ON photos_labels.label_id = c.label_id").
|
Joins("JOIN categories c ON photos_labels.label_id = c.label_id").
|
||||||
Joins("JOIN labels ON c.category_id = labels.id AND labels.label_uid= ?", labelUID).
|
Joins("JOIN labels ON c.category_id = labels.id AND labels.label_uid= ?", labelUID).
|
||||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = 0 AND photos.deleted_at IS NULL").
|
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = FALSE AND photos.deleted_at IS NULL").
|
||||||
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
||||||
First(&file).Error
|
First(&file).Error
|
||||||
|
|
||||||
|
@@ -201,7 +201,7 @@ func MomentsTime(threshold int, public bool) (results Moments, err error) {
|
|||||||
|
|
||||||
// Ignore private pictures?
|
// Ignore private pictures?
|
||||||
if public {
|
if public {
|
||||||
stmt = stmt.Where("photo_private = 0")
|
stmt = stmt.Where("photo_private = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt = stmt.Group("photos.photo_year, photos.photo_month").
|
stmt = stmt.Group("photos.photo_year, photos.photo_month").
|
||||||
@@ -223,7 +223,7 @@ func MomentsCountries(threshold int, public bool) (results Moments, err error) {
|
|||||||
|
|
||||||
// Ignore private pictures?
|
// Ignore private pictures?
|
||||||
if public {
|
if public {
|
||||||
stmt = stmt.Where("photo_private = 0")
|
stmt = stmt.Where("photo_private = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt = stmt.Group("photo_year, photo_country").
|
stmt = stmt.Group("photo_year, photo_country").
|
||||||
@@ -245,7 +245,7 @@ func MomentsStates(threshold int, public bool) (results Moments, err error) {
|
|||||||
|
|
||||||
// Ignore private pictures?
|
// Ignore private pictures?
|
||||||
if public {
|
if public {
|
||||||
stmt = stmt.Where("photo_private = 0")
|
stmt = stmt.Where("photo_private = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt = stmt.Group("p.place_country, p.place_state").
|
stmt = stmt.Group("p.place_country, p.place_state").
|
||||||
@@ -276,7 +276,7 @@ func MomentsLabels(threshold int, public bool) (results Moments, err error) {
|
|||||||
|
|
||||||
// Ignore private pictures?
|
// Ignore private pictures?
|
||||||
if public {
|
if public {
|
||||||
stmt = stmt.Where("photo_private = 0")
|
stmt = stmt.Where("photo_private = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt = stmt.Group("l.label_slug").
|
stmt = stmt.Group("l.label_slug").
|
||||||
@@ -309,16 +309,16 @@ func RemoveDuplicateMoments() (removed int, err error) {
|
|||||||
if res := UnscopedDb().Exec(`DELETE FROM links WHERE share_uid
|
if res := UnscopedDb().Exec(`DELETE FROM links WHERE share_uid
|
||||||
IN (SELECT a.album_uid FROM albums a JOIN albums b ON a.album_type <> ?
|
IN (SELECT a.album_uid FROM albums a JOIN albums b ON a.album_type <> ?
|
||||||
AND a.album_type = b.album_type AND a.id > b.id
|
AND a.album_type = b.album_type AND a.id > b.id
|
||||||
WHERE (a.album_slug = b.album_slug OR a.album_filter = b.album_filter)
|
WHERE (a.album_slug = b.album_slug OR a.album_filter = b.album_filter))`,
|
||||||
GROUP BY a.album_uid)`, entity.AlbumManual); res.Error != nil {
|
entity.AlbumManual); res.Error != nil {
|
||||||
return removed, res.Error
|
return removed, res.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
if res := UnscopedDb().Exec(`DELETE FROM albums WHERE id
|
if res := UnscopedDb().Exec(`DELETE FROM albums WHERE id
|
||||||
IN (SELECT a.id FROM albums a JOIN albums b ON a.album_type <> ?
|
IN (SELECT a.id FROM albums a JOIN albums b ON a.album_type <> ?
|
||||||
AND a.album_type = b.album_type AND a.id > b.id
|
AND a.album_type = b.album_type AND a.id > b.id
|
||||||
WHERE (a.album_slug = b.album_slug OR a.album_filter = b.album_filter)
|
WHERE (a.album_slug = b.album_slug OR a.album_filter = b.album_filter))`,
|
||||||
GROUP BY a.album_uid)`, entity.AlbumManual); res.Error != nil {
|
entity.AlbumManual); res.Error != nil {
|
||||||
return removed, res.Error
|
return removed, res.Error
|
||||||
} else if res.RowsAffected > 0 {
|
} else if res.RowsAffected > 0 {
|
||||||
removed = int(res.RowsAffected)
|
removed = int(res.RowsAffected)
|
||||||
|
@@ -77,7 +77,7 @@ func PhotoPreloadByUID(photoUID string) (photo entity.Photo, err error) {
|
|||||||
func MissingPhotos(limit int, offset int) (entities entity.Photos, err error) {
|
func MissingPhotos(limit int, offset int) (entities entity.Photos, err error) {
|
||||||
err = Db().
|
err = Db().
|
||||||
Select("photos.*").
|
Select("photos.*").
|
||||||
Where("id NOT IN (SELECT photo_id FROM files WHERE file_missing = 0 AND file_root = '/' AND deleted_at IS NULL)").
|
Where("id NOT IN (SELECT photo_id FROM files WHERE file_missing = FALSE AND file_root = '/' AND deleted_at IS NULL)").
|
||||||
Order("photos.id").
|
Order("photos.id").
|
||||||
Limit(limit).Offset(offset).Find(&entities).Error
|
Limit(limit).Offset(offset).Find(&entities).Error
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ func FixPrimaries() error {
|
|||||||
|
|
||||||
// Remove primary file flag from broken or missing files.
|
// Remove primary file flag from broken or missing files.
|
||||||
if err := UnscopedDb().Table(entity.File{}.TableName()).
|
if err := UnscopedDb().Table(entity.File{}.TableName()).
|
||||||
Where("(file_error <> '' OR file_missing = 1) AND file_primary <> 0").
|
Where("(file_error <> '' OR file_missing = TRUE) AND file_primary <> 0").
|
||||||
UpdateColumn("file_primary", 0).Error; err != nil {
|
UpdateColumn("file_primary", 0).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ func FixPrimaries() error {
|
|||||||
if err := UnscopedDb().
|
if err := UnscopedDb().
|
||||||
Raw(`SELECT * FROM photos
|
Raw(`SELECT * FROM photos
|
||||||
WHERE deleted_at IS NULL
|
WHERE deleted_at IS NULL
|
||||||
AND id NOT IN (SELECT photo_id FROM files WHERE file_primary = 1)`).
|
AND id NOT IN (SELECT photo_id FROM files WHERE file_primary = TRUE)`).
|
||||||
Find(&photos).Error; err != nil {
|
Find(&photos).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -188,7 +188,7 @@ func FlagHiddenPhotos() (err error) {
|
|||||||
|
|
||||||
// Find and flag hidden photos.
|
// Find and flag hidden photos.
|
||||||
if err = Db().Table(entity.Photo{}.TableName()).
|
if err = Db().Table(entity.Photo{}.TableName()).
|
||||||
Where("id NOT IN (SELECT photo_id FROM files WHERE file_primary = 1 AND file_missing = 0 AND file_error = '' AND deleted_at IS NULL) AND photo_quality > -1").
|
Where("id NOT IN (SELECT photo_id FROM files WHERE file_primary = TRUE AND file_missing = FALSE AND file_error = '' AND deleted_at IS NULL) AND photo_quality > -1").
|
||||||
Pluck("id", &hidden).Error; err != nil {
|
Pluck("id", &hidden).Error; err != nil {
|
||||||
// Find query failed.
|
// Find query failed.
|
||||||
return err
|
return err
|
||||||
|
@@ -38,7 +38,7 @@ func SelectedPhotos(f form.Selection) (results entity.Photos, err error) {
|
|||||||
OR photos.photo_path IN (
|
OR photos.photo_path IN (
|
||||||
SELECT a.path FROM folders a WHERE a.folder_uid IN (?) UNION
|
SELECT a.path FROM folders a WHERE a.folder_uid IN (?) UNION
|
||||||
SELECT b.path FROM folders a JOIN folders b ON b.path LIKE %s WHERE a.folder_uid IN (?))
|
SELECT b.path FROM folders a JOIN folders b ON b.path LIKE %s WHERE a.folder_uid IN (?))
|
||||||
OR photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = 0 AND album_uid IN (?))
|
OR photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = FALSE AND album_uid IN (?))
|
||||||
OR photos.id IN (SELECT f.photo_id FROM files f JOIN %s m ON f.file_uid = m.file_uid WHERE f.deleted_at IS NULL AND m.subj_uid IN (?))
|
OR photos.id IN (SELECT f.photo_id FROM files f JOIN %s m ON f.file_uid = m.file_uid WHERE f.deleted_at IS NULL AND m.subj_uid IN (?))
|
||||||
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN labels l ON pl.label_id = l.id AND pl.uncertainty < 100 AND l.deleted_at IS NULL WHERE l.label_uid IN (?))
|
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN labels l ON pl.label_id = l.id AND pl.uncertainty < 100 AND l.deleted_at IS NULL WHERE l.label_uid IN (?))
|
||||||
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN categories c ON c.label_id = pl.label_id AND pl.uncertainty < 100 JOIN labels lc ON lc.id = c.category_id AND lc.deleted_at IS NULL WHERE lc.label_uid IN (?))`,
|
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN categories c ON c.label_id = pl.label_id AND pl.uncertainty < 100 JOIN labels lc ON lc.id = c.category_id AND lc.deleted_at IS NULL WHERE lc.label_uid IN (?))`,
|
||||||
|
@@ -71,7 +71,7 @@ func PurgeOrphanDuplicates() error {
|
|||||||
|
|
||||||
result := UnscopedDb().
|
result := UnscopedDb().
|
||||||
Delete(entity.Duplicate{},
|
Delete(entity.Duplicate{},
|
||||||
"file_hash NOT IN (SELECT file_hash FROM files WHERE file_missing = 0 AND deleted_at IS NULL)")
|
"file_hash NOT IN (SELECT file_hash FROM files WHERE file_missing = FALSE AND deleted_at IS NULL)")
|
||||||
|
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@ func PeopleCount() (count int, err error) {
|
|||||||
err = Db().
|
err = Db().
|
||||||
Table(entity.Subject{}.TableName()).
|
Table(entity.Subject{}.TableName()).
|
||||||
Where("deleted_at IS NULL").
|
Where("deleted_at IS NULL").
|
||||||
Where("subj_hidden = 0").
|
Where("subj_hidden = FALSE").
|
||||||
Where("subj_type = ?", entity.SubjPerson).
|
Where("subj_type = ?", entity.SubjPerson).
|
||||||
Count(&cnt).Error
|
Count(&cnt).Error
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ func UserAlbums(f form.SearchAlbums, sess *entity.Session) (results AlbumResults
|
|||||||
// Base query.
|
// Base query.
|
||||||
s := UnscopedDb().Table("albums").
|
s := UnscopedDb().Table("albums").
|
||||||
Select("albums.*, cp.photo_count, cl.link_count, CASE WHEN albums.album_year = 0 THEN 0 ELSE 1 END AS has_year, CASE WHEN albums.album_location = '' THEN 1 ELSE 0 END AS no_location").
|
Select("albums.*, cp.photo_count, cl.link_count, CASE WHEN albums.album_year = 0 THEN 0 ELSE 1 END AS has_year, CASE WHEN albums.album_location = '' THEN 1 ELSE 0 END AS no_location").
|
||||||
Joins("LEFT JOIN (SELECT album_uid, count(photo_uid) AS photo_count FROM photos_albums WHERE hidden = 0 AND missing = 0 GROUP BY album_uid) AS cp ON cp.album_uid = albums.album_uid").
|
Joins("LEFT JOIN (SELECT album_uid, count(photo_uid) AS photo_count FROM photos_albums WHERE hidden = FALSE AND missing = FALSE GROUP BY album_uid) AS cp ON cp.album_uid = albums.album_uid").
|
||||||
Joins("LEFT JOIN (SELECT share_uid, count(share_uid) AS link_count FROM links GROUP BY share_uid) AS cl ON cl.share_uid = albums.album_uid").
|
Joins("LEFT JOIN (SELECT share_uid, count(share_uid) AS link_count FROM links GROUP BY share_uid) AS cl ON cl.share_uid = albums.album_uid").
|
||||||
Where("albums.deleted_at IS NULL")
|
Where("albums.deleted_at IS NULL")
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ func UserAlbums(f form.SearchAlbums, sess *entity.Session) (results AlbumResults
|
|||||||
|
|
||||||
// Albums with public pictures only?
|
// Albums with public pictures only?
|
||||||
if f.Public {
|
if f.Public {
|
||||||
s = s.Where("albums.album_private = 0 AND (albums.album_type <> 'folder' OR albums.album_path IN (SELECT photo_path FROM photos WHERE photo_private = 0 AND photo_quality > -1 AND deleted_at IS NULL))")
|
s = s.Where("albums.album_private = FALSE AND (albums.album_type <> 'folder' OR albums.album_path IN (SELECT photo_path FROM photos WHERE photo_private = FALSE AND photo_quality > -1 AND deleted_at IS NULL))")
|
||||||
} else {
|
} else {
|
||||||
s = s.Where("albums.album_type <> 'folder' OR albums.album_path IN (SELECT photo_path FROM photos WHERE photo_quality > -1 AND deleted_at IS NULL)")
|
s = s.Where("albums.album_type <> 'folder' OR albums.album_path IN (SELECT photo_path FROM photos WHERE photo_quality > -1 AND deleted_at IS NULL)")
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ func UserAlbums(f form.SearchAlbums, sess *entity.Session) (results AlbumResults
|
|||||||
|
|
||||||
// Favorites only?
|
// Favorites only?
|
||||||
if f.Favorite {
|
if f.Favorite {
|
||||||
s = s.Where("albums.album_favorite = 1")
|
s = s.Where("albums.album_favorite = TRUE")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by year?
|
// Filter by year?
|
||||||
@@ -185,7 +185,7 @@ func UserAlbums(f form.SearchAlbums, sess *entity.Session) (results AlbumResults
|
|||||||
// year assigned to them, unlike calendar albums and moments for example.
|
// year assigned to them, unlike calendar albums and moments for example.
|
||||||
if f.Type == entity.AlbumManual {
|
if f.Type == entity.AlbumManual {
|
||||||
s = s.Where("? OR albums.album_uid IN (SELECT DISTINCT pay.album_uid FROM photos_albums pay "+
|
s = s.Where("? OR albums.album_uid IN (SELECT DISTINCT pay.album_uid FROM photos_albums pay "+
|
||||||
"JOIN photos py ON pay.photo_uid = py.photo_uid WHERE py.photo_year IN (?) AND pay.hidden = 0 AND pay.missing = 0)",
|
"JOIN photos py ON pay.photo_uid = py.photo_uid WHERE py.photo_year IN (?) AND pay.hidden = FALSE AND pay.missing = FALSE)",
|
||||||
gorm.Expr(AnyInt("albums.album_year", f.Year, txt.Or, entity.UnknownYear, txt.YearMax)), strings.Split(f.Year, txt.Or))
|
gorm.Expr(AnyInt("albums.album_year", f.Year, txt.Or, entity.UnknownYear, txt.YearMax)), strings.Split(f.Year, txt.Or))
|
||||||
} else {
|
} else {
|
||||||
s = s.Where(AnyInt("albums.album_year", f.Year, txt.Or, entity.UnknownYear, txt.YearMax))
|
s = s.Where(AnyInt("albums.album_year", f.Year, txt.Or, entity.UnknownYear, txt.YearMax))
|
||||||
|
@@ -91,7 +91,7 @@ func Faces(f form.SearchFaces) (results FaceResults, err error) {
|
|||||||
|
|
||||||
// Show hidden faces?
|
// Show hidden faces?
|
||||||
if !txt.Yes(f.Hidden) {
|
if !txt.Yes(f.Hidden) {
|
||||||
s = s.Where(fmt.Sprintf("%s.face_hidden = 0", facesTable))
|
s = s.Where(fmt.Sprintf("%s.face_hidden = FALSE", facesTable))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform query.
|
// Perform query.
|
||||||
|
@@ -78,11 +78,11 @@ func Labels(f form.SearchLabels) (results []Label, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if f.Favorite {
|
if f.Favorite {
|
||||||
s = s.Where("labels.label_favorite = 1")
|
s = s.Where("labels.label_favorite = TRUE")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !f.All {
|
if !f.All {
|
||||||
s = s.Where("labels.label_priority >= 0 OR labels.label_favorite = 1")
|
s = s.Where("labels.label_priority >= 0 OR labels.label_favorite = TRUE")
|
||||||
}
|
}
|
||||||
|
|
||||||
if result := s.Scan(&results); result.Error != nil {
|
if result := s.Scan(&results); result.Error != nil {
|
||||||
|
@@ -105,13 +105,13 @@ func searchPhotos(f form.SearchPhotos, sess *entity.Session, resultCols string)
|
|||||||
return PhotoResults{}, 0, ErrInvalidId
|
return PhotoResults{}, 0, ErrInvalidId
|
||||||
} else if a.AlbumFilter == "" {
|
} else if a.AlbumFilter == "" {
|
||||||
s = s.Joins("JOIN photos_albums ON photos_albums.photo_uid = files.photo_uid").
|
s = s.Joins("JOIN photos_albums ON photos_albums.photo_uid = files.photo_uid").
|
||||||
Where("photos_albums.hidden = 0 AND photos_albums.album_uid = ?", a.AlbumUID)
|
Where("photos_albums.hidden = FALSE AND photos_albums.album_uid = ?", a.AlbumUID)
|
||||||
} else if formErr := form.Unserialize(&f, a.AlbumFilter); formErr != nil {
|
} else if formErr := form.Unserialize(&f, a.AlbumFilter); formErr != nil {
|
||||||
log.Debugf("search: %s (%s)", clean.Error(formErr), clean.Log(a.AlbumFilter))
|
log.Debugf("search: %s (%s)", clean.Error(formErr), clean.Log(a.AlbumFilter))
|
||||||
return PhotoResults{}, 0, ErrBadFilter
|
return PhotoResults{}, 0, ErrBadFilter
|
||||||
} else {
|
} else {
|
||||||
f.Filter = a.AlbumFilter
|
f.Filter = a.AlbumFilter
|
||||||
s = s.Where("files.photo_uid NOT IN (SELECT photo_uid FROM photos_albums pa WHERE pa.hidden = 1 AND pa.album_uid = ?)", a.AlbumUID)
|
s = s.Where("files.photo_uid NOT IN (SELECT photo_uid FROM photos_albums pa WHERE pa.hidden = TRUE AND pa.album_uid = ?)", a.AlbumUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce search distance range (km).
|
// Enforce search distance range (km).
|
||||||
@@ -155,7 +155,7 @@ func searchPhotos(f form.SearchPhotos, sess *entity.Session, resultCols string)
|
|||||||
|
|
||||||
// Limit results for external users.
|
// Limit results for external users.
|
||||||
if f.Scope == "" && acl.Rules.DenyAll(acl.ResourcePhotos, aclRole, acl.Permissions{acl.AccessAll, acl.AccessLibrary}) {
|
if f.Scope == "" && acl.Rules.DenyAll(acl.ResourcePhotos, aclRole, acl.Permissions{acl.AccessAll, acl.AccessLibrary}) {
|
||||||
sharedAlbums := "photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = 0 AND missing = 0 AND album_uid IN (?)) OR "
|
sharedAlbums := "photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = FALSE AND missing = FALSE AND album_uid IN (?)) OR "
|
||||||
|
|
||||||
if sess.IsVisitor() || sess.NotRegistered() {
|
if sess.IsVisitor() || sess.NotRegistered() {
|
||||||
s = s.Where(sharedAlbums+"photos.published_at > ?", sess.SharedUIDs(), entity.TimeStamp())
|
s = s.Where(sharedAlbums+"photos.published_at > ?", sess.SharedUIDs(), entity.TimeStamp())
|
||||||
@@ -210,14 +210,14 @@ func searchPhotos(f form.SearchPhotos, sess *entity.Session, resultCols string)
|
|||||||
|
|
||||||
// Find primary files only?
|
// Find primary files only?
|
||||||
if f.Primary {
|
if f.Primary {
|
||||||
s = s.Where("files.file_primary = 1")
|
s = s.Where("files.file_primary = TRUE")
|
||||||
} else if f.Order == sortby.Similar {
|
} else if f.Order == sortby.Similar {
|
||||||
s = s.Where("files.file_primary = 1 OR files.media_type = ?", media.Video)
|
s = s.Where("files.file_primary = TRUE OR files.media_type = ?", media.Video)
|
||||||
} else if f.Order == sortby.Random {
|
} else if f.Order == sortby.Random {
|
||||||
s = s.Where("files.file_primary = 1 AND photos.photo_type NOT IN ('live','video') OR photos.photo_type IN ('live','video') AND files.media_type IN ('live','video')")
|
s = s.Where("files.file_primary = TRUE AND photos.photo_type NOT IN ('live','video') OR photos.photo_type IN ('live','video') AND files.media_type IN ('live','video')")
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, find all matching media except sidecar files.
|
// Otherwise, find all matching media except sidecar files.
|
||||||
s = s.Where("files.file_sidecar = 0")
|
s = s.Where("files.file_sidecar = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find specific UIDs only.
|
// Find specific UIDs only.
|
||||||
@@ -467,9 +467,9 @@ func searchPhotos(f form.SearchPhotos, sess *entity.Session, resultCols string)
|
|||||||
s = s.Where("photos.deleted_at IS NULL")
|
s = s.Where("photos.deleted_at IS NULL")
|
||||||
|
|
||||||
if f.Private {
|
if f.Private {
|
||||||
s = s.Where("photos.photo_private = 1")
|
s = s.Where("photos.photo_private = TRUE")
|
||||||
} else if f.Public {
|
} else if f.Public {
|
||||||
s = s.Where("photos.photo_private = 0")
|
s = s.Where("photos.photo_private = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Review {
|
if f.Review {
|
||||||
@@ -564,9 +564,9 @@ func searchPhotos(f form.SearchPhotos, sess *entity.Session, resultCols string)
|
|||||||
|
|
||||||
// Filter by favorite flag.
|
// Filter by favorite flag.
|
||||||
if txt.No(f.Favorite) {
|
if txt.No(f.Favorite) {
|
||||||
s = s.Where("photos.photo_favorite = 0")
|
s = s.Where("photos.photo_favorite = FALSE")
|
||||||
} else if txt.NotEmpty(f.Favorite) {
|
} else if txt.NotEmpty(f.Favorite) {
|
||||||
s = s.Where("photos.photo_favorite = 1")
|
s = s.Where("photos.photo_favorite = TRUE")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by scan flag.
|
// Filter by scan flag.
|
||||||
@@ -722,13 +722,13 @@ func searchPhotos(f form.SearchPhotos, sess *entity.Session, resultCols string)
|
|||||||
// Find photos in albums or not in an album, unless search results are limited to a scope.
|
// Find photos in albums or not in an album, unless search results are limited to a scope.
|
||||||
if f.Scope == "" {
|
if f.Scope == "" {
|
||||||
if f.Unsorted {
|
if f.Unsorted {
|
||||||
s = s.Where("photos.photo_uid NOT IN (SELECT photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid WHERE pa.hidden = 0 AND a.deleted_at IS NULL)")
|
s = s.Where("photos.photo_uid NOT IN (SELECT photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid WHERE pa.hidden = FALSE AND a.deleted_at IS NULL)")
|
||||||
} else if txt.NotEmpty(f.Album) {
|
} else if txt.NotEmpty(f.Album) {
|
||||||
v := strings.Trim(f.Album, "*%") + "%"
|
v := strings.Trim(f.Album, "*%") + "%"
|
||||||
s = s.Where("photos.photo_uid IN (SELECT pa.photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid AND pa.hidden = 0 WHERE (a.album_title LIKE ? OR a.album_slug LIKE ?))", v, v)
|
s = s.Where("photos.photo_uid IN (SELECT pa.photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid AND pa.hidden = FALSE WHERE (a.album_title LIKE ? OR a.album_slug LIKE ?))", v, v)
|
||||||
} else if txt.NotEmpty(f.Albums) {
|
} else if txt.NotEmpty(f.Albums) {
|
||||||
for _, where := range LikeAnyWord("a.album_title", f.Albums) {
|
for _, where := range LikeAnyWord("a.album_title", f.Albums) {
|
||||||
s = s.Where("photos.photo_uid IN (SELECT pa.photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid AND pa.hidden = 0 WHERE (?))", gorm.Expr(where))
|
s = s.Where("photos.photo_uid IN (SELECT pa.photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid AND pa.hidden = FALSE WHERE (?))", gorm.Expr(where))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -69,7 +69,7 @@ func UserPhotosGeo(f form.SearchPhotosGeo, sess *entity.Session) (results GeoRes
|
|||||||
|
|
||||||
// Specify table names and joins.
|
// Specify table names and joins.
|
||||||
s := UnscopedDb().Table(entity.Photo{}.TableName()).Select(GeoCols).
|
s := UnscopedDb().Table(entity.Photo{}.TableName()).Select(GeoCols).
|
||||||
Joins(`JOIN files ON files.photo_id = photos.id AND files.file_primary = 1 AND files.media_id IS NOT NULL`).
|
Joins(`JOIN files ON files.photo_id = photos.id AND files.file_primary = TRUE AND files.media_id IS NOT NULL`).
|
||||||
Joins("LEFT JOIN places ON photos.place_id = places.id").
|
Joins("LEFT JOIN places ON photos.place_id = places.id").
|
||||||
Where("photos.deleted_at IS NULL").
|
Where("photos.deleted_at IS NULL").
|
||||||
Where("photos.photo_lat <> 0")
|
Where("photos.photo_lat <> 0")
|
||||||
@@ -93,13 +93,13 @@ func UserPhotosGeo(f form.SearchPhotosGeo, sess *entity.Session) (results GeoRes
|
|||||||
return GeoResults{}, ErrInvalidId
|
return GeoResults{}, ErrInvalidId
|
||||||
} else if a.AlbumFilter == "" {
|
} else if a.AlbumFilter == "" {
|
||||||
s = s.Joins("JOIN photos_albums ON photos_albums.photo_uid = files.photo_uid").
|
s = s.Joins("JOIN photos_albums ON photos_albums.photo_uid = files.photo_uid").
|
||||||
Where("photos_albums.hidden = 0 AND photos_albums.album_uid = ?", a.AlbumUID)
|
Where("photos_albums.hidden = FALSE AND photos_albums.album_uid = ?", a.AlbumUID)
|
||||||
} else if formErr := form.Unserialize(&f, a.AlbumFilter); formErr != nil {
|
} else if formErr := form.Unserialize(&f, a.AlbumFilter); formErr != nil {
|
||||||
log.Debugf("search: %s (%s)", clean.Error(formErr), clean.Log(a.AlbumFilter))
|
log.Debugf("search: %s (%s)", clean.Error(formErr), clean.Log(a.AlbumFilter))
|
||||||
return GeoResults{}, ErrBadFilter
|
return GeoResults{}, ErrBadFilter
|
||||||
} else {
|
} else {
|
||||||
f.Filter = a.AlbumFilter
|
f.Filter = a.AlbumFilter
|
||||||
s = s.Where("files.photo_uid NOT IN (SELECT photo_uid FROM photos_albums pa WHERE pa.hidden = 1 AND pa.album_uid = ?)", a.AlbumUID)
|
s = s.Where("files.photo_uid NOT IN (SELECT photo_uid FROM photos_albums pa WHERE pa.hidden = TRUE AND pa.album_uid = ?)", a.AlbumUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce search distance range (km).
|
// Enforce search distance range (km).
|
||||||
@@ -138,7 +138,7 @@ func UserPhotosGeo(f form.SearchPhotosGeo, sess *entity.Session) (results GeoRes
|
|||||||
|
|
||||||
// Limit results for external users.
|
// Limit results for external users.
|
||||||
if f.Scope == "" && acl.Rules.DenyAll(acl.ResourcePlaces, aclRole, acl.Permissions{acl.AccessAll, acl.AccessLibrary}) {
|
if f.Scope == "" && acl.Rules.DenyAll(acl.ResourcePlaces, aclRole, acl.Permissions{acl.AccessAll, acl.AccessLibrary}) {
|
||||||
sharedAlbums := "photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = 0 AND missing = 0 AND album_uid IN (?)) OR "
|
sharedAlbums := "photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = FALSE AND missing = FALSE AND album_uid IN (?)) OR "
|
||||||
|
|
||||||
if sess.IsVisitor() || sess.NotRegistered() {
|
if sess.IsVisitor() || sess.NotRegistered() {
|
||||||
s = s.Where(sharedAlbums+"photos.published_at > ?", sess.SharedUIDs(), entity.TimeStamp())
|
s = s.Where(sharedAlbums+"photos.published_at > ?", sess.SharedUIDs(), entity.TimeStamp())
|
||||||
@@ -387,13 +387,13 @@ func UserPhotosGeo(f form.SearchPhotosGeo, sess *entity.Session) (results GeoRes
|
|||||||
// Find photos in albums or not in an album, unless search results are limited to a scope.
|
// Find photos in albums or not in an album, unless search results are limited to a scope.
|
||||||
if f.Scope == "" {
|
if f.Scope == "" {
|
||||||
if f.Unsorted {
|
if f.Unsorted {
|
||||||
s = s.Where("photos.photo_uid NOT IN (SELECT photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid WHERE pa.hidden = 0 AND a.deleted_at IS NULL)")
|
s = s.Where("photos.photo_uid NOT IN (SELECT photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid WHERE pa.hidden = FALSE AND a.deleted_at IS NULL)")
|
||||||
} else if txt.NotEmpty(f.Album) {
|
} else if txt.NotEmpty(f.Album) {
|
||||||
v := strings.Trim(f.Album, "*%") + "%"
|
v := strings.Trim(f.Album, "*%") + "%"
|
||||||
s = s.Where("photos.photo_uid IN (SELECT pa.photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid AND pa.hidden = 0 WHERE (a.album_title LIKE ? OR a.album_slug LIKE ?))", v, v)
|
s = s.Where("photos.photo_uid IN (SELECT pa.photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid AND pa.hidden = FALSE WHERE (a.album_title LIKE ? OR a.album_slug LIKE ?))", v, v)
|
||||||
} else if txt.NotEmpty(f.Albums) {
|
} else if txt.NotEmpty(f.Albums) {
|
||||||
for _, where := range LikeAnyWord("a.album_title", f.Albums) {
|
for _, where := range LikeAnyWord("a.album_title", f.Albums) {
|
||||||
s = s.Where("photos.photo_uid IN (SELECT pa.photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid AND pa.hidden = 0 WHERE (?))", gorm.Expr(where))
|
s = s.Where("photos.photo_uid IN (SELECT pa.photo_uid FROM photos_albums pa JOIN albums a ON a.album_uid = pa.album_uid AND pa.hidden = FALSE WHERE (?))", gorm.Expr(where))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -473,9 +473,9 @@ func UserPhotosGeo(f form.SearchPhotosGeo, sess *entity.Session) (results GeoRes
|
|||||||
|
|
||||||
// Filter by favorite flag.
|
// Filter by favorite flag.
|
||||||
if txt.No(f.Favorite) {
|
if txt.No(f.Favorite) {
|
||||||
s = s.Where("photos.photo_favorite = 0")
|
s = s.Where("photos.photo_favorite = FALSE")
|
||||||
} else if txt.NotEmpty(f.Favorite) {
|
} else if txt.NotEmpty(f.Favorite) {
|
||||||
s = s.Where("photos.photo_favorite = 1")
|
s = s.Where("photos.photo_favorite = TRUE")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by scan flag.
|
// Filter by scan flag.
|
||||||
@@ -565,9 +565,9 @@ func UserPhotosGeo(f form.SearchPhotosGeo, sess *entity.Session) (results GeoRes
|
|||||||
s = s.Where("photos.deleted_at IS NULL")
|
s = s.Where("photos.deleted_at IS NULL")
|
||||||
|
|
||||||
if f.Private {
|
if f.Private {
|
||||||
s = s.Where("photos.photo_private = 1")
|
s = s.Where("photos.photo_private = TRUE")
|
||||||
} else if f.Public {
|
} else if f.Public {
|
||||||
s = s.Where("photos.photo_private = 0")
|
s = s.Where("photos.photo_private = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Review {
|
if f.Review {
|
||||||
|
@@ -82,7 +82,7 @@ func Subjects(f form.SearchSubjects) (results SubjectResults, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !txt.Yes(f.Hidden) {
|
if !txt.Yes(f.Hidden) {
|
||||||
s = s.Where("subj_hidden = 0")
|
s = s.Where("subj_hidden = FALSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
if txt.Yes(f.Private) {
|
if txt.Yes(f.Private) {
|
||||||
|
Reference in New Issue
Block a user