From be83849beedad193323414dd63919129fd29c1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20Mar=C3=B3y?= Date: Sun, 31 Jan 2021 17:06:25 +0100 Subject: [PATCH] Implement postgres support --- api/database/database.go | 23 +++++++++++++++++++++++ api/database/drivers/database_drivers.go | 7 +++++-- api/example.env | 4 ++++ api/go.mod | 1 + api/graphql/resolvers/album.go | 7 +++---- api/graphql/resolvers/media.go | 2 +- api/utils/environment_variables.go | 1 + 7 files changed, 38 insertions(+), 7 deletions(-) diff --git a/api/database/database.go b/api/database/database.go index 34b50a8b..50d90958 100644 --- a/api/database/database.go +++ b/api/database/database.go @@ -13,6 +13,7 @@ import ( "github.com/pkg/errors" "gorm.io/driver/mysql" + "gorm.io/driver/postgres" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -37,6 +38,20 @@ func getMysqlAddress() (*url.URL, error) { return address, nil } +func getPostgresAddress() (*url.URL, error) { + addressString := utils.EnvPostgresURL.GetValue() + if addressString == "" { + return nil, errors.New(fmt.Sprintf("Environment variable %s missing, exiting", utils.EnvPostgresURL.GetName())) + } + + address, err := url.Parse(addressString) + if err != nil { + return nil, errors.Wrap(err, "Could not parse postgres url") + } + + return address, nil +} + func getSqliteAddress() (*url.URL, error) { path := utils.EnvSqlitePath.GetValue() if path == "" { @@ -77,6 +92,14 @@ func configureDatabase(config *gorm.Config) (*gorm.DB, error) { } log.Printf("Opening SQLITE database: %s", sqliteAddress) databaseDialect = sqlite.Open(sqliteAddress.String()) + + case drivers.DatabaseDriverPostgres: + postgresAddress, err := getPostgresAddress() + if err != nil { + return nil, err + } + log.Printf("Connecting to POSTGRES database: %s", postgresAddress) + databaseDialect = postgres.Open(postgresAddress.String()) } db, err := gorm.Open(databaseDialect, config) diff --git a/api/database/drivers/database_drivers.go b/api/database/drivers/database_drivers.go index eab45ef2..f4305229 100644 --- a/api/database/drivers/database_drivers.go +++ b/api/database/drivers/database_drivers.go @@ -10,8 +10,9 @@ import ( type DatabaseDriverType string const ( - DatabaseDriverMysql DatabaseDriverType = "mysql" - DatabaseDriverSqlite DatabaseDriverType = "sqlite" + DatabaseDriverMysql DatabaseDriverType = "mysql" + DatabaseDriverSqlite DatabaseDriverType = "sqlite" + DatabaseDriverPostgres DatabaseDriverType = "postgres" ) func DatabaseDriver() DatabaseDriverType { @@ -24,6 +25,8 @@ func DatabaseDriver() DatabaseDriverType { driver = DatabaseDriverMysql case "sqlite": driver = DatabaseDriverSqlite + case "postgres": + driver = DatabaseDriverPostgres default: driver = DatabaseDriverMysql } diff --git a/api/example.env b/api/example.env index 27227f74..88ad929b 100644 --- a/api/example.env +++ b/api/example.env @@ -3,6 +3,10 @@ PHOTOVIEW_DATABASE_DRIVER=mysql PHOTOVIEW_MYSQL_URL=user:password@tcp(localhost)/dbname +# Specifies the connection string for the postgres database, if PHOTOVIEW_DATABASE_DRIVER is set to 'postgres' +# See https://www.postgresql.org/docs/current/libpq-ssl.html for possible ssl modes +# PHOTOVIEW_POSTGRES_URL=postgres://user:password@host:port/dbname?sslmode=(disable|allow|...) + # Specifies the filepath for the sqlite database, if PHOTOVIEW_DATABASE_DRIVER is set to 'sqlite' # PHOTOVIEW_SQLITE_PATH=photoview.db diff --git a/api/go.mod b/api/go.mod index d3646aad..598e1f0c 100644 --- a/api/go.mod +++ b/api/go.mod @@ -22,6 +22,7 @@ require ( gopkg.in/vansante/go-ffprobe.v2 v2.0.2 gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/driver/mysql v1.0.3 + gorm.io/driver/postgres v1.0.7 gorm.io/driver/sqlite v1.1.4 gorm.io/gorm v1.20.11 ) diff --git a/api/graphql/resolvers/album.go b/api/graphql/resolvers/album.go index 826d6748..92064925 100644 --- a/api/graphql/resolvers/album.go +++ b/api/graphql/resolvers/album.go @@ -42,7 +42,7 @@ func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter, onl favoritesSubquery := r.Database. Model(&models.UserMediaData{UserID: user.ID}). Where("user_media_data.media_id = media.id"). - Where("user_media_data.favorite = 1") + Where("user_media_data.favorite = true") subQuery = subQuery.Where("EXISTS (?)", favoritesSubquery) } @@ -95,8 +95,7 @@ type albumResolver struct{ *Resolver } func (r *albumResolver) Media(ctx context.Context, album *models.Album, filter *models.Filter, onlyFavorites *bool) ([]*models.Media, error) { query := r.Database. - Joins("Album"). - Where("Album.id = ?", album.ID). + Where("media.album_id = ?", album.ID). Where("media.id IN (?)", r.Database.Model(&models.MediaURL{}).Select("media_urls.media_id").Where("media_urls.media_id = media.id")) if onlyFavorites != nil && *onlyFavorites == true { @@ -107,7 +106,7 @@ func (r *albumResolver) Media(ctx context.Context, album *models.Album, filter * favoriteQuery := r.Database.Model(&models.UserMediaData{ UserID: user.ID, - }).Where("user_media_data.media_id = media.id").Where("user_media_data.favorite = 1") + }).Where("user_media_data.media_id = media.id").Where("user_media_data.favorite = true") query = query.Where("EXISTS (?)", favoriteQuery) } diff --git a/api/graphql/resolvers/media.go b/api/graphql/resolvers/media.go index c6bb69c7..23792682 100644 --- a/api/graphql/resolvers/media.go +++ b/api/graphql/resolvers/media.go @@ -54,7 +54,7 @@ func (r *queryResolver) Media(ctx context.Context, id int) (*models.Media, error err := r.Database. Joins("Album"). Where("media.id = ?", id). - Where("EXISTS (SELECT * FROM user_albums WHERE user_albums.album_id = Album.id AND user_albums.user_id = ?)", user.ID). + Where("EXISTS (SELECT * FROM user_albums WHERE user_albums.album_id = media.album_id AND user_albums.user_id = ?)", user.ID). Where("media.id IN (?)", r.Database.Model(&models.MediaURL{}).Select("media_id").Where("media_urls.media_id = media.id")). First(&media).Error diff --git a/api/utils/environment_variables.go b/api/utils/environment_variables.go index 15f5a2e6..fa88c8b4 100644 --- a/api/utils/environment_variables.go +++ b/api/utils/environment_variables.go @@ -25,6 +25,7 @@ const ( const ( EnvDatabaseDriver EnvironmentVariable = "PHOTOVIEW_DATABASE_DRIVER" EnvMysqlURL EnvironmentVariable = "PHOTOVIEW_MYSQL_URL" + EnvPostgresURL EnvironmentVariable = "PHOTOVIEW_POSTGRES_URL" EnvSqlitePath EnvironmentVariable = "PHOTOVIEW_SQLITE_PATH" )