From 80b1aa9a2c81617bdda7ef551c19a2f114e49204 Mon Sep 17 00:00:00 2001 From: Robin Dadswell <19610103+RobinDadswell@users.noreply.github.com> Date: Mon, 28 Mar 2022 21:45:52 +0100 Subject: [PATCH] New: Postgres Support Co-Authored-By: Qstick <376117+Qstick@users.noreply.github.com> --- frontend/src/System/Status/About/About.js | 9 + .../CleanseLogMessageFixture.cs | 1 + .../Instrumentation/CleanseLogMessage.cs | 1 + .../Datastore/DatabaseFixture.cs | 2 +- .../Migration/147_custom_formatsFixture.cs | 4 +- .../149_regex_required_tagsFixture.cs | 4 +- ...ix_format_tags_double_underscoreFixture.cs | 4 +- ...guage_to_files_history_blacklistFixture.cs | 34 +- ...156_add_download_client_priorityFixture.cs | 22 +- .../159_add_webrip_qualitiesFixture.cs | 10 +- ...emove_custom_formats_from_quality_model.cs | 12 +- .../Migration/168_custom_format_rework.cs | 4 +- .../170_fix_trakt_list_configFixture.cs | 32 +- .../174_email_multiple_addressesFixture.cs | 2 +- .../Migration/178_new_list_serverFixture.cs | 4 +- ...0_fix_invalid_profile_referencesFixture.cs | 24 +- .../186_fix_tmdb_duplicatesFixture.cs | 16 +- ...188_mediainfo_channel_propertiesFixture.cs | 2 +- .../200_cdh_per_downloadclientFixture.cs | 12 +- .../201_migrate_discord_from_slackFixture.cs | 2 +- .../Migration/202_remove_predbFixture.cs | 10 +- ...ixture.cs => WhereBuilderSqliteFixture.cs} | 12 +- .../Housekeepers/CleanupUnusedTagsFixture.cs | 2 +- .../FixFutureRunScheduledTasksFixture.cs | 5 +- src/NzbDrone.Core/Backup/BackupService.cs | 7 +- .../Blocklisting/BlocklistRepository.cs | 2 +- .../Configuration/ConfigFileProvider.cs | 14 +- .../Datastore/BasicRepository.cs | 21 +- .../Datastore/ConnectionStringFactory.cs | 29 +- src/NzbDrone.Core/Datastore/Database.cs | 43 +- src/NzbDrone.Core/Datastore/DbFactory.cs | 18 +- .../Datastore/Extensions/BuilderExtensions.cs | 35 +- src/NzbDrone.Core/Datastore/LogDatabase.cs | 4 + src/NzbDrone.Core/Datastore/MainDatabase.cs | 4 + .../Datastore/Migration/001_initial_setup.cs | 6 +- .../Migration/108_update_schedule_interval.cs | 2 +- .../109_add_movie_formats_to_naming_config.cs | 8 +- .../Migration/115_update_movie_sorttitle.cs | 4 +- .../116_update_movie_sorttitle_again.cs | 4 +- .../Migration/117_update_movie_file.cs | 4 +- .../Migration/118_update_movie_slug.cs | 4 +- .../Migration/121_update_filedate_config.cs | 4 +- .../Migration/123_create_netimport_table.cs | 4 +- .../Migration/125_fix_imdb_unique.cs | 4 +- .../126_update_qualities_and_profiles.cs | 6 +- .../132_rename_torrent_downloadstation.cs | 2 +- .../Migration/133_add_minimumavailability.cs | 4 +- .../137_add_import_exclusions_table.cs | 4 +- .../Migration/139_fix_indexer_baseurl.cs | 4 +- .../Migration/141_fix_duplicate_alt_titles.cs | 8 +- .../Migration/145_banner_to_fanart.cs | 4 +- .../148_remove_extra_naming_config.cs | 2 +- .../149_convert_regex_required_tags.cs | 12 +- .../Migration/151_add_tags_to_net_import.cs | 2 +- ...53_indexer_client_status_search_changes.cs | 2 +- ..._add_language_to_file_history_blacklist.cs | 50 ++- .../155_add_update_allowed_quality_profile.cs | 2 +- .../156_add_download_client_priority.cs | 53 ++- .../Migration/159_add_webrip_qualities.cs | 16 +- .../160_health_issue_notification.cs | 4 +- ...emove_custom_formats_from_quality_model.cs | 28 +- .../Migration/166_fix_tmdb_list_config.cs | 12 +- .../Migration/167_remove_movie_pathstate.cs | 2 +- .../Migration/168_custom_format_rework.cs | 4 +- .../Migration/169_custom_format_scores.cs | 6 +- .../Migration/170_fix_trakt_list_config.cs | 10 +- .../171_quality_definition_preferred_size.cs | 4 +- .../Migration/172_add_download_history.cs | 14 +- .../Migration/174_email_multiple_addresses.cs | 4 +- ...175_remove_chown_and_folderchmod_config.cs | 2 +- .../Migration/177_language_improvements.cs | 35 +- .../Migration/178_new_list_server.cs | 20 +- .../180_fix_invalid_profile_references.cs | 27 +- .../Migration/181_list_movies_table.cs | 2 +- .../Migration/183_download_propers_config.cs | 6 +- .../Migration/186_fix_tmdb_duplicates.cs | 4 +- .../187_swap_filechmod_for_folderchmod.cs | 6 +- .../Migration/188_mediainfo_channels.cs | 7 +- .../Migration/190_update_awesome_hd_link.cs | 4 +- .../192_add_on_delete_to_notifications.cs | 4 +- .../194_add_bypass_to_delay_profile.cs | 2 +- .../Migration/195_update_notifiarr.cs | 2 +- .../Migration/196_legacy_mediainfo_hdr.cs | 2 +- .../Migration/199_mediainfo_to_ffmpeg.cs | 4 +- .../Migration/200_cdh_per_downloadclient.cs | 23 +- .../201_migrate_discord_from_slack.cs | 12 +- .../203_add_on_update_to_notifications.cs | 2 +- .../204_ensure_identity_on_id_columns.cs | 22 +- .../Migration/206_multiple_ratings_support.cs | 8 +- .../Framework/MigrationController.cs | 16 +- src/NzbDrone.Core/Datastore/SqlBuilder.cs | 8 + src/NzbDrone.Core/Datastore/TableMapper.cs | 37 +- src/NzbDrone.Core/Datastore/WhereBuilder.cs | 384 +---------------- .../Datastore/WhereBuilderPostgres.cs | 387 ++++++++++++++++++ .../Datastore/WhereBuilderSqlite.cs | 387 ++++++++++++++++++ .../History/HistoryRepository.cs | 10 +- .../CleanupAbsolutePathMetadataFiles.cs | 30 +- .../CleanupAdditionalNamingSpecs.cs | 6 +- .../Housekeepers/CleanupAdditionalUsers.cs | 6 +- ...ownloadClientUnavailablePendingReleases.cs | 20 +- .../CleanupDuplicateMetadataFiles.cs | 24 +- .../CleanupOrphanedAlternativeTitles.cs | 12 +- .../Housekeepers/CleanupOrphanedBlocklist.cs | 12 +- .../Housekeepers/CleanupOrphanedCredits.cs | 12 +- .../CleanupOrphanedDownloadClientStatus.cs | 12 +- .../Housekeepers/CleanupOrphanedExtraFiles.cs | 26 +- .../CleanupOrphanedHistoryItems.cs | 12 +- .../CleanupOrphanedIndexerStatus.cs | 12 +- .../CleanupOrphanedMetadataFiles.cs | 36 +- .../Housekeepers/CleanupOrphanedMovieFiles.cs | 12 +- .../CleanupOrphanedMovieMovieFileIds.cs | 14 +- .../CleanupOrphanedMovieTranslations.cs | 12 +- .../CleanupOrphanedPendingReleases.cs | 12 +- .../CleanupOrphanedSubtitleFiles.cs | 26 +- .../Housekeepers/CleanupUnusedTags.cs | 20 +- .../FixFutureRunScheduledTasks.cs | 6 +- .../FixWronglyMatchedMovieFiles.cs | 10 +- .../Instrumentation/DatabaseTarget.cs | 73 +++- src/NzbDrone.Core/Localization/Core/en.json | 1 + .../Messaging/Commands/CommandRepository.cs | 2 +- src/NzbDrone.Core/Movies/MovieRepository.cs | 97 ++++- src/NzbDrone.Core/Radarr.Core.csproj | 2 + .../Update/UpdatePackageProvider.cs | 6 +- src/Radarr.Api.V3/System/SystemController.cs | 3 +- 124 files changed, 1740 insertions(+), 909 deletions(-) rename src/NzbDrone.Core.Test/Datastore/{WhereBuilderFixture.cs => WhereBuilderSqliteFixture.cs} (94%) create mode 100644 src/NzbDrone.Core/Datastore/WhereBuilderPostgres.cs create mode 100644 src/NzbDrone.Core/Datastore/WhereBuilderSqlite.cs diff --git a/frontend/src/System/Status/About/About.js b/frontend/src/System/Status/About/About.js index 4314aa880..775b3ea5b 100644 --- a/frontend/src/System/Status/About/About.js +++ b/frontend/src/System/Status/About/About.js @@ -23,6 +23,8 @@ class About extends Component { isDocker, runtimeVersion, migrationVersion, + databaseVersion, + databaseType, appData, startupPath, mode, @@ -68,6 +70,11 @@ class About extends Component { data={migrationVersion} /> + + [^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase), new Regex(@"/fetch/[a-z0-9]{32}/(?[a-z0-9]{32})", RegexOptions.Compiled), new Regex(@"getnzb.*?(?<=\?|&)(r)=(?[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase), + new Regex(@"(?<=[?& ;])[^=]*?(_?(?[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase), // Trackers Announce Keys; Designed for Qbit Json; should work for all in theory new Regex(@"announce(\.php)?(/|%2f|%3fpasskey%3d)(?[a-z0-9]{16,})|(?[a-z0-9]{16,})(/|%2f)announce"), diff --git a/src/NzbDrone.Core.Test/Datastore/DatabaseFixture.cs b/src/NzbDrone.Core.Test/Datastore/DatabaseFixture.cs index 8735845d6..2769e8e7b 100644 --- a/src/NzbDrone.Core.Test/Datastore/DatabaseFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/DatabaseFixture.cs @@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.Datastore public void SingleOrDefault_should_return_null_on_empty_db() { Mocker.Resolve() - .OpenConnection().Query("SELECT * FROM Movies") + .OpenConnection().Query("SELECT * FROM \"Movies\"") .SingleOrDefault() .Should() .BeNull(); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/147_custom_formatsFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/147_custom_formatsFixture.cs index 1ebf69101..bff868068 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/147_custom_formatsFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/147_custom_formatsFixture.cs @@ -135,9 +135,9 @@ namespace NzbDrone.Core.Test.Datastore.Migration private List QueryItems(IDirectDataMapper db) { - var test = db.Query("SELECT * FROM Profiles"); + var test = db.Query("SELECT * FROM \"Profiles\""); - var items = db.Query("SELECT FormatItems, FormatCutoff FROM Profiles"); + var items = db.Query("SELECT \"FormatItems\", \"FormatCutoff\" FROM \"Profiles\""); return items.Select(i => { diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/149_regex_required_tagsFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/149_regex_required_tagsFixture.cs index e4765319b..55af2587e 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/149_regex_required_tagsFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/149_regex_required_tagsFixture.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using FluentAssertions; using Newtonsoft.Json; @@ -77,7 +77,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration private List QueryItems(IDirectDataMapper db) { - var items = db.Query("SELECT Name, FormatTags FROM CustomFormats"); + var items = db.Query("SELECT \"Name\", \"FormatTags\" FROM \"CustomFormats\""); return items.Select(i => { diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/150_fix_format_tags_double_underscoreFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/150_fix_format_tags_double_underscoreFixture.cs index 7afde6ef0..21e7818a5 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/150_fix_format_tags_double_underscoreFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/150_fix_format_tags_double_underscoreFixture.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using FluentAssertions; using Newtonsoft.Json; @@ -40,7 +40,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration private List QueryItems(IDirectDataMapper db) { - var items = db.Query("SELECT Name, FormatTags FROM CustomFormats"); + var items = db.Query("SELECT \"Name\", \"FormatTags\" FROM \"CustomFormats\""); return items.Select(i => { diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/154_add_language_to_files_history_blacklistFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/154_add_language_to_files_history_blacklistFixture.cs index 0f4a94cc3..417e8d840 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/154_add_language_to_files_history_blacklistFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/154_add_language_to_files_history_blacklistFixture.cs @@ -32,8 +32,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration Monitored = true, Title = "My Movie", CleanTitle = "mytitle", - Status = MovieStatusType.Announced, - MinimumAvailability = MovieStatusType.Announced, + Status = (int)MovieStatusType.Announced, + MinimumAvailability = (int)MovieStatusType.Announced, Images = new[] { new { CoverType = "Poster" } }.ToJson(), HasPreDBEntry = false, PathState = 1, @@ -112,7 +112,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovieFile(c, "My.Movie.2018.German.BluRay-Radarr", "Japanese"); }); - var items = db.Query("SELECT Id, Languages FROM MovieFiles"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -130,7 +130,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovieFile(c, "My.Movie.2018.German.BluRay-Radarr", "Japanese / French"); }); - var items = db.Query("SELECT Id, Languages FROM MovieFiles"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(2); @@ -149,7 +149,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovieFile(c, "My.Movie.2018.German.BluRay-Radarr", ""); }); - var items = db.Query("SELECT Id, Languages FROM MovieFiles"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -166,7 +166,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovieFile(c, "My.Movie.2018.German.BluRay-Radarr", "English (USA)"); }); - var items = db.Query("SELECT Id, Languages FROM MovieFiles"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -184,7 +184,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovieFile(c, "", ""); }); - var items = db.Query("SELECT Id, Languages FROM MovieFiles"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -201,7 +201,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovieFile(c, null, null); }); - var items = db.Query("SELECT Id, Languages FROM MovieFiles"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -218,7 +218,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovieFile(c, "My.Movie.2018.BluRay-Radarr", ""); }); - var items = db.Query("SELECT Id, Languages FROM MovieFiles"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -235,7 +235,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovieFile(c, "", ""); }); - var items = db.Query("SELECT Id, Languages FROM MovieFiles"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"MovieFiles\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -253,7 +253,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddHistory(c, "My.Movie.2018.Italian.BluRay-Radarr"); }); - var items = db.Query("SELECT Id, Languages FROM History"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"History\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -270,7 +270,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddHistory(c, ""); }); - var items = db.Query("SELECT Id, Languages FROM History"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"History\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -287,7 +287,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddHistory(c, "Man on Fire"); }); - var items = db.Query("SELECT Id, Languages FROM History"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"History\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -305,7 +305,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddHistory(c, "My.Movie.2018.Italian.BluRay-Radarr"); }); - var items = db.Query("SELECT Id, Languages FROM History"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"History\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(3); @@ -324,7 +324,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddBlacklist(c, "My.Movie.2018.Italian.BluRay-Radarr"); }); - var items = db.Query("SELECT Id, Languages FROM Blacklist"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"Blacklist\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -341,7 +341,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddBlacklist(c, ""); }); - var items = db.Query("SELECT Id, Languages FROM Blacklist"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"Blacklist\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); @@ -358,7 +358,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddBlacklist(c, "Man on Fire"); }); - var items = db.Query("SELECT Id, Languages FROM Blacklist"); + var items = db.Query("SELECT \"Id\", \"Languages\" FROM \"Blacklist\""); items.Should().HaveCount(1); items.First().Languages.Count.Should().Be(1); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/156_add_download_client_priorityFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/156_add_download_client_priorityFixture.cs index 7f6c05671..276d03586 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/156_add_download_client_priorityFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/156_add_download_client_priorityFixture.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using FluentAssertions; using Newtonsoft.Json.Linq; using NUnit.Framework; @@ -18,7 +18,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration { c.Insert.IntoTable("DownloadClients").Row(new { - Enable = 1, + Enable = true, Name = "Deluge", Implementation = "Deluge", Settings = new DelugeSettings156 @@ -31,7 +31,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM DownloadClients"); + var items = db.Query("SELECT * FROM \"DownloadClients\""); items.Should().HaveCount(1); items.First().Priority.Should().Be(1); @@ -44,7 +44,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration { c.Insert.IntoTable("DownloadClients").Row(new { - Enable = 1, + Enable = true, Name = "Deluge", Implementation = "Deluge", Settings = new DelugeSettings156 @@ -56,7 +56,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration ConfigContract = "DelugeSettings" }).Row(new { - Enable = 1, + Enable = true, Name = "Deluge2", Implementation = "Deluge", Settings = new DelugeSettings156 @@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration ConfigContract = "DelugeSettings" }).Row(new { - Enable = 1, + Enable = true, Name = "sab", Implementation = "Sabnzbd", Settings = new SabnzbdSettings156 @@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM DownloadClients"); + var items = db.Query("SELECT * FROM \"DownloadClients\""); items.Should().HaveCount(3); items[0].Priority.Should().Be(1); @@ -95,7 +95,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration { c.Insert.IntoTable("DownloadClients").Row(new { - Enable = 0, + Enable = false, Name = "Deluge", Implementation = "Deluge", Settings = new DelugeSettings156 @@ -107,7 +107,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration ConfigContract = "DelugeSettings" }).Row(new { - Enable = 0, + Enable = false, Name = "Deluge2", Implementation = "Deluge", Settings = new DelugeSettings156 @@ -119,7 +119,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration ConfigContract = "DelugeSettings" }).Row(new { - Enable = 0, + Enable = false, Name = "sab", Implementation = "Sabnzbd", Settings = new SabnzbdSettings156 @@ -131,7 +131,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM DownloadClients"); + var items = db.Query("SELECT * FROM \"DownloadClients\""); items.Should().HaveCount(3); items[0].Priority.Should().Be(1); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/159_add_webrip_qualitiesFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/159_add_webrip_qualitiesFixture.cs index 43bc3b2b0..92d04e225 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/159_add_webrip_qualitiesFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/159_add_webrip_qualitiesFixture.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Datastore.Migration; @@ -34,7 +34,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var profiles = db.Query("SELECT Items FROM Profiles LIMIT 1"); + var profiles = db.Query("SELECT \"Items\" FROM \"Profiles\" LIMIT 1"); var items = profiles.First().Items; items.Should().HaveCount(5); @@ -57,7 +57,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var profiles = db.Query("SELECT Items FROM Profiles LIMIT 1"); + var profiles = db.Query("SELECT \"Items\" FROM \"Profiles\" LIMIT 1"); var items = profiles.First().Items; items.Should().HaveCount(5); @@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var profiles = db.Query("SELECT Items FROM Profiles LIMIT 1"); + var profiles = db.Query("SELECT \"Items\" FROM \"Profiles\" LIMIT 1"); var items = profiles.First().Items; items.Count(c => c.Id == 1001).Should().Be(1); @@ -104,7 +104,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var profiles = db.Query("SELECT Items FROM Profiles LIMIT 1"); + var profiles = db.Query("SELECT \"Items\" FROM \"Profiles\" LIMIT 1"); var items = profiles.First().Items; items[1].Items.First().Quality.Should().Be((int)Quality.WEBRip480p); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/165_remove_custom_formats_from_quality_model.cs b/src/NzbDrone.Core.Test/Datastore/Migration/165_remove_custom_formats_from_quality_model.cs index 88d9eb7de..ca919f573 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/165_remove_custom_formats_from_quality_model.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/165_remove_custom_formats_from_quality_model.cs @@ -81,14 +81,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration ""imdbId"": """" }", Release = "{}", - Reason = PendingReleaseReason.Delay + Reason = (int)PendingReleaseReason.Delay }); }); - var json = db.Query("SELECT ParsedMovieInfo FROM PendingReleases").First(); + var json = db.Query("SELECT \"ParsedMovieInfo\" FROM \"PendingReleases\"").First(); json.Should().NotContain("customFormats"); - var pending = db.Query("SELECT ParsedMovieInfo FROM PendingReleases").First(); + var pending = db.Query("SELECT \"ParsedMovieInfo\" FROM \"PendingReleases\"").First(); pending.Quality.Quality.Should().Be(Quality.Bluray1080p); pending.Languages.Should().BeEmpty(); } @@ -129,15 +129,15 @@ namespace NzbDrone.Core.Test.Datastore.Migration ""imdbId"": """" }", Release = "{}", - Reason = PendingReleaseReason.Delay + Reason = (int)PendingReleaseReason.Delay }); }); - var json = db.Query("SELECT ParsedMovieInfo FROM PendingReleases").First(); + var json = db.Query("SELECT \"ParsedMovieInfo\" FROM \"PendingReleases\"").First(); json.Should().NotContain("customFormats"); json.Should().NotContain("resolution"); - var pending = db.Query("SELECT ParsedMovieInfo FROM PendingReleases").First(); + var pending = db.Query("SELECT \"ParsedMovieInfo\" FROM \"PendingReleases\"").First(); pending.Quality.Quality.Should().Be(Quality.Bluray1080p); pending.Languages.Should().BeEquivalentTo(new List { Language.English }); } diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/168_custom_format_rework.cs b/src/NzbDrone.Core.Test/Datastore/Migration/168_custom_format_rework.cs index 4b25145a3..4914764f1 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/168_custom_format_rework.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/168_custom_format_rework.cs @@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var json = db.Query("SELECT Specifications FROM CustomFormats").First(); + var json = db.Query("SELECT \"Specifications\" FROM \"CustomFormats\"").First(); ValidateFormatTag(json, "ReleaseTitleSpecification", false, false); json.Should().Contain($"\"name\": \"Test\""); @@ -99,7 +99,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var json = db.Query("SELECT Specifications FROM CustomFormats").First(); + var json = db.Query("SELECT \"Specifications\" FROM \"CustomFormats\"").First(); ValidateFormatTag(json, "ReleaseTitleSpecification", false, false); ValidateFormatTag(json, "EditionSpecification", false, false); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/170_fix_trakt_list_configFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/170_fix_trakt_list_configFixture.cs index 74f58043e..2ef5dad44 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/170_fix_trakt_list_configFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/170_fix_trakt_list_configFixture.cs @@ -19,12 +19,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration { c.Insert.IntoTable("NetImport").Row(new { - Enabled = 1, - EnableAuto = 1, + Enabled = true, + EnableAuto = true, RootFolderPath = "D:\\Movies", ProfileId = 1, MinimumAvailability = 1, - ShouldMonitor = 1, + ShouldMonitor = true, Name = "IMDB List", Implementation = "RadarrLists", Settings = new RadarrListSettings169 @@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM NetImport"); + var items = db.Query("SELECT * FROM \"NetImport\""); items.Should().HaveCount(1); items.First().Implementation.Should().Be("RadarrListImport"); @@ -52,12 +52,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration { c.Insert.IntoTable("NetImport").Row(new { - Enabled = 1, - EnableAuto = 1, + Enabled = true, + EnableAuto = true, RootFolderPath = "D:\\Movies", ProfileId = 1, MinimumAvailability = 1, - ShouldMonitor = 1, + ShouldMonitor = true, Name = "TraktImport", Implementation = "TraktImport", Settings = new TraktSettings169 @@ -72,7 +72,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM NetImport"); + var items = db.Query("SELECT * FROM \"NetImport\""); items.Should().HaveCount(1); items.First().Implementation.Should().Be("TraktUserImport"); @@ -90,12 +90,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration { c.Insert.IntoTable("NetImport").Row(new { - Enabled = 1, - EnableAuto = 1, + Enabled = true, + EnableAuto = true, RootFolderPath = "D:\\Movies", ProfileId = 1, MinimumAvailability = 1, - ShouldMonitor = 1, + ShouldMonitor = true, Name = "TraktImport", Implementation = "TraktImport", Settings = new TraktSettings169 @@ -110,7 +110,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM NetImport"); + var items = db.Query("SELECT * FROM \"NetImport\""); items.Should().HaveCount(1); items.First().Implementation.Should().Be("TraktPopularImport"); @@ -128,12 +128,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration { c.Insert.IntoTable("NetImport").Row(new { - Enabled = 1, - EnableAuto = 1, + Enabled = true, + EnableAuto = true, RootFolderPath = "D:\\Movies", ProfileId = 1, MinimumAvailability = 1, - ShouldMonitor = 1, + ShouldMonitor = true, Name = "TraktImport", Implementation = "TraktImport", Settings = new TraktSettings169 @@ -149,7 +149,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM NetImport"); + var items = db.Query("SELECT * FROM \"NetImport\""); items.Should().HaveCount(1); items.First().Implementation.Should().Be("TraktListImport"); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/174_email_multiple_addressesFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/174_email_multiple_addressesFixture.cs index 2d240134d..82e014dd5 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/174_email_multiple_addressesFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/174_email_multiple_addressesFixture.cs @@ -37,7 +37,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM Notifications"); + var items = db.Query("SELECT * FROM \"Notifications\""); items.Should().HaveCount(1); items.First().Implementation.Should().Be("Email"); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/178_new_list_serverFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/178_new_list_serverFixture.cs index cf71ed09f..406ce1d2d 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/178_new_list_serverFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/178_new_list_serverFixture.cs @@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration } }); - var items = db.Query("SELECT * FROM NetImport"); + var items = db.Query("SELECT * FROM \"NetImport\""); items.Should().HaveCount(7); @@ -157,7 +157,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration } }); - var items = db.Query("SELECT * FROM NetImport"); + var items = db.Query("SELECT * FROM \"NetImport\""); items.Should().HaveCount(5); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/180_fix_invalid_profile_referencesFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/180_fix_invalid_profile_referencesFixture.cs index ee6218366..8b1eca13d 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/180_fix_invalid_profile_referencesFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/180_fix_invalid_profile_referencesFixture.cs @@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration Items = items.ToJson(), Language = (int)Language.English, MinFormatScore = 0, - CutOffFormatScore = 0 + CutoffFormatScore = 0 }; m.Insert.IntoTable("Profiles").Row(profile); @@ -50,8 +50,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration Monitored = true, Title = movieTitle, CleanTitle = movieTitle, - Status = MovieStatusType.Announced, - MinimumAvailability = MovieStatusType.Announced, + Status = (int)MovieStatusType.Announced, + MinimumAvailability = (int)MovieStatusType.Announced, Images = new[] { new { CoverType = "Poster" } }.ToJson(), Recommendations = new[] { 1 }.ToJson(), HasPreDBEntry = false, @@ -89,8 +89,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, "movie", 123456, profileId); }); - var items = db.Query("SELECT Id, ProfileId FROM Movies"); - var profiles = db.Query("SELECT Id FROM Profiles"); + var items = db.Query("SELECT \"Id\", \"ProfileId\" FROM \"Movies\""); + var profiles = db.Query("SELECT \"Id\" FROM \"Profiles\""); items.Should().HaveCount(1); profiles.Should().HaveCount(6); @@ -108,8 +108,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, "movie", 123456, 17); }); - var items = db.Query("SELECT Id, ProfileId FROM Movies"); - var profiles = db.Query("SELECT Id FROM Profiles"); + var items = db.Query("SELECT \"Id\", \"ProfileId\" FROM \"Movies\""); + var profiles = db.Query("SELECT \"Id\" FROM \"Profiles\""); items.Should().HaveCount(1); profiles.Should().HaveCount(1); @@ -128,8 +128,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, "movie", 123456, profileId); }); - var items = db.Query("SELECT Id, ProfileId FROM Movies"); - var profiles = db.Query("SELECT Id, FormatItems FROM Profiles"); + var items = db.Query("SELECT \"Id\", \"ProfileId\" FROM \"Movies\""); + var profiles = db.Query("SELECT \"Id\", \"FormatItems\" FROM \"Profiles\""); items.Should().HaveCount(1); profiles.Should().HaveCount(6); @@ -149,7 +149,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, "movie", 123456, profileId); }); - var items = db.Query("SELECT Id, ProfileId FROM Movies"); + var items = db.Query("SELECT \"Id\", \"ProfileId\" FROM \"Movies\""); items.Should().HaveCount(1); items.First().ProfileId.Should().Be(profileId); @@ -166,7 +166,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, "movie", 123456, 1); }); - var items = db.Query("SELECT Id, ProfileId FROM Movies"); + var items = db.Query("SELECT \"Id\", \"ProfileId\" FROM \"Movies\""); items.Should().HaveCount(1); items.First().ProfileId.Should().Be(profileId); @@ -193,7 +193,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, "movie9", 123459, otherProfileId); }); - var items = db.Query("SELECT Id, ProfileId FROM Movies"); + var items = db.Query("SELECT \"Id\", \"ProfileId\" FROM \"Movies\""); items.Should().HaveCount(9); items.Where(x => x.ProfileId == commonProfileId).Should().HaveCount(7); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/186_fix_tmdb_duplicatesFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/186_fix_tmdb_duplicatesFixture.cs index 9a4f1971b..5d7fc617d 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/186_fix_tmdb_duplicatesFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/186_fix_tmdb_duplicatesFixture.cs @@ -20,8 +20,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration Monitored = true, Title = movieTitle, CleanTitle = movieTitle, - Status = MovieStatusType.Announced, - MinimumAvailability = MovieStatusType.Announced, + Status = (int)MovieStatusType.Announced, + MinimumAvailability = (int)MovieStatusType.Announced, Images = new[] { new { CoverType = "Poster" } }.ToJson(), Recommendations = new[] { 1 }.ToJson(), HasPreDBEntry = false, @@ -53,7 +53,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, 4, "movie", "slug3", tmdbId, 0, dateAdded, dateAdded); }); - var items = db.Query("SELECT Id, TmdbId, MovieFileId FROM Movies"); + var items = db.Query("SELECT \"Id\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\""); items.Should().HaveCount(1); } @@ -73,7 +73,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, 5, "movie2", "slug4", 123457, 0, dateAdded, dateAdded); }); - var items = db.Query("SELECT Id, TmdbId, MovieFileId FROM Movies"); + var items = db.Query("SELECT \"Id\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\""); items.Should().HaveCount(2); items.Where(i => i.TmdbId == tmdbId).Should().HaveCount(1); @@ -93,7 +93,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, 5, "movie5", "slug4", 123457, 0, dateAdded, dateAdded); }); - var items = db.Query("SELECT Id, TmdbId, MovieFileId FROM Movies"); + var items = db.Query("SELECT \"Id\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\""); items.Should().HaveCount(5); } @@ -112,7 +112,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, 4, "movie", "slug3", tmdbId, 0, dateAdded, dateAdded); }); - var items = db.Query("SELECT Id, TmdbId, MovieFileId FROM Movies"); + var items = db.Query("SELECT \"Id\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\""); items.Should().HaveCount(1); items.First().Id.Should().Be(2); @@ -132,7 +132,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, 4, "movie", "slug3", tmdbId, 2, dateAdded, dateAdded); }); - var items = db.Query("SELECT Id, TmdbId, MovieFileId FROM Movies"); + var items = db.Query("SELECT \"Id\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\""); items.Should().HaveCount(1); items.First().MovieFileId.Should().BeGreaterThan(0); @@ -153,7 +153,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovie(c, 4, "movie", "slug3", tmdbId, 0, null, dateAdded); }); - var items = db.Query("SELECT Id, LastInfoSync, TmdbId, MovieFileId FROM Movies"); + var items = db.Query("SELECT \"Id\", \"LastInfoSync\", \"TmdbId\", \"MovieFileId\" FROM \"Movies\""); items.Should().HaveCount(1); items.First().LastInfoSync.Should().NotBeNull(); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/188_mediainfo_channel_propertiesFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/188_mediainfo_channel_propertiesFixture.cs index 14fa22164..204c9ab4f 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/188_mediainfo_channel_propertiesFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/188_mediainfo_channel_propertiesFixture.cs @@ -67,7 +67,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration AddMovieFile(c, 1); }); - var items = db.Query("SELECT MediaInfo FROM MovieFiles"); + var items = db.Query("SELECT \"MediaInfo\" FROM \"MovieFiles\""); items.Should().HaveCount(1); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/200_cdh_per_downloadclientFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/200_cdh_per_downloadclientFixture.cs index 438e26a93..ce3f8db7c 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/200_cdh_per_downloadclientFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/200_cdh_per_downloadclientFixture.cs @@ -20,7 +20,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration { c.Insert.IntoTable("DownloadClients").Row(new { - Enable = 1, + Enable = true, Name = "Deluge", Implementation = "Deluge", Priority = 1, @@ -34,7 +34,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM DownloadClients"); + var items = db.Query("SELECT * FROM \"DownloadClients\""); items.Should().HaveCount(1); items.First().RemoveCompletedDownloads.Should().BeFalse(); @@ -54,7 +54,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration c.Insert.IntoTable("DownloadClients").Row(new { - Enable = 1, + Enable = true, Name = "Deluge", Implementation = "Deluge", Priority = 1, @@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM DownloadClients"); + var items = db.Query("SELECT * FROM \"DownloadClients\""); items.Should().HaveCount(1); items.First().RemoveCompletedDownloads.Should().BeTrue(); @@ -82,7 +82,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration { c.Insert.IntoTable("DownloadClients").Row(new { - Enable = 1, + Enable = true, Name = "RTorrent", Implementation = "RTorrent", Priority = 1, @@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT * FROM DownloadClients"); + var items = db.Query("SELECT * FROM \"DownloadClients\""); items.Should().HaveCount(1); items.First().RemoveCompletedDownloads.Should().BeFalse(); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/201_migrate_discord_from_slackFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/201_migrate_discord_from_slackFixture.cs index 370618416..15e50d14f 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/201_migrate_discord_from_slackFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/201_migrate_discord_from_slackFixture.cs @@ -58,7 +58,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT Id,ConfigContract,Implementation,Name,Settings FROM Notifications"); + var items = db.Query("SELECT \"Id\",\"ConfigContract\",\"Implementation\",\"Name\",\"Settings\" FROM \"Notifications\""); items.Should().HaveCount(1); items.First().ConfigContract.Should().Be("DiscordSettings"); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/202_remove_predbFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/202_remove_predbFixture.cs index f6b1618db..ebc71465e 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/202_remove_predbFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/202_remove_predbFixture.cs @@ -20,12 +20,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration { c.Insert.IntoTable("ImportLists").Row(new { - Enabled = 1, - EnableAuto = 1, + Enabled = true, + EnableAuto = true, RootFolderPath = "D:\\Movies", ProfileId = 1, MinimumAvailability = 4, - ShouldMonitor = 1, + ShouldMonitor = true, Name = "IMDB List", Implementation = "RadarrLists", Settings = new RadarrListSettings169 @@ -37,7 +37,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT Id, MinimumAvailability FROM ImportLists"); + var items = db.Query("SELECT \"Id\", \"MinimumAvailability\" FROM \"ImportLists\""); items.Should().HaveCount(1); items.First().MinimumAvailability.Should().Be(3); @@ -70,7 +70,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration }); }); - var items = db.Query("SELECT Id, MinimumAvailability FROM Movies"); + var items = db.Query("SELECT \"Id\", \"MinimumAvailability\" FROM \"Movies\""); items.Should().HaveCount(1); items.First().MinimumAvailability.Should().Be(3); diff --git a/src/NzbDrone.Core.Test/Datastore/WhereBuilderFixture.cs b/src/NzbDrone.Core.Test/Datastore/WhereBuilderSqliteFixture.cs similarity index 94% rename from src/NzbDrone.Core.Test/Datastore/WhereBuilderFixture.cs rename to src/NzbDrone.Core.Test/Datastore/WhereBuilderSqliteFixture.cs index b1cccc8d5..30fe38306 100644 --- a/src/NzbDrone.Core.Test/Datastore/WhereBuilderFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/WhereBuilderSqliteFixture.cs @@ -11,9 +11,9 @@ using NzbDrone.Core.Test.Framework; namespace NzbDrone.Core.Test.Datastore { [TestFixture] - public class WhereBuilderFixture : CoreTest + public class WhereBuilderSqliteFixture : CoreTest { - private WhereBuilder _subject; + private WhereBuilderSqlite _subject; [OneTimeSetUp] public void MapTables() @@ -22,9 +22,9 @@ namespace NzbDrone.Core.Test.Datastore Mocker.Resolve(); } - private WhereBuilder Where(Expression> filter) + private WhereBuilderSqlite Where(Expression> filter) { - return new WhereBuilder(filter, true, 0); + return new WhereBuilderSqlite(filter, true, 0); } [Test] @@ -71,7 +71,7 @@ namespace NzbDrone.Core.Test.Datastore public void where_throws_without_concrete_condition_if_requiresConcreteCondition() { Expression> filter = (x, y) => x.Id == y.Id; - _subject = new WhereBuilder(filter, true, 0); + _subject = new WhereBuilderSqlite(filter, true, 0); Assert.Throws(() => _subject.ToString()); } @@ -79,7 +79,7 @@ namespace NzbDrone.Core.Test.Datastore public void where_allows_abstract_condition_if_not_requiresConcreteCondition() { Expression> filter = (x, y) => x.Id == y.Id; - _subject = new WhereBuilder(filter, false, 0); + _subject = new WhereBuilderSqlite(filter, false, 0); _subject.ToString().Should().Be($"(\"Movies\".\"Id\" = \"Movies\".\"Id\")"); } diff --git a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupUnusedTagsFixture.cs b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupUnusedTagsFixture.cs index d32e16e63..3fb5376e4 100644 --- a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupUnusedTagsFixture.cs +++ b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupUnusedTagsFixture.cs @@ -1,4 +1,4 @@ -using FizzWare.NBuilder; +using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Housekeeping.Housekeepers; diff --git a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/FixFutureRunScheduledTasksFixture.cs b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/FixFutureRunScheduledTasksFixture.cs index 68e4c87e6..ce7df27b7 100644 --- a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/FixFutureRunScheduledTasksFixture.cs +++ b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/FixFutureRunScheduledTasksFixture.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using FizzWare.NBuilder; using FluentAssertions; @@ -41,7 +41,8 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers Subject.Clean(); - AllStoredModels.ToList().ForEach(t => t.LastExecution.Should().Be(expectedTime)); + // BeCloseTo handles Postgres rounding times + AllStoredModels.ToList().ForEach(t => t.LastExecution.Should().BeCloseTo(expectedTime)); } } } diff --git a/src/NzbDrone.Core/Backup/BackupService.cs b/src/NzbDrone.Core/Backup/BackupService.cs index 89f3d24ab..da720df88 100644 --- a/src/NzbDrone.Core/Backup/BackupService.cs +++ b/src/NzbDrone.Core/Backup/BackupService.cs @@ -190,9 +190,12 @@ namespace NzbDrone.Core.Backup private void BackupDatabase() { - _logger.ProgressDebug("Backing up database"); + if (_maindDb.DatabaseType == DatabaseType.SQLite) + { + _logger.ProgressDebug("Backing up database"); - _makeDatabaseBackup.BackupDatabase(_maindDb, _backupTempFolder); + _makeDatabaseBackup.BackupDatabase(_maindDb, _backupTempFolder); + } } private void BackupConfigFile() diff --git a/src/NzbDrone.Core/Blocklisting/BlocklistRepository.cs b/src/NzbDrone.Core/Blocklisting/BlocklistRepository.cs index 3cfc921b4..5dfc96c6e 100644 --- a/src/NzbDrone.Core/Blocklisting/BlocklistRepository.cs +++ b/src/NzbDrone.Core/Blocklisting/BlocklistRepository.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Core.Blocklisting Delete(x => movieIds.Contains(x.MovieId)); } - protected override SqlBuilder PagedBuilder() => new SqlBuilder().Join((b, m) => b.MovieId == m.Id); + protected override SqlBuilder PagedBuilder() => new SqlBuilder(_database.DatabaseType).Join((b, m) => b.MovieId == m.Id); protected override IEnumerable PagedQuery(SqlBuilder sql) => _database.QueryJoined(sql, (bl, movie) => { bl.Movie = movie; diff --git a/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs b/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs index d0253aaed..1047edc46 100644 --- a/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs +++ b/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs @@ -19,7 +19,7 @@ using NzbDrone.Core.Update; namespace NzbDrone.Core.Configuration { public interface IConfigFileProvider : IHandleAsync, - IExecute + IExecute { XDocument LoadConfigFile(); Dictionary GetConfigDictionary(); @@ -48,6 +48,12 @@ namespace NzbDrone.Core.Configuration string UpdateScriptPath { get; } string SyslogServer { get; } int SyslogPort { get; } + string PostgresHost { get; } + int PostgresPort { get; } + string PostgresUser { get; } + string PostgresPassword { get; } + string PostgresMainDb { get; } + string PostgresLogDb { get; } } public class ConfigFileProvider : IConfigFileProvider @@ -184,6 +190,12 @@ namespace NzbDrone.Core.Configuration public string LogLevel => GetValue("LogLevel", "info").ToLowerInvariant(); public string ConsoleLogLevel => GetValue("ConsoleLogLevel", string.Empty, persist: false); + public string PostgresHost => GetValue("PostgresHost", string.Empty, persist: false); + public string PostgresUser => GetValue("PostgresUser", string.Empty, persist: false); + public string PostgresPassword => GetValue("PostgresPassword", string.Empty, persist: false); + public string PostgresMainDb => GetValue("PostgresMainDb", "radarr-main", persist: false); + public string PostgresLogDb => GetValue("PostgresLogDb", "radarr-log", persist: false); + public int PostgresPort => GetValueInt("PostgresPort", 5432, persist: false); public bool LogSql => GetValueBoolean("LogSql", false, persist: false); public int LogRotate => GetValueInt("LogRotate", 50, persist: false); public bool FilterSentryEvents => GetValueBoolean("FilterSentryEvents", true, persist: false); diff --git a/src/NzbDrone.Core/Datastore/BasicRepository.cs b/src/NzbDrone.Core/Datastore/BasicRepository.cs index 33527e89f..6d213d273 100644 --- a/src/NzbDrone.Core/Datastore/BasicRepository.cs +++ b/src/NzbDrone.Core/Datastore/BasicRepository.cs @@ -67,7 +67,7 @@ namespace NzbDrone.Core.Datastore _updateSql = GetUpdateSql(_properties); } - protected virtual SqlBuilder Builder() => new SqlBuilder(); + protected virtual SqlBuilder Builder() => new SqlBuilder(_database.DatabaseType); protected virtual List Query(SqlBuilder builder) => _database.Query(builder).ToList(); @@ -79,7 +79,7 @@ namespace NzbDrone.Core.Datastore { using (var conn = _database.OpenConnection()) { - return conn.ExecuteScalar($"SELECT COUNT(*) FROM {_table}"); + return conn.ExecuteScalar($"SELECT COUNT(*) FROM \"{_table}\""); } } @@ -175,6 +175,11 @@ namespace NzbDrone.Core.Datastore } } + if (_database.DatabaseType == DatabaseType.PostgreSQL) + { + return $"INSERT INTO \"{_table}\" ({sbColumnList.ToString()}) VALUES ({sbParameterList.ToString()}) RETURNING \"Id\""; + } + return $"INSERT INTO {_table} ({sbColumnList.ToString()}) VALUES ({sbParameterList.ToString()}); SELECT last_insert_rowid() id"; } @@ -182,7 +187,8 @@ namespace NzbDrone.Core.Datastore { SqlBuilderExtensions.LogQuery(_insertSql, model); var multi = connection.QueryMultiple(_insertSql, model, transaction); - var id = (int)multi.Read().First().id; + var multiRead = multi.Read(); + var id = (int)(multiRead.First().id ?? multiRead.First().Id); _keyProperty.SetValue(model, id); return model; @@ -293,7 +299,7 @@ namespace NzbDrone.Core.Datastore { using (var conn = _database.OpenConnection()) { - conn.Execute($"DELETE FROM [{_table}]"); + conn.Execute($"DELETE FROM \"{_table}\""); } if (vacuum) @@ -352,7 +358,7 @@ namespace NzbDrone.Core.Datastore private string GetUpdateSql(List propertiesToUpdate) { var sb = new StringBuilder(); - sb.AppendFormat("UPDATE {0} SET ", _table); + sb.AppendFormat("UPDATE \"{0}\" SET ", _table); for (var i = 0; i < propertiesToUpdate.Count; i++) { @@ -420,9 +426,10 @@ namespace NzbDrone.Core.Datastore pagingSpec.SortKey = $"{_table}.{_keyProperty.Name}"; } + var sortKey = TableMapping.Mapper.GetSortKey(pagingSpec.SortKey); var sortDirection = pagingSpec.SortDirection == SortDirection.Descending ? "DESC" : "ASC"; - var pagingOffset = (pagingSpec.Page - 1) * pagingSpec.PageSize; - builder.OrderBy($"{pagingSpec.SortKey} {sortDirection} LIMIT {pagingSpec.PageSize} OFFSET {pagingOffset}"); + var pagingOffset = Math.Max(pagingSpec.Page - 1, 0) * pagingSpec.PageSize; + builder.OrderBy($"\"{sortKey}\" {sortDirection} LIMIT {pagingSpec.PageSize} OFFSET {pagingOffset}"); return queryFunc(builder).ToList(); } diff --git a/src/NzbDrone.Core/Datastore/ConnectionStringFactory.cs b/src/NzbDrone.Core/Datastore/ConnectionStringFactory.cs index 9bdd133f7..961d060f8 100644 --- a/src/NzbDrone.Core/Datastore/ConnectionStringFactory.cs +++ b/src/NzbDrone.Core/Datastore/ConnectionStringFactory.cs @@ -1,7 +1,9 @@ using System; using System.Data.SQLite; +using Npgsql; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Configuration; namespace NzbDrone.Core.Datastore { @@ -14,10 +16,17 @@ namespace NzbDrone.Core.Datastore public class ConnectionStringFactory : IConnectionStringFactory { - public ConnectionStringFactory(IAppFolderInfo appFolderInfo) + private readonly IConfigFileProvider _configFileProvider; + + public ConnectionStringFactory(IAppFolderInfo appFolderInfo, IConfigFileProvider configFileProvider) { - MainDbConnectionString = GetConnectionString(appFolderInfo.GetDatabase()); - LogDbConnectionString = GetConnectionString(appFolderInfo.GetLogDatabase()); + _configFileProvider = configFileProvider; + + MainDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresMainDb) : + GetConnectionString(appFolderInfo.GetDatabase()); + + LogDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresLogDb) : + GetConnectionString(appFolderInfo.GetLogDatabase()); } public string MainDbConnectionString { get; private set; } @@ -48,5 +57,19 @@ namespace NzbDrone.Core.Datastore return connectionBuilder.ConnectionString; } + + private string GetPostgresConnectionString(string dbName) + { + var connectionBuilder = new NpgsqlConnectionStringBuilder(); + + connectionBuilder.Database = dbName; + connectionBuilder.Host = _configFileProvider.PostgresHost; + connectionBuilder.Username = _configFileProvider.PostgresUser; + connectionBuilder.Password = _configFileProvider.PostgresPassword; + connectionBuilder.Port = _configFileProvider.PostgresPort; + connectionBuilder.Enlist = false; + + return connectionBuilder.ConnectionString; + } } } diff --git a/src/NzbDrone.Core/Datastore/Database.cs b/src/NzbDrone.Core/Datastore/Database.cs index a9b6e807f..433fef0b6 100644 --- a/src/NzbDrone.Core/Datastore/Database.cs +++ b/src/NzbDrone.Core/Datastore/Database.cs @@ -1,5 +1,6 @@ using System; using System.Data; +using System.Text.RegularExpressions; using Dapper; using NLog; using NzbDrone.Common.Instrumentation; @@ -11,6 +12,7 @@ namespace NzbDrone.Core.Datastore IDbConnection OpenConnection(); Version Version { get; } int Migration { get; } + DatabaseType DatabaseType { get; } void Vacuum(); } @@ -32,13 +34,44 @@ namespace NzbDrone.Core.Datastore return _datamapperFactory(); } + public DatabaseType DatabaseType + { + get + { + using (var db = _datamapperFactory()) + { + if (db.ConnectionString.Contains(".db")) + { + return DatabaseType.SQLite; + } + else + { + return DatabaseType.PostgreSQL; + } + } + } + } + public Version Version { get { using (var db = _datamapperFactory()) { - var version = db.QueryFirstOrDefault("SELECT sqlite_version()"); + string version; + + try + { + version = db.QueryFirstOrDefault("SHOW server_version"); + + //Postgres can return extra info about operating system on version call, ignore this + version = Regex.Replace(version, @"\(.*?\)", ""); + } + catch + { + version = db.QueryFirstOrDefault("SELECT sqlite_version()"); + } + return new Version(version); } } @@ -50,7 +83,7 @@ namespace NzbDrone.Core.Datastore { using (var db = _datamapperFactory()) { - return db.QueryFirstOrDefault("SELECT version from VersionInfo ORDER BY version DESC LIMIT 1"); + return db.QueryFirstOrDefault("SELECT \"Version\" from \"VersionInfo\" ORDER BY \"Version\" DESC LIMIT 1"); } } } @@ -73,4 +106,10 @@ namespace NzbDrone.Core.Datastore } } } + + public enum DatabaseType + { + SQLite, + PostgreSQL + } } diff --git a/src/NzbDrone.Core/Datastore/DbFactory.cs b/src/NzbDrone.Core/Datastore/DbFactory.cs index 1bc2ab348..3298a7f0d 100644 --- a/src/NzbDrone.Core/Datastore/DbFactory.cs +++ b/src/NzbDrone.Core/Datastore/DbFactory.cs @@ -1,10 +1,13 @@ using System; +using System.Data.Common; using System.Data.SQLite; using NLog; +using Npgsql; using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Exceptions; using NzbDrone.Common.Instrumentation; +using NzbDrone.Core.Configuration; using NzbDrone.Core.Datastore.Migration.Framework; namespace NzbDrone.Core.Datastore @@ -85,10 +88,19 @@ namespace NzbDrone.Core.Datastore var db = new Database(migrationContext.MigrationType.ToString(), () => { - var conn = SQLiteFactory.Instance.CreateConnection(); - conn.ConnectionString = connectionString; - conn.Open(); + DbConnection conn; + if (connectionString.Contains(".db")) + { + conn = SQLiteFactory.Instance.CreateConnection(); + conn.ConnectionString = connectionString; + } + else + { + conn = new NpgsqlConnection(connectionString); + } + + conn.Open(); return conn; }); diff --git a/src/NzbDrone.Core/Datastore/Extensions/BuilderExtensions.cs b/src/NzbDrone.Core/Datastore/Extensions/BuilderExtensions.cs index 97ce5d731..b7fc3df98 100644 --- a/src/NzbDrone.Core/Datastore/Extensions/BuilderExtensions.cs +++ b/src/NzbDrone.Core/Datastore/Extensions/BuilderExtensions.cs @@ -20,7 +20,7 @@ namespace NzbDrone.Core.Datastore public static SqlBuilder Select(this SqlBuilder builder, params Type[] types) { - return builder.Select(types.Select(x => TableMapping.Mapper.TableNameMapping(x) + ".*").Join(", ")); + return builder.Select(types.Select(x => $"\"{TableMapping.Mapper.TableNameMapping(x)}\".*").Join(", ")); } public static SqlBuilder SelectDistinct(this SqlBuilder builder, params Type[] types) @@ -42,41 +42,48 @@ namespace NzbDrone.Core.Datastore public static SqlBuilder Where(this SqlBuilder builder, Expression> filter) { - var wb = new WhereBuilder(filter, true, builder.Sequence); + var wb = GetWhereBuilder(builder.DatabaseType, filter, true, builder.Sequence); + + return builder.Where(wb.ToString(), wb.Parameters); + } + + public static SqlBuilder WherePostgres(this SqlBuilder builder, Expression> filter) + { + var wb = new WhereBuilderPostgres(filter, true, builder.Sequence); return builder.Where(wb.ToString(), wb.Parameters); } public static SqlBuilder OrWhere(this SqlBuilder builder, Expression> filter) { - var wb = new WhereBuilder(filter, true, builder.Sequence); + var wb = GetWhereBuilder(builder.DatabaseType, filter, true, builder.Sequence); return builder.OrWhere(wb.ToString(), wb.Parameters); } public static SqlBuilder Join(this SqlBuilder builder, Expression> filter) { - var wb = new WhereBuilder(filter, false, builder.Sequence); + var wb = GetWhereBuilder(builder.DatabaseType, filter, false, builder.Sequence); var rightTable = TableMapping.Mapper.TableNameMapping(typeof(TRight)); - return builder.Join($"{rightTable} ON {wb.ToString()}"); + return builder.Join($"\"{rightTable}\" ON {wb.ToString()}"); } public static SqlBuilder LeftJoin(this SqlBuilder builder, Expression> filter) { - var wb = new WhereBuilder(filter, false, builder.Sequence); + var wb = GetWhereBuilder(builder.DatabaseType, filter, false, builder.Sequence); var rightTable = TableMapping.Mapper.TableNameMapping(typeof(TRight)); - return builder.LeftJoin($"{rightTable} ON {wb.ToString()}"); + return builder.LeftJoin($"\"{rightTable}\" ON {wb.ToString()}"); } public static SqlBuilder GroupBy(this SqlBuilder builder, Expression> property) { var table = TableMapping.Mapper.TableNameMapping(typeof(TModel)); var propName = property.GetMemberName().Name; - return builder.GroupBy($"{table}.{propName}"); + return builder.GroupBy($"\"{table}\".\"{propName}\""); } public static SqlBuilder.Template AddSelectTemplate(this SqlBuilder builder, Type type) @@ -138,6 +145,18 @@ namespace NzbDrone.Core.Datastore return sb.ToString(); } + private static WhereBuilder GetWhereBuilder(DatabaseType databaseType, Expression filter, bool requireConcrete, int seq) + { + if (databaseType == DatabaseType.PostgreSQL) + { + return new WhereBuilderPostgres(filter, requireConcrete, seq); + } + else + { + return new WhereBuilderSqlite(filter, requireConcrete, seq); + } + } + private static Dictionary ToDictionary(this DynamicParameters dynamicParams) { var argsDictionary = new Dictionary(); diff --git a/src/NzbDrone.Core/Datastore/LogDatabase.cs b/src/NzbDrone.Core/Datastore/LogDatabase.cs index f992c8bbe..a770c2661 100644 --- a/src/NzbDrone.Core/Datastore/LogDatabase.cs +++ b/src/NzbDrone.Core/Datastore/LogDatabase.cs @@ -10,10 +10,12 @@ namespace NzbDrone.Core.Datastore public class LogDatabase : ILogDatabase { private readonly IDatabase _database; + private readonly DatabaseType _databaseType; public LogDatabase(IDatabase database) { _database = database; + _databaseType = _database == null ? DatabaseType.SQLite : _database.DatabaseType; } public IDbConnection OpenConnection() @@ -25,6 +27,8 @@ namespace NzbDrone.Core.Datastore public int Migration => _database.Migration; + public DatabaseType DatabaseType => _databaseType; + public void Vacuum() { _database.Vacuum(); diff --git a/src/NzbDrone.Core/Datastore/MainDatabase.cs b/src/NzbDrone.Core/Datastore/MainDatabase.cs index 4a9d3298c..521293299 100644 --- a/src/NzbDrone.Core/Datastore/MainDatabase.cs +++ b/src/NzbDrone.Core/Datastore/MainDatabase.cs @@ -10,10 +10,12 @@ namespace NzbDrone.Core.Datastore public class MainDatabase : IMainDatabase { private readonly IDatabase _database; + private readonly DatabaseType _databaseType; public MainDatabase(IDatabase database) { _database = database; + _databaseType = _database == null ? DatabaseType.SQLite : _database.DatabaseType; } public IDbConnection OpenConnection() @@ -25,6 +27,8 @@ namespace NzbDrone.Core.Datastore public int Migration => _database.Migration; + public DatabaseType DatabaseType => _databaseType; + public void Vacuum() { _database.Vacuum(); diff --git a/src/NzbDrone.Core/Datastore/Migration/001_initial_setup.cs b/src/NzbDrone.Core/Datastore/Migration/001_initial_setup.cs index a3c9140be..6d2a79968 100644 --- a/src/NzbDrone.Core/Datastore/Migration/001_initial_setup.cs +++ b/src/NzbDrone.Core/Datastore/Migration/001_initial_setup.cs @@ -144,7 +144,7 @@ namespace NzbDrone.Core.Datastore.Migration .WithColumn("Items").AsString().NotNullable() .WithColumn("Language").AsInt32().Nullable(); - Execute.Sql("UPDATE Profiles SET Language = 1"); + Execute.Sql("UPDATE \"Profiles\" SET \"Language\" = 1"); Create.TableForModel("SceneMappings") .WithColumn("TvdbId").AsInt32() @@ -243,8 +243,8 @@ namespace NzbDrone.Core.Datastore.Migration Insert.IntoTable("DelayProfiles").Row(new { - EnableUsenet = 1, - EnableTorrent = 1, + EnableUsenet = true, + EnableTorrent = true, PreferredProtocol = 1, UsenetDelay = 0, TorrentDelay = 0, diff --git a/src/NzbDrone.Core/Datastore/Migration/108_update_schedule_interval.cs b/src/NzbDrone.Core/Datastore/Migration/108_update_schedule_interval.cs index 82f204b3e..8be302bbe 100644 --- a/src/NzbDrone.Core/Datastore/Migration/108_update_schedule_interval.cs +++ b/src/NzbDrone.Core/Datastore/Migration/108_update_schedule_interval.cs @@ -9,7 +9,7 @@ namespace NzbDrone.Core.Datastore.Migration protected override void MainDbUpgrade() { Alter.Table("ScheduledTasks").AlterColumn("Interval").AsDouble(); - Execute.Sql("UPDATE ScheduledTasks SET Interval=0.25 WHERE TypeName='NzbDrone.Core.Download.CheckForFinishedDownloadCommand'"); + Execute.Sql("UPDATE \"ScheduledTasks\" SET \"Interval\" = 0.25 WHERE \"TypeName\" = 'NzbDrone.Core.Download.CheckForFinishedDownloadCommand'"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/109_add_movie_formats_to_naming_config.cs b/src/NzbDrone.Core/Datastore/Migration/109_add_movie_formats_to_naming_config.cs index ca7f447a5..e20cb8939 100644 --- a/src/NzbDrone.Core/Datastore/Migration/109_add_movie_formats_to_naming_config.cs +++ b/src/NzbDrone.Core/Datastore/Migration/109_add_movie_formats_to_naming_config.cs @@ -20,7 +20,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand namingConfigCmd = conn.CreateCommand()) { namingConfigCmd.Transaction = tran; - namingConfigCmd.CommandText = @"SELECT * FROM NamingConfig LIMIT 1"; + namingConfigCmd.CommandText = @"SELECT * FROM ""NamingConfig"" LIMIT 1"; using (IDataReader namingConfigReader = namingConfigCmd.ExecuteReader()) { while (namingConfigReader.Read()) @@ -38,9 +38,9 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand updateCmd = conn.CreateCommand()) { - var text = string.Format("UPDATE NamingConfig " + - "SET StandardMovieFormat = '{0}', " + - "MovieFolderFormat = '{1}'", + var text = string.Format("UPDATE \"NamingConfig\" " + + "SET \"StandardMovieFormat\" = '{0}', " + + "\"MovieFolderFormat\" = '{1}'", standardMovieFormat, movieFolderFormat); diff --git a/src/NzbDrone.Core/Datastore/Migration/115_update_movie_sorttitle.cs b/src/NzbDrone.Core/Datastore/Migration/115_update_movie_sorttitle.cs index 593665455..8ae00b36b 100644 --- a/src/NzbDrone.Core/Datastore/Migration/115_update_movie_sorttitle.cs +++ b/src/NzbDrone.Core/Datastore/Migration/115_update_movie_sorttitle.cs @@ -18,7 +18,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"SELECT Id, Title FROM Movies"; + getSeriesCmd.CommandText = @"SELECT ""Id"", ""Title"" FROM ""Movies"""; using (IDataReader seriesReader = getSeriesCmd.ExecuteReader()) { while (seriesReader.Read()) @@ -31,7 +31,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand updateCmd = conn.CreateCommand()) { updateCmd.Transaction = tran; - updateCmd.CommandText = "UPDATE Movies SET SortTitle = ? WHERE Id = ?"; + updateCmd.CommandText = "UPDATE \"Movies\" SET \"SortTitle\" = ? WHERE \"Id\" = ?"; updateCmd.AddParameter(sortTitle); updateCmd.AddParameter(id); diff --git a/src/NzbDrone.Core/Datastore/Migration/116_update_movie_sorttitle_again.cs b/src/NzbDrone.Core/Datastore/Migration/116_update_movie_sorttitle_again.cs index 45666b1c2..e998afc41 100644 --- a/src/NzbDrone.Core/Datastore/Migration/116_update_movie_sorttitle_again.cs +++ b/src/NzbDrone.Core/Datastore/Migration/116_update_movie_sorttitle_again.cs @@ -17,7 +17,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"SELECT Id, Title FROM Movies"; + getSeriesCmd.CommandText = @"SELECT ""Id"", ""Title"" FROM ""Movies"""; using (IDataReader seriesReader = getSeriesCmd.ExecuteReader()) { while (seriesReader.Read()) @@ -30,7 +30,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand updateCmd = conn.CreateCommand()) { updateCmd.Transaction = tran; - updateCmd.CommandText = "UPDATE Movies SET SortTitle = ? WHERE Id = ?"; + updateCmd.CommandText = "UPDATE \"Movies\" SET \"SortTitle\" = ? WHERE \"Id\" = ?"; updateCmd.AddParameter(sortTitle); updateCmd.AddParameter(id); diff --git a/src/NzbDrone.Core/Datastore/Migration/117_update_movie_file.cs b/src/NzbDrone.Core/Datastore/Migration/117_update_movie_file.cs index f28ef6f29..bbcd501fc 100644 --- a/src/NzbDrone.Core/Datastore/Migration/117_update_movie_file.cs +++ b/src/NzbDrone.Core/Datastore/Migration/117_update_movie_file.cs @@ -19,7 +19,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"SELECT Id, RelativePath FROM MovieFiles"; + getSeriesCmd.CommandText = @"SELECT ""Id"", ""RelativePath"" FROM ""MovieFiles"""; using (IDataReader seriesReader = getSeriesCmd.ExecuteReader()) { while (seriesReader.Read()) @@ -39,7 +39,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand updateCmd = conn.CreateCommand()) { updateCmd.Transaction = tran; - updateCmd.CommandText = "UPDATE MovieFiles SET Edition = ? WHERE Id = ?"; + updateCmd.CommandText = "UPDATE \"MovieFiles\" SET \"Edition\" = ? WHERE \"Id\" = ?"; updateCmd.AddParameter(edition); updateCmd.AddParameter(id); diff --git a/src/NzbDrone.Core/Datastore/Migration/118_update_movie_slug.cs b/src/NzbDrone.Core/Datastore/Migration/118_update_movie_slug.cs index 4dbdee96b..adb1a7ed2 100644 --- a/src/NzbDrone.Core/Datastore/Migration/118_update_movie_slug.cs +++ b/src/NzbDrone.Core/Datastore/Migration/118_update_movie_slug.cs @@ -17,7 +17,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"SELECT Id, Title, Year, TmdbId FROM Movies"; + getSeriesCmd.CommandText = @"SELECT ""Id"", ""Title"", ""Year"", ""TmdbId"" FROM ""Movies"""; using (IDataReader seriesReader = getSeriesCmd.ExecuteReader()) { while (seriesReader.Read()) @@ -32,7 +32,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand updateCmd = conn.CreateCommand()) { updateCmd.Transaction = tran; - updateCmd.CommandText = "UPDATE Movies SET TitleSlug = ? WHERE Id = ?"; + updateCmd.CommandText = "UPDATE \"Movies\" SET \"TitleSlug\" = ? WHERE \"Id\" = ?"; updateCmd.AddParameter(titleSlug); updateCmd.AddParameter(id); diff --git a/src/NzbDrone.Core/Datastore/Migration/121_update_filedate_config.cs b/src/NzbDrone.Core/Datastore/Migration/121_update_filedate_config.cs index 8478360bd..ec9bf187a 100644 --- a/src/NzbDrone.Core/Datastore/Migration/121_update_filedate_config.cs +++ b/src/NzbDrone.Core/Datastore/Migration/121_update_filedate_config.cs @@ -19,7 +19,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"SELECT Id, Value FROM Config WHERE Key = 'filedate'"; + getSeriesCmd.CommandText = @"SELECT ""Id"", ""Value"" FROM ""Config"" WHERE ""Key"" = 'filedate'"; using (IDataReader seriesReader = getSeriesCmd.ExecuteReader()) { while (seriesReader.Read()) @@ -30,7 +30,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand updateCmd = conn.CreateCommand()) { updateCmd.Transaction = tran; - updateCmd.CommandText = "UPDATE Config SET Value = 'Release' WHERE Id = ?"; + updateCmd.CommandText = "UPDATE \"Config\" SET \"Value\" = 'Release' WHERE \"Id\" = ?"; updateCmd.AddParameter(id); updateCmd.ExecuteNonQuery(); diff --git a/src/NzbDrone.Core/Datastore/Migration/123_create_netimport_table.cs b/src/NzbDrone.Core/Datastore/Migration/123_create_netimport_table.cs index 91af60e36..aec46763d 100644 --- a/src/NzbDrone.Core/Datastore/Migration/123_create_netimport_table.cs +++ b/src/NzbDrone.Core/Datastore/Migration/123_create_netimport_table.cs @@ -16,9 +16,9 @@ namespace NzbDrone.Core.Datastore.Migration .WithColumn("Implementation").AsString() .WithColumn("ConfigContract").AsString().Nullable() .WithColumn("Settings").AsString().Nullable() - .WithColumn("EnableAuto").AsInt32() + .WithColumn("EnableAuto").AsBoolean() .WithColumn("RootFolderPath").AsString() - .WithColumn("ShouldMonitor").AsInt32() + .WithColumn("ShouldMonitor").AsBoolean() .WithColumn("ProfileId").AsInt32(); } } diff --git a/src/NzbDrone.Core/Datastore/Migration/125_fix_imdb_unique.cs b/src/NzbDrone.Core/Datastore/Migration/125_fix_imdb_unique.cs index fdbcdcd06..c79a18b5a 100644 --- a/src/NzbDrone.Core/Datastore/Migration/125_fix_imdb_unique.cs +++ b/src/NzbDrone.Core/Datastore/Migration/125_fix_imdb_unique.cs @@ -1,4 +1,4 @@ -using System.Data; +using System.Data; using FluentMigrator; using NzbDrone.Core.Datastore.Migration.Framework; @@ -17,7 +17,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"DROP INDEX 'IX_Movies_ImdbId'"; + getSeriesCmd.CommandText = @"DROP INDEX ""IX_Movies_ImdbId"""; getSeriesCmd.ExecuteNonQuery(); } diff --git a/src/NzbDrone.Core/Datastore/Migration/126_update_qualities_and_profiles.cs b/src/NzbDrone.Core/Datastore/Migration/126_update_qualities_and_profiles.cs index 70a3a231a..6194ec0fe 100644 --- a/src/NzbDrone.Core/Datastore/Migration/126_update_qualities_and_profiles.cs +++ b/src/NzbDrone.Core/Datastore/Migration/126_update_qualities_and_profiles.cs @@ -82,7 +82,7 @@ namespace NzbDrone.Core.Datastore.Migration using (var updateProfileCmd = _connection.CreateCommand()) { updateProfileCmd.Transaction = _transaction; - updateProfileCmd.CommandText = "UPDATE Profiles SET Name = ?, Cutoff = ?, Items = ?, Language = ? WHERE Id = ?"; + updateProfileCmd.CommandText = "UPDATE \"Profiles\" SET \"Name\" = ?, \"Cutoff\" = ?, \"Items\" = ?, \"Language\" = ? WHERE \"Id\" = ?"; updateProfileCmd.AddParameter(profile.Name); updateProfileCmd.AddParameter(profile.Cutoff); updateProfileCmd.AddParameter(profile.Items.ToJson()); @@ -187,7 +187,7 @@ namespace NzbDrone.Core.Datastore.Migration using (var getDefinitions = _connection.CreateCommand()) { getDefinitions.Transaction = _transaction; - getDefinitions.CommandText = @"SELECT Id, Quality FROM QualityDefinitions"; + getDefinitions.CommandText = @"SELECT ""Id"", ""Quality"" FROM ""QualityDefinitions"""; using (var definitionsReader = getDefinitions.ExecuteReader()) { @@ -225,7 +225,7 @@ namespace NzbDrone.Core.Datastore.Migration using (var getProfilesCmd = _connection.CreateCommand()) { getProfilesCmd.Transaction = _transaction; - getProfilesCmd.CommandText = @"SELECT Id, Name, Cutoff, Items, Language FROM Profiles"; + getProfilesCmd.CommandText = @"SELECT ""Id"", ""Name"", ""Cutoff"", ""Items"", ""Language"" FROM ""Profiles"""; using (var profileReader = getProfilesCmd.ExecuteReader()) { diff --git a/src/NzbDrone.Core/Datastore/Migration/132_rename_torrent_downloadstation.cs b/src/NzbDrone.Core/Datastore/Migration/132_rename_torrent_downloadstation.cs index f17c9610c..661546ee6 100644 --- a/src/NzbDrone.Core/Datastore/Migration/132_rename_torrent_downloadstation.cs +++ b/src/NzbDrone.Core/Datastore/Migration/132_rename_torrent_downloadstation.cs @@ -8,7 +8,7 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Execute.Sql("UPDATE DownloadClients SET Implementation = 'TorrentDownloadStation' WHERE Implementation = 'DownloadStation';"); + Execute.Sql("UPDATE \"DownloadClients\" SET \"Implementation\" = 'TorrentDownloadStation' WHERE \"Implementation\" = 'DownloadStation';"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/133_add_minimumavailability.cs b/src/NzbDrone.Core/Datastore/Migration/133_add_minimumavailability.cs index 89c317472..ddcfadf50 100644 --- a/src/NzbDrone.Core/Datastore/Migration/133_add_minimumavailability.cs +++ b/src/NzbDrone.Core/Datastore/Migration/133_add_minimumavailability.cs @@ -13,12 +13,12 @@ namespace NzbDrone.Core.Datastore.Migration { if (!Schema.Schema("dbo").Table("NetImport").Column("MinimumAvailability").Exists()) { - Alter.Table("NetImport").AddColumn("MinimumAvailability").AsInt32().WithDefaultValue(MovieStatusType.Released); + Alter.Table("NetImport").AddColumn("MinimumAvailability").AsInt32().WithDefaultValue((int)MovieStatusType.Released); } if (!Schema.Schema("dbo").Table("Movies").Column("MinimumAvailability").Exists()) { - Alter.Table("Movies").AddColumn("MinimumAvailability").AsInt32().WithDefaultValue(MovieStatusType.Released); + Alter.Table("Movies").AddColumn("MinimumAvailability").AsInt32().WithDefaultValue((int)MovieStatusType.Released); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/137_add_import_exclusions_table.cs b/src/NzbDrone.Core/Datastore/Migration/137_add_import_exclusions_table.cs index 25b68583a..fe527f04b 100644 --- a/src/NzbDrone.Core/Datastore/Migration/137_add_import_exclusions_table.cs +++ b/src/NzbDrone.Core/Datastore/Migration/137_add_import_exclusions_table.cs @@ -29,7 +29,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"SELECT Key, Value FROM Config WHERE Key = 'importexclusions'"; + getSeriesCmd.CommandText = @"SELECT ""Key"", ""Value"" FROM ""Config"" WHERE ""Key"" = 'importexclusions'"; TextInfo textInfo = new CultureInfo("en-US", false).TextInfo; using (IDataReader seriesReader = getSeriesCmd.ExecuteReader()) { @@ -48,7 +48,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand updateCmd = conn.CreateCommand()) { updateCmd.Transaction = tran; - updateCmd.CommandText = "INSERT INTO ImportExclusions (tmdbid, MovieTitle) VALUES " + string.Join(", ", importExclusions); + updateCmd.CommandText = "INSERT INTO \"ImportExclusions\" (tmdbid, MovieTitle) VALUES " + string.Join(", ", importExclusions); updateCmd.ExecuteNonQuery(); } diff --git a/src/NzbDrone.Core/Datastore/Migration/139_fix_indexer_baseurl.cs b/src/NzbDrone.Core/Datastore/Migration/139_fix_indexer_baseurl.cs index 30ead987c..1f24b03fe 100644 --- a/src/NzbDrone.Core/Datastore/Migration/139_fix_indexer_baseurl.cs +++ b/src/NzbDrone.Core/Datastore/Migration/139_fix_indexer_baseurl.cs @@ -20,7 +20,7 @@ namespace NzbDrone.Core.Datastore.Migration using (var cmd = conn.CreateCommand()) { cmd.Transaction = tran; - cmd.CommandText = "SELECT Id, Settings FROM Indexers WHERE ConfigContract IN ('NewznabSettings', 'TorznabSettings', 'IPTorrentsSettings', 'OmgwtfnzbsSettings')"; + cmd.CommandText = "SELECT \"Id\", \"Settings\" FROM \"Indexers\" WHERE \"ConfigContract\" IN ('NewznabSettings', 'TorznabSettings', 'IPTorrentsSettings', 'OmgwtfnzbsSettings')"; using (var reader = cmd.ExecuteReader()) { @@ -42,7 +42,7 @@ namespace NzbDrone.Core.Datastore.Migration using (var updateCmd = conn.CreateCommand()) { updateCmd.Transaction = tran; - updateCmd.CommandText = "UPDATE Indexers SET Settings = ? WHERE Id = ?"; + updateCmd.CommandText = "UPDATE \"Indexers\" SET \"Settings\" = ? WHERE \"Id\" = ?"; updateCmd.AddParameter(settings); updateCmd.AddParameter(id); updateCmd.ExecuteNonQuery(); diff --git a/src/NzbDrone.Core/Datastore/Migration/141_fix_duplicate_alt_titles.cs b/src/NzbDrone.Core/Datastore/Migration/141_fix_duplicate_alt_titles.cs index dd09aa4a6..e58cdff78 100644 --- a/src/NzbDrone.Core/Datastore/Migration/141_fix_duplicate_alt_titles.cs +++ b/src/NzbDrone.Core/Datastore/Migration/141_fix_duplicate_alt_titles.cs @@ -1,4 +1,4 @@ -using System.Data; +using System.Data; using FluentMigrator; using NzbDrone.Core.Datastore.Migration.Framework; @@ -9,16 +9,16 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Execute.WithConnection(RenameUrlToBaseUrl); + Execute.WithConnection(RemoveDuplicateAlternateTitles); Alter.Table("AlternativeTitles").AlterColumn("CleanTitle").AsString().Unique(); } - private void RenameUrlToBaseUrl(IDbConnection conn, IDbTransaction tran) + private void RemoveDuplicateAlternateTitles(IDbConnection conn, IDbTransaction tran) { using (var cmd = conn.CreateCommand()) { cmd.Transaction = tran; - cmd.CommandText = "DELETE FROM AlternativeTitles WHERE rowid NOT IN ( SELECT MIN(rowid) FROM AlternativeTitles GROUP BY CleanTitle )"; + cmd.CommandText = "DELETE FROM \"AlternativeTitles\" WHERE \"Id\" NOT IN (Select Min(\"Id\") From \"AlternativeTitles\" Group By \"CleanTitle\")"; cmd.ExecuteNonQuery(); } diff --git a/src/NzbDrone.Core/Datastore/Migration/145_banner_to_fanart.cs b/src/NzbDrone.Core/Datastore/Migration/145_banner_to_fanart.cs index 7ad227539..535668e2f 100644 --- a/src/NzbDrone.Core/Datastore/Migration/145_banner_to_fanart.cs +++ b/src/NzbDrone.Core/Datastore/Migration/145_banner_to_fanart.cs @@ -8,10 +8,10 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Execute.Sql("UPDATE Movies SET Images = replace(Images, \'\"coverType\": \"banner\"\', \'\"coverType\": \"fanart\"\')"); + Execute.Sql("UPDATE \"Movies\" SET \"Images\" = replace(\"Images\", \'\"coverType\": \"banner\"\', \'\"coverType\": \"fanart\"\')"); // Remove Link for images to specific MovieFiles, Images are now related to the Movie object only - Execute.Sql("UPDATE MetadataFiles SET MovieFileId = null WHERE Type = 2"); + Execute.Sql("UPDATE \"MetadataFiles\" SET \"MovieFileId\" = null WHERE \"Type\" = 2"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/148_remove_extra_naming_config.cs b/src/NzbDrone.Core/Datastore/Migration/148_remove_extra_naming_config.cs index a5b41cb68..c34b2ce8a 100644 --- a/src/NzbDrone.Core/Datastore/Migration/148_remove_extra_naming_config.cs +++ b/src/NzbDrone.Core/Datastore/Migration/148_remove_extra_naming_config.cs @@ -9,7 +9,7 @@ namespace NzbDrone.Core.Datastore.Migration protected override void MainDbUpgrade() { // Remove all but 1 NamingConfig - Execute.Sql("DELETE FROM NamingConfig WHERE ID NOT IN(SELECT ID FROM NamingConfig LIMIT 1)"); + Execute.Sql("DELETE FROM \"NamingConfig\" WHERE \"Id\" NOT IN(SELECT \"Id\" FROM \"NamingConfig\" LIMIT 1)"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/149_convert_regex_required_tags.cs b/src/NzbDrone.Core/Datastore/Migration/149_convert_regex_required_tags.cs index 436ce949f..5f6259e25 100644 --- a/src/NzbDrone.Core/Datastore/Migration/149_convert_regex_required_tags.cs +++ b/src/NzbDrone.Core/Datastore/Migration/149_convert_regex_required_tags.cs @@ -82,7 +82,15 @@ namespace NzbDrone.Core.Datastore.Migration using (var updateProfileCmd = _connection.CreateCommand()) { updateProfileCmd.Transaction = _transaction; - updateProfileCmd.CommandText = "UPDATE CustomFormats SET Name = ?, FormatTags = ? WHERE Id = ?"; + if (_connection.GetType().FullName == "Npgsql.NpgsqlConnection") + { + updateProfileCmd.CommandText = "UPDATE \"CustomFormats\" SET \"Name\" = $1, \"FormatTags\" = $2 WHERE \"Id\" = $3"; + } + else + { + updateProfileCmd.CommandText = "UPDATE \"CustomFormats\" SET \"Name\" = ?, \"FormatTags\" = ? WHERE \"Id\" = ?"; + } + updateProfileCmd.AddParameter(profile.Name); updateProfileCmd.AddParameter(profile.FormatTags.ToJson()); updateProfileCmd.AddParameter(profile.Id); @@ -119,7 +127,7 @@ namespace NzbDrone.Core.Datastore.Migration using (var getProfilesCmd = _connection.CreateCommand()) { getProfilesCmd.Transaction = _transaction; - getProfilesCmd.CommandText = @"SELECT Id, Name, FormatTags FROM CustomFormats"; + getProfilesCmd.CommandText = @"SELECT ""Id"", ""Name"", ""FormatTags"" FROM ""CustomFormats"""; using (var profileReader = getProfilesCmd.ExecuteReader()) { diff --git a/src/NzbDrone.Core/Datastore/Migration/151_add_tags_to_net_import.cs b/src/NzbDrone.Core/Datastore/Migration/151_add_tags_to_net_import.cs index 69e42c536..0af3ab09d 100644 --- a/src/NzbDrone.Core/Datastore/Migration/151_add_tags_to_net_import.cs +++ b/src/NzbDrone.Core/Datastore/Migration/151_add_tags_to_net_import.cs @@ -11,7 +11,7 @@ namespace NzbDrone.Core.Datastore.Migration Alter.Table("NetImport") .AddColumn("Tags").AsString().Nullable(); - Execute.Sql("UPDATE NetImport SET Tags = '[]'"); + Execute.Sql("UPDATE \"NetImport\" SET \"Tags\" = '[]'"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/153_indexer_client_status_search_changes.cs b/src/NzbDrone.Core/Datastore/Migration/153_indexer_client_status_search_changes.cs index 74cb33345..c03aa6ca0 100644 --- a/src/NzbDrone.Core/Datastore/Migration/153_indexer_client_status_search_changes.cs +++ b/src/NzbDrone.Core/Datastore/Migration/153_indexer_client_status_search_changes.cs @@ -21,7 +21,7 @@ namespace NzbDrone.Core.Datastore.Migration Rename.Column("EnableSearch").OnTable("Indexers").To("EnableAutomaticSearch"); Alter.Table("Indexers").AddColumn("EnableInteractiveSearch").AsBoolean().Nullable(); - Execute.Sql("UPDATE Indexers SET EnableInteractiveSearch = EnableAutomaticSearch"); + Execute.Sql("UPDATE \"Indexers\" SET \"EnableInteractiveSearch\" = \"EnableAutomaticSearch\""); Alter.Table("Indexers").AlterColumn("EnableInteractiveSearch").AsBoolean().NotNullable(); diff --git a/src/NzbDrone.Core/Datastore/Migration/154_add_language_to_file_history_blacklist.cs b/src/NzbDrone.Core/Datastore/Migration/154_add_language_to_file_history_blacklist.cs index fda7fdaec..499d587d0 100644 --- a/src/NzbDrone.Core/Datastore/Migration/154_add_language_to_file_history_blacklist.cs +++ b/src/NzbDrone.Core/Datastore/Migration/154_add_language_to_file_history_blacklist.cs @@ -41,7 +41,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getProfileCmd = conn.CreateCommand()) { getProfileCmd.Transaction = tran; - getProfileCmd.CommandText = "SELECT Id, Language FROM Profiles"; + getProfileCmd.CommandText = "SELECT \"Id\", \"Language\" FROM \"Profiles\""; IDataReader profilesReader = getProfileCmd.ExecuteReader(); while (profilesReader.Read()) @@ -59,6 +59,8 @@ namespace NzbDrone.Core.Datastore.Migration profileLanguages[profileId] = movieLanguage; } + + profilesReader.Close(); } var movieLanguages = new Dictionary(); @@ -66,7 +68,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"SELECT Id, ProfileId FROM Movies"; + getSeriesCmd.CommandText = @"SELECT ""Id"", ""ProfileId"" FROM ""Movies"""; using (IDataReader moviesReader = getSeriesCmd.ExecuteReader()) { while (moviesReader.Read()) @@ -76,6 +78,8 @@ namespace NzbDrone.Core.Datastore.Migration movieLanguages[movieId] = profileLanguages.GetValueOrDefault(movieProfileId, Language.English.Id); } + + moviesReader.Close(); } } @@ -85,7 +89,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"SELECT Id, MovieId, SceneName, MediaInfo FROM MovieFiles"; + getSeriesCmd.CommandText = @"SELECT ""Id"", ""MovieId"", ""SceneName"", ""MediaInfo"" FROM ""MovieFiles"""; using (IDataReader movieFilesReader = getSeriesCmd.ExecuteReader()) { while (movieFilesReader.Read()) @@ -125,6 +129,8 @@ namespace NzbDrone.Core.Datastore.Migration movieFileLanguages[movieFileId] = languages; } + + movieFilesReader.Close(); } } @@ -133,7 +139,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"SELECT Id, SourceTitle, MovieId FROM History"; + getSeriesCmd.CommandText = @"SELECT ""Id"", ""SourceTitle"", ""MovieId"" FROM ""History"""; using (IDataReader historyReader = getSeriesCmd.ExecuteReader()) { while (historyReader.Read()) @@ -160,6 +166,8 @@ namespace NzbDrone.Core.Datastore.Migration historyLanguages[historyId] = languages; } + + historyReader.Close(); } } @@ -168,7 +176,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getSeriesCmd = conn.CreateCommand()) { getSeriesCmd.Transaction = tran; - getSeriesCmd.CommandText = @"SELECT Id, SourceTitle, MovieId FROM Blacklist"; + getSeriesCmd.CommandText = @"SELECT ""Id"", ""SourceTitle"", ""MovieId"" FROM ""Blacklist"""; using (IDataReader blacklistReader = getSeriesCmd.ExecuteReader()) { while (blacklistReader.Read()) @@ -190,6 +198,8 @@ namespace NzbDrone.Core.Datastore.Migration blacklistLanguages[blacklistId] = languages; } + + blacklistReader.Close(); } } @@ -202,7 +212,15 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand updateMovieFilesCmd = conn.CreateCommand()) { updateMovieFilesCmd.Transaction = tran; - updateMovieFilesCmd.CommandText = $"UPDATE MovieFiles SET Languages = ? WHERE Id IN ({movieFileIds})"; + if (conn.GetType().FullName == "Npgsql.NpgsqlConnection") + { + updateMovieFilesCmd.CommandText = $"UPDATE \"MovieFiles\" SET \"Languages\" = $1 WHERE \"Id\" IN ({movieFileIds})"; + } + else + { + updateMovieFilesCmd.CommandText = $"UPDATE \"MovieFiles\" SET \"Languages\" = ? WHERE \"Id\" IN ({movieFileIds})"; + } + var param = updateMovieFilesCmd.CreateParameter(); languageConverter.SetValue(param, languages); updateMovieFilesCmd.Parameters.Add(param); @@ -220,7 +238,15 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand updateHistoryCmd = conn.CreateCommand()) { updateHistoryCmd.Transaction = tran; - updateHistoryCmd.CommandText = $"UPDATE History SET Languages = ? WHERE Id IN ({historyIds})"; + if (conn.GetType().FullName == "Npgsql.NpgsqlConnection") + { + updateHistoryCmd.CommandText = $"UPDATE \"History\" SET \"Languages\" = $1 WHERE \"Id\" IN ({historyIds})"; + } + else + { + updateHistoryCmd.CommandText = $"UPDATE \"History\" SET \"Languages\" = ? WHERE \"Id\" IN ({historyIds})"; + } + var param = updateHistoryCmd.CreateParameter(); languageConverter.SetValue(param, languages); updateHistoryCmd.Parameters.Add(param); @@ -238,7 +264,15 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand updateBlacklistCmd = conn.CreateCommand()) { updateBlacklistCmd.Transaction = tran; - updateBlacklistCmd.CommandText = $"UPDATE Blacklist SET Languages = ? WHERE Id IN ({blacklistIds})"; + if (conn.GetType().FullName == "Npgsql.NpgsqlConnection") + { + updateBlacklistCmd.CommandText = $"UPDATE \"Blacklist\" SET \"Languages\" = $1 WHERE \"Id\" IN ({blacklistIds})"; + } + else + { + updateBlacklistCmd.CommandText = $"UPDATE \"Blacklist\" SET \"Languages\" = ? WHERE \"Id\" IN ({blacklistIds})"; + } + var param = updateBlacklistCmd.CreateParameter(); languageConverter.SetValue(param, languages); updateBlacklistCmd.Parameters.Add(param); diff --git a/src/NzbDrone.Core/Datastore/Migration/155_add_update_allowed_quality_profile.cs b/src/NzbDrone.Core/Datastore/Migration/155_add_update_allowed_quality_profile.cs index 066e234bd..f3af4c6bd 100644 --- a/src/NzbDrone.Core/Datastore/Migration/155_add_update_allowed_quality_profile.cs +++ b/src/NzbDrone.Core/Datastore/Migration/155_add_update_allowed_quality_profile.cs @@ -8,7 +8,7 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Alter.Table("Profiles").AddColumn("UpgradeAllowed").AsInt32().Nullable(); + Alter.Table("Profiles").AddColumn("UpgradeAllowed").AsBoolean().Nullable(); // Set upgrade allowed for existing profiles (default will be false for new profiles) Update.Table("Profiles").Set(new { UpgradeAllowed = true }).AllRows(); diff --git a/src/NzbDrone.Core/Datastore/Migration/156_add_download_client_priority.cs b/src/NzbDrone.Core/Datastore/Migration/156_add_download_client_priority.cs index 17533029e..3428406eb 100644 --- a/src/NzbDrone.Core/Datastore/Migration/156_add_download_client_priority.cs +++ b/src/NzbDrone.Core/Datastore/Migration/156_add_download_client_priority.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Data; +using System.Linq; +using Dapper; using FluentMigrator; using NzbDrone.Core.Datastore.Migration.Framework; @@ -22,37 +24,46 @@ namespace NzbDrone.Core.Datastore.Migration private void InitPriorityForBackwardCompatibility(IDbConnection conn, IDbTransaction tran) { - using (var cmd = conn.CreateCommand()) + var downloadClients = conn.Query($"SELECT \"Id\", \"Implementation\" FROM \"DownloadClients\" WHERE \"Enable\""); + + if (!downloadClients.Any()) { - cmd.Transaction = tran; - cmd.CommandText = "SELECT Id, Implementation FROM DownloadClients WHERE Enable = 1"; + return; + } + + var nextUsenet = 1; + var nextTorrent = 1; - using (var reader = cmd.ExecuteReader()) + foreach (var downloadClient in downloadClients) + { + var isUsenet = _usenetImplementations.Contains(downloadClient.Implementation); + using (var updateCmd = conn.CreateCommand()) { - int nextUsenet = 1; - int nextTorrent = 1; - while (reader.Read()) + updateCmd.Transaction = tran; + if (conn.GetType().FullName == "Npgsql.NpgsqlConnection") { - var id = reader.GetInt32(0); - var implName = reader.GetString(1); - - var isUsenet = _usenetImplementations.Contains(implName); + updateCmd.CommandText = "UPDATE \"DownloadClients\" SET \"Priority\" = $1 WHERE \"Id\" = $2"; + } + else + { + updateCmd.CommandText = "UPDATE \"DownloadClients\" SET \"Priority\" = ? WHERE \"Id\" = ?"; + } - using (var updateCmd = conn.CreateCommand()) - { - updateCmd.Transaction = tran; - updateCmd.CommandText = "UPDATE DownloadClients SET Priority = ? WHERE Id = ?"; - updateCmd.AddParameter(isUsenet ? nextUsenet++ : nextTorrent++); - updateCmd.AddParameter(id); + updateCmd.AddParameter(isUsenet ? nextUsenet++ : nextTorrent++); + updateCmd.AddParameter(downloadClient.Id); - updateCmd.ExecuteNonQuery(); - } - } + updateCmd.ExecuteNonQuery(); } } } } + public class DownloadClients156 + { + public int Id { get; set; } + public string Implementation { get; set; } + } + public class DelugeSettings156 { public string Host { get; set; } diff --git a/src/NzbDrone.Core/Datastore/Migration/159_add_webrip_qualities.cs b/src/NzbDrone.Core/Datastore/Migration/159_add_webrip_qualities.cs index fc5f120e7..277fd99f3 100644 --- a/src/NzbDrone.Core/Datastore/Migration/159_add_webrip_qualities.cs +++ b/src/NzbDrone.Core/Datastore/Migration/159_add_webrip_qualities.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Data; using System.Linq; using FluentMigrator; @@ -76,8 +76,16 @@ namespace NzbDrone.Core.Datastore.Migration using (var updateProfileCmd = _connection.CreateCommand()) { updateProfileCmd.Transaction = _transaction; - updateProfileCmd.CommandText = - "UPDATE Profiles SET Name = ?, Cutoff = ?, Items = ? WHERE Id = ?"; + + if (_connection.GetType().FullName == "Npgsql.NpgsqlConnection") + { + updateProfileCmd.CommandText = "UPDATE \"Profiles\" SET \"Name\" = $1, \"Cutoff\" = $2, \"Items\" = $3 WHERE \"Id\" = $4"; + } + else + { + updateProfileCmd.CommandText = "UPDATE \"Profiles\" SET \"Name\" = ?, \"Cutoff\" = ?, \"Items\" = ? WHERE \"Id\" = ?"; + } + updateProfileCmd.AddParameter(profile.Name); updateProfileCmd.AddParameter(profile.Cutoff); updateProfileCmd.AddParameter(profile.Items.ToJson()); @@ -219,7 +227,7 @@ namespace NzbDrone.Core.Datastore.Migration using (var getProfilesCmd = _connection.CreateCommand()) { getProfilesCmd.Transaction = _transaction; - getProfilesCmd.CommandText = @"SELECT Id, Name, Cutoff, Items FROM Profiles"; + getProfilesCmd.CommandText = @"SELECT ""Id"", ""Name"", ""Cutoff"", ""Items"" FROM ""Profiles"""; using (var profileReader = getProfilesCmd.ExecuteReader()) { diff --git a/src/NzbDrone.Core/Datastore/Migration/160_health_issue_notification.cs b/src/NzbDrone.Core/Datastore/Migration/160_health_issue_notification.cs index d41a8bd47..f26c66f88 100644 --- a/src/NzbDrone.Core/Datastore/Migration/160_health_issue_notification.cs +++ b/src/NzbDrone.Core/Datastore/Migration/160_health_issue_notification.cs @@ -8,8 +8,8 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Alter.Table("Notifications").AddColumn("OnHealthIssue").AsBoolean().WithDefaultValue(0); - Alter.Table("Notifications").AddColumn("IncludeHealthWarnings").AsBoolean().WithDefaultValue(0); + Alter.Table("Notifications").AddColumn("OnHealthIssue").AsBoolean().WithDefaultValue(false); + Alter.Table("Notifications").AddColumn("IncludeHealthWarnings").AsBoolean().WithDefaultValue(false); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/165_remove_custom_formats_from_quality_model.cs b/src/NzbDrone.Core/Datastore/Migration/165_remove_custom_formats_from_quality_model.cs index ee80c6dc8..236aac66e 100644 --- a/src/NzbDrone.Core/Datastore/Migration/165_remove_custom_formats_from_quality_model.cs +++ b/src/NzbDrone.Core/Datastore/Migration/165_remove_custom_formats_from_quality_model.cs @@ -39,7 +39,7 @@ namespace NzbDrone.Core.Datastore.Migration { SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter()); SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter()); - var rows = conn.Query("SELECT Id, ParsedMovieInfo from PendingReleases"); + var rows = conn.Query("SELECT \"Id\", \"ParsedMovieInfo\" from \"PendingReleases\""); var newRows = new List(); @@ -76,26 +76,26 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var sql = $"UPDATE PendingReleases SET ParsedMovieInfo = @ParsedMovieInfo WHERE Id = @Id"; + var sql = $"UPDATE \"PendingReleases\" SET \"ParsedMovieInfo\" = @ParsedMovieInfo WHERE \"Id\" = @Id"; conn.Execute(sql, newRows, transaction: tran); } private void RemoveCustomFormatFromQuality(IDbConnection conn, IDbTransaction tran, string table) { - var rows = conn.Query($"SELECT Id, Quality from {table}"); + var rows = conn.Query($"SELECT \"Id\", \"Quality\" from \"{table}\""); - var sql = $"UPDATE {table} SET Quality = @Quality WHERE Id = @Id"; + var sql = $"UPDATE \"{table}\" SET \"Quality\" = @Quality WHERE \"Id\" = @Id"; conn.Execute(sql, rows, transaction: tran); } private void AddIndexerFlagsToBlacklist(IDbConnection conn, IDbTransaction tran) { - var blacklists = conn.Query("SELECT Blacklist.Id, Blacklist.TorrentInfoHash, History.Data " + - "FROM Blacklist " + - "JOIN History ON Blacklist.MovieId = History.MovieId " + - "WHERE History.EventType = 1"); + var blacklists = conn.Query("SELECT \"Blacklist\".\"Id\", \"Blacklist\".\"TorrentInfoHash\", \"History\".\"Data\" " + + "FROM \"Blacklist\" " + + "JOIN \"History\" ON \"Blacklist\".\"MovieId\" = \"History\".\"MovieId\" " + + "WHERE \"History\".\"EventType\" = 1"); var toUpdate = new List(); @@ -117,16 +117,16 @@ namespace NzbDrone.Core.Datastore.Migration } } - var updateSql = "UPDATE Blacklist SET IndexerFlags = @IndexerFlags WHERE Id = @Id"; + var updateSql = "UPDATE \"Blacklist\" SET \"IndexerFlags\" = @IndexerFlags WHERE \"Id\" = @Id"; conn.Execute(updateSql, toUpdate, transaction: tran); } private void AddIndexerFlagsToMovieFiles(IDbConnection conn, IDbTransaction tran) { - var movieFiles = conn.Query("SELECT MovieFiles.Id, MovieFiles.SceneName, History.SourceTitle, History.Data " + - "FROM MovieFiles " + - "JOIN History ON MovieFiles.MovieId = History.MovieId " + - "WHERE History.EventType = 1"); + var movieFiles = conn.Query("SELECT \"MovieFiles\".\"Id\", \"MovieFiles\".\"SceneName\", \"History\".\"SourceTitle\", \"History\".\"Data\" " + + "FROM \"MovieFiles\" " + + "JOIN \"History\" ON \"MovieFiles\".\"MovieId\" = \"History\".\"MovieId\" " + + "WHERE \"History\".\"EventType\" = 1"); var toUpdate = new List(); @@ -148,7 +148,7 @@ namespace NzbDrone.Core.Datastore.Migration } } - var updateSql = "UPDATE MovieFiles SET IndexerFlags = @IndexerFlags WHERE Id = @Id"; + var updateSql = "UPDATE \"MovieFiles\" SET \"IndexerFlags\" = @IndexerFlags WHERE \"Id\" = @Id"; conn.Execute(updateSql, toUpdate, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/166_fix_tmdb_list_config.cs b/src/NzbDrone.Core/Datastore/Migration/166_fix_tmdb_list_config.cs index 591d9196b..aa0b3387e 100644 --- a/src/NzbDrone.Core/Datastore/Migration/166_fix_tmdb_list_config.cs +++ b/src/NzbDrone.Core/Datastore/Migration/166_fix_tmdb_list_config.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Core.Datastore.Migration private void RenameTMDbListType(IDbConnection conn, IDbTransaction tran) { - var rows = conn.Query($"SELECT Id, Implementation, ConfigContract, Settings FROM NetImport WHERE Implementation = 'TMDbPopularImport'"); + var rows = conn.Query($"SELECT \"Id\", \"Implementation\", \"ConfigContract\", \"Settings\" FROM \"NetImport\" WHERE \"Implementation\" = 'TMDbPopularImport'"); var corrected = new List(); @@ -71,13 +71,13 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var updateSql = "UPDATE NetImport SET Settings = @Settings WHERE Id = @Id"; + var updateSql = "UPDATE \"NetImport\" SET \"Settings\" = @Settings WHERE \"Id\" = @Id"; conn.Execute(updateSql, corrected, transaction: tran); } private void RenameTraktListType(IDbConnection conn, IDbTransaction tran) { - var rows = conn.Query($"SELECT Id, Implementation, ConfigContract, Settings FROM NetImport WHERE Implementation = 'TraktImport'"); + var rows = conn.Query($"SELECT \"Id\", \"Implementation\", \"ConfigContract\", \"Settings\" FROM \"NetImport\" WHERE \"Implementation\" = 'TraktImport'"); var corrected = new List(); @@ -112,13 +112,13 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var updateSql = "UPDATE NetImport SET Settings = @Settings WHERE Id = @Id"; + var updateSql = "UPDATE \"NetImport\" SET \"Settings\" = @Settings WHERE \"Id\" = @Id"; conn.Execute(updateSql, corrected, transaction: tran); } private void FixConfig(IDbConnection conn, IDbTransaction tran) { - var rows = conn.Query($"SELECT Id, Implementation, ConfigContract, Settings FROM NetImport WHERE Implementation = 'TMDbImport'"); + var rows = conn.Query($"SELECT \"Id\", \"Implementation\", \"ConfigContract\", \"Settings\" FROM \"NetImport\" WHERE \"Implementation\" = 'TMDbImport'"); var corrected = new List(); @@ -167,7 +167,7 @@ namespace NzbDrone.Core.Datastore.Migration } } - var updateSql = "UPDATE NetImport SET Implementation = @Implementation, ConfigContract = @ConfigContract, Settings = @Settings WHERE Id = @Id"; + var updateSql = "UPDATE \"NetImport\" SET \"Implementation\" = @Implementation, \"ConfigContract\" = @ConfigContract, \"Settings\" = @Settings WHERE \"Id\" = @Id"; conn.Execute(updateSql, corrected, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/167_remove_movie_pathstate.cs b/src/NzbDrone.Core/Datastore/Migration/167_remove_movie_pathstate.cs index a3f191b48..08532f410 100644 --- a/src/NzbDrone.Core/Datastore/Migration/167_remove_movie_pathstate.cs +++ b/src/NzbDrone.Core/Datastore/Migration/167_remove_movie_pathstate.cs @@ -10,7 +10,7 @@ namespace NzbDrone.Core.Datastore.Migration { Delete.Column("PathState").FromTable("Movies"); - Execute.Sql("DELETE FROM Config WHERE [KEY] IN ('pathsdefaultstatic')"); + Execute.Sql("DELETE FROM \"Config\" WHERE \"Key\" IN ('pathsdefaultstatic')"); Alter.Table("MovieFiles").AddColumn("OriginalFilePath").AsString().Nullable(); diff --git a/src/NzbDrone.Core/Datastore/Migration/168_custom_format_rework.cs b/src/NzbDrone.Core/Datastore/Migration/168_custom_format_rework.cs index a91d85202..de1b12c8b 100644 --- a/src/NzbDrone.Core/Datastore/Migration/168_custom_format_rework.cs +++ b/src/NzbDrone.Core/Datastore/Migration/168_custom_format_rework.cs @@ -32,7 +32,7 @@ namespace NzbDrone.Core.Datastore.Migration private void UpdateCustomFormats(IDbConnection conn, IDbTransaction tran) { - var existing = conn.Query("SELECT Id, Name, FormatTags FROM CustomFormats"); + var existing = conn.Query("SELECT \"Id\", \"Name\", \"FormatTags\" FROM \"CustomFormats\""); var updated = new List(); @@ -66,7 +66,7 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var updateSql = "UPDATE CustomFormats SET Specifications = @Specifications WHERE Id = @Id"; + var updateSql = "UPDATE \"CustomFormats\" SET \"Specifications\" = @Specifications WHERE \"Id\" = @Id"; conn.Execute(updateSql, updated, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/169_custom_format_scores.cs b/src/NzbDrone.Core/Datastore/Migration/169_custom_format_scores.cs index adcc6e6e4..05332d905 100644 --- a/src/NzbDrone.Core/Datastore/Migration/169_custom_format_scores.cs +++ b/src/NzbDrone.Core/Datastore/Migration/169_custom_format_scores.cs @@ -21,7 +21,7 @@ namespace NzbDrone.Core.Datastore.Migration Delete.Column("FormatCutoff").FromTable("Profiles"); - Alter.Table("CustomFormats").AddColumn("IncludeCustomFormatWhenRenaming").AsBoolean().WithDefaultValue(0); + Alter.Table("CustomFormats").AddColumn("IncludeCustomFormatWhenRenaming").AsBoolean().WithDefaultValue(false); } private void MigrateOrderToScores(IDbConnection conn, IDbTransaction tran) @@ -29,7 +29,7 @@ namespace NzbDrone.Core.Datastore.Migration SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter>()); SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter>()); - var rows = conn.Query("SELECT Id, FormatCutoff, FormatItems from Profiles", transaction: tran); + var rows = conn.Query("SELECT \"Id\", \"FormatCutoff\", \"FormatItems\" from \"Profiles\"", transaction: tran); var newRows = new List(); foreach (var row in rows) @@ -125,7 +125,7 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var sql = $"UPDATE Profiles SET MinFormatScore = @MinFormatScore, CutoffFormatScore = @CutoffFormatScore, FormatItems = @FormatItems WHERE Id = @Id"; + var sql = $"UPDATE \"Profiles\" SET \"MinFormatScore\" = @MinFormatScore, \"CutoffFormatScore\" = @CutoffFormatScore, \"FormatItems\" = @FormatItems WHERE \"Id\" = @Id"; conn.Execute(sql, newRows, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/170_fix_trakt_list_config.cs b/src/NzbDrone.Core/Datastore/Migration/170_fix_trakt_list_config.cs index e000a8209..267f80840 100644 --- a/src/NzbDrone.Core/Datastore/Migration/170_fix_trakt_list_config.cs +++ b/src/NzbDrone.Core/Datastore/Migration/170_fix_trakt_list_config.cs @@ -33,12 +33,12 @@ namespace NzbDrone.Core.Datastore.Migration { Execute.WithConnection(FixTraktConfig); Execute.WithConnection(RenameRadarrListType); - Execute.Sql("DELETE FROM Config WHERE[KEY] IN ('TraktAuthToken', 'TraktRefreshToken', 'TraktTokenExpiry', 'NewTraktAuthToken', 'NewTraktRefreshToken', 'NewTraktTokenExpiry')"); + Execute.Sql("DELETE FROM \"Config\" WHERE \"Key\" IN ('TraktAuthToken', 'TraktRefreshToken', 'TraktTokenExpiry', 'NewTraktAuthToken', 'NewTraktRefreshToken', 'NewTraktTokenExpiry')"); } private void RenameRadarrListType(IDbConnection conn, IDbTransaction tran) { - var rows = conn.Query($"SELECT Id, Implementation, ConfigContract, Settings FROM NetImport WHERE Implementation = 'RadarrLists'"); + var rows = conn.Query($"SELECT \"Id\", \"Implementation\", \"ConfigContract\", \"Settings\" FROM \"NetImport\" WHERE \"Implementation\" = 'RadarrLists'"); var corrected = new List(); @@ -52,13 +52,13 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var updateSql = "UPDATE NetImport SET Implementation = @Implementation, ConfigContract = @ConfigContract WHERE Id = @Id"; + var updateSql = "UPDATE \"NetImport\" SET \"Implementation\" = @Implementation, \"ConfigContract\" = @ConfigContract WHERE \"Id\" = @Id"; conn.Execute(updateSql, corrected, transaction: tran); } private void FixTraktConfig(IDbConnection conn, IDbTransaction tran) { - var rows = conn.Query($"SELECT Id, Implementation, ConfigContract, Settings FROM NetImport WHERE Implementation = 'TraktImport'"); + var rows = conn.Query($"SELECT \"Id\", \"Implementation\", \"ConfigContract\", \"Settings\" FROM \"NetImport\" WHERE \"Implementation\" = 'TraktImport'"); var corrected = new List(); @@ -158,7 +158,7 @@ namespace NzbDrone.Core.Datastore.Migration Console.WriteLine(corrected.ToJson()); - var updateSql = "UPDATE NetImport SET Implementation = @Implementation, ConfigContract = @ConfigContract, Settings = @Settings WHERE Id = @Id"; + var updateSql = "UPDATE \"NetImport\" SET \"Implementation\" = @Implementation, \"ConfigContract\" = @ConfigContract, \"Settings\" = @Settings WHERE \"Id\" = @Id"; conn.Execute(updateSql, corrected, transaction: tran); } } diff --git a/src/NzbDrone.Core/Datastore/Migration/171_quality_definition_preferred_size.cs b/src/NzbDrone.Core/Datastore/Migration/171_quality_definition_preferred_size.cs index f9ac4b7aa..5f3afe280 100644 --- a/src/NzbDrone.Core/Datastore/Migration/171_quality_definition_preferred_size.cs +++ b/src/NzbDrone.Core/Datastore/Migration/171_quality_definition_preferred_size.cs @@ -18,7 +18,7 @@ namespace NzbDrone.Core.Datastore.Migration private void UpdateQualityDefinitions(IDbConnection conn, IDbTransaction tran) { - var existing = conn.Query("SELECT Id, MaxSize FROM QualityDefinitions"); + var existing = conn.Query("SELECT \"Id\", \"MaxSize\" FROM \"QualityDefinitions\""); var updated = new List(); @@ -39,7 +39,7 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var updateSql = "UPDATE QualityDefinitions SET PreferredSize = @PreferredSize WHERE Id = @Id"; + var updateSql = "UPDATE \"QualityDefinitions\" SET \"PreferredSize\" = @PreferredSize WHERE \"Id\" = @Id"; conn.Execute(updateSql, updated, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/172_add_download_history.cs b/src/NzbDrone.Core/Datastore/Migration/172_add_download_history.cs index def537015..c1c21240e 100644 --- a/src/NzbDrone.Core/Datastore/Migration/172_add_download_history.cs +++ b/src/NzbDrone.Core/Datastore/Migration/172_add_download_history.cs @@ -28,7 +28,7 @@ namespace NzbDrone.Core.Datastore.Migration Create.Index().OnTable("DownloadHistory").OnColumn("MovieId"); Create.Index().OnTable("DownloadHistory").OnColumn("DownloadId"); - Execute.WithConnection(InitialImportedDownloadHistory); + IfDatabase("sqlite").Execute.WithConnection(InitialImportedDownloadHistory); } private static readonly Dictionary EventTypeMap = new Dictionary() @@ -44,7 +44,7 @@ namespace NzbDrone.Core.Datastore.Migration using (var cmd = conn.CreateCommand()) { cmd.Transaction = tran; - cmd.CommandText = "SELECT MovieId, DownloadId, EventType, SourceTitle, Date, Data FROM History WHERE DownloadId IS NOT NULL AND EventType IN (1, 3, 4, 9) GROUP BY EventType, DownloadId"; + cmd.CommandText = "SELECT \"MovieId\", \"DownloadId\", \"EventType\", \"SourceTitle\", \"Date\", \"Data\" FROM \"History\" WHERE \"DownloadId\" IS NOT NULL AND \"EventType\" IN (1, 3, 4, 9) GROUP BY \"EventType\", \"DownloadId\""; using (var reader = cmd.ExecuteReader()) { @@ -75,7 +75,15 @@ namespace NzbDrone.Core.Datastore.Migration using (var updateCmd = conn.CreateCommand()) { updateCmd.Transaction = tran; - updateCmd.CommandText = @"INSERT INTO DownloadHistory (EventType, MovieId, DownloadId, SourceTitle, Date, Protocol, Data) VALUES (?, ?, ?, ?, ?, ?, ?)"; + if (conn.GetType().FullName == "Npgsql.NpgsqlConnection") + { + updateCmd.CommandText = @"INSERT INTO ""DownloadHistory"" (""EventType"", ""MovieId"", ""DownloadId"", ""SourceTitle"", ""Date"", ""Protocol"", ""Data"") VALUES ($1, $2, $3, $4, $5, $6, $7)"; + } + else + { + updateCmd.CommandText = @"INSERT INTO ""DownloadHistory"" (""EventType"", ""MovieId"", ""DownloadId"", ""SourceTitle"", ""Date"", ""Protocol"", ""Data"") VALUES (?, ?, ?, ?, ?, ?, ?)"; + } + updateCmd.AddParameter(downloadHistoryEventType); updateCmd.AddParameter(movieId); updateCmd.AddParameter(downloadId); diff --git a/src/NzbDrone.Core/Datastore/Migration/174_email_multiple_addresses.cs b/src/NzbDrone.Core/Datastore/Migration/174_email_multiple_addresses.cs index 06cf0693c..145df36e2 100644 --- a/src/NzbDrone.Core/Datastore/Migration/174_email_multiple_addresses.cs +++ b/src/NzbDrone.Core/Datastore/Migration/174_email_multiple_addresses.cs @@ -34,7 +34,7 @@ namespace NzbDrone.Core.Datastore.Migration private void ChangeEmailAddressType(IDbConnection conn, IDbTransaction tran) { - var rows = conn.Query($"SELECT Id, Settings FROM Notifications WHERE Implementation = 'Email'"); + var rows = conn.Query($"SELECT \"Id\", \"Settings\" FROM \"Notifications\" WHERE \"Implementation\" = 'Email'"); var corrected = new List(); @@ -62,7 +62,7 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var updateSql = "UPDATE Notifications SET Settings = @Settings WHERE Id = @Id"; + var updateSql = "UPDATE \"Notifications\" SET \"Settings\" = @Settings WHERE \"Id\" = @Id"; conn.Execute(updateSql, corrected, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/175_remove_chown_and_folderchmod_config.cs b/src/NzbDrone.Core/Datastore/Migration/175_remove_chown_and_folderchmod_config.cs index 9e8f44aa3..2764d59a3 100644 --- a/src/NzbDrone.Core/Datastore/Migration/175_remove_chown_and_folderchmod_config.cs +++ b/src/NzbDrone.Core/Datastore/Migration/175_remove_chown_and_folderchmod_config.cs @@ -8,7 +8,7 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Execute.Sql("DELETE FROM config WHERE Key IN ('folderchmod', 'chownuser', 'parsingleniency')"); + Execute.Sql("DELETE FROM \"Config\" WHERE \"Key\" IN ('folderchmod', 'chownuser', 'parsingleniency')"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/177_language_improvements.cs b/src/NzbDrone.Core/Datastore/Migration/177_language_improvements.cs index 481777acf..ecd7639f0 100644 --- a/src/NzbDrone.Core/Datastore/Migration/177_language_improvements.cs +++ b/src/NzbDrone.Core/Datastore/Migration/177_language_improvements.cs @@ -41,18 +41,27 @@ namespace NzbDrone.Core.Datastore.Migration Delete.Column("PhysicalReleaseNote").FromTable("Movies"); Delete.Column("SecondaryYearSourceId").FromTable("Movies"); - Alter.Table("NamingConfig").AddColumn("RenameMovies").AsBoolean().WithDefaultValue(0); - Execute.Sql("UPDATE NamingConfig SET RenameMovies=RenameEpisodes"); + Alter.Table("NamingConfig").AddColumn("RenameMovies").AsBoolean().WithDefaultValue(false); + Execute.Sql("UPDATE \"NamingConfig\" SET \"RenameMovies\"=\"RenameEpisodes\""); Delete.Column("RenameEpisodes").FromTable("NamingConfig"); //Manual SQL, Fluent Migrator doesn't support multi-column unique contraint on table creation, SQLite doesn't support adding it after creation - Execute.Sql("CREATE TABLE MovieTranslations(" + - "Id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " + - "MovieId INTEGER NOT NULL, " + - "Title TEXT, " + - "CleanTitle TEXT, " + - "Overview TEXT, " + - "Language INTEGER NOT NULL, " + + IfDatabase("sqlite").Execute.Sql("CREATE TABLE \"MovieTranslations\"(" + + "\"Id\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " + + "\"MovieId\" INTEGER NOT NULL, " + + "\"Title\" TEXT, " + + "\"CleanTitle\" TEXT, " + + "\"Overview\" TEXT, " + + "\"Language\" INTEGER NOT NULL, " + + "Unique(\"MovieId\", \"Language\"));"); + + IfDatabase("postgres").Execute.Sql("CREATE TABLE \"MovieTranslations\"(" + + "\"Id\" SERIAL PRIMARY KEY , " + + "\"MovieId\" INTEGER NOT NULL, " + + "\"Title\" TEXT, " + + "\"CleanTitle\" TEXT, " + + "\"Overview\" TEXT, " + + "\"Language\" INTEGER NOT NULL, " + "Unique(\"MovieId\", \"Language\"));"); // Prevent failure if two movies have same alt titles @@ -73,7 +82,7 @@ namespace NzbDrone.Core.Datastore.Migration private void FixLanguagesMoveFile(IDbConnection conn, IDbTransaction tran) { - var rows = conn.Query($"SELECT Id, Languages FROM MovieFiles"); + var rows = conn.Query($"SELECT \"Id\", \"Languages\" FROM \"MovieFiles\""); var corrected = new List(); @@ -90,13 +99,13 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var updateSql = "UPDATE MovieFiles SET Languages = @Languages WHERE Id = @Id"; + var updateSql = "UPDATE \"MovieFiles\" SET \"Languages\" = @Languages WHERE \"Id\" = @Id"; conn.Execute(updateSql, corrected, transaction: tran); } private void FixLanguagesHistory(IDbConnection conn, IDbTransaction tran) { - var rows = conn.Query($"SELECT Id, Languages FROM History"); + var rows = conn.Query($"SELECT \"Id\", \"Languages\" FROM \"History\""); var corrected = new List(); @@ -113,7 +122,7 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var updateSql = "UPDATE History SET Languages = @Languages WHERE Id = @Id"; + var updateSql = "UPDATE \"History\" SET \"Languages\" = @Languages WHERE \"Id\" = @Id"; conn.Execute(updateSql, corrected, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/178_new_list_server.cs b/src/NzbDrone.Core/Datastore/Migration/178_new_list_server.cs index 9aa3179ad..5a201b592 100644 --- a/src/NzbDrone.Core/Datastore/Migration/178_new_list_server.cs +++ b/src/NzbDrone.Core/Datastore/Migration/178_new_list_server.cs @@ -41,7 +41,7 @@ namespace NzbDrone.Core.Datastore.Migration private void FixRadarrLists(IDbConnection conn, IDbTransaction tran) { - var rows = conn.Query($"SELECT * FROM NetImport WHERE ConfigContract = 'RadarrListSettings'"); + var rows = conn.Query($"SELECT * FROM \"NetImport\" WHERE \"ConfigContract\" = 'RadarrListSettings'"); var radarrUrls = new List { @@ -108,17 +108,17 @@ namespace NzbDrone.Core.Datastore.Migration row.Settings = JsonSerializer.Serialize(newSettings, _serializerSettings); } - var updateSql = "UPDATE NetImport SET Implementation = @Implementation, " + - "ConfigContract = @ConfigContract, " + - "Settings = @Settings " + - "WHERE Id = @Id"; + var updateSql = "UPDATE \"NetImport\" SET \"Implementation\" = @Implementation, " + + "\"ConfigContract\" = @ConfigContract, " + + "\"Settings\" = @Settings " + + "WHERE \"Id\" = @Id"; conn.Execute(updateSql, rows, transaction: tran); } private void FixStevenLuLists(IDbConnection conn, IDbTransaction tran) { - var rows = conn.Query($"SELECT * FROM NetImport WHERE ConfigContract = 'StevenLuSettings'"); + var rows = conn.Query($"SELECT * FROM \"NetImport\" WHERE \"ConfigContract\" = 'StevenLuSettings'"); var updated = new List(); @@ -160,10 +160,10 @@ namespace NzbDrone.Core.Datastore.Migration } } - var updateSql = "UPDATE NetImport SET Implementation = @Implementation, " + - "ConfigContract = @ConfigContract, " + - "Settings = @Settings " + - "WHERE Id = @Id"; + var updateSql = "UPDATE \"NetImport\" SET \"Implementation\" = @Implementation, " + + "\"ConfigContract\" = @ConfigContract, " + + "\"Settings\" = @Settings " + + "WHERE \"Id\" = @Id"; conn.Execute(updateSql, updated, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/180_fix_invalid_profile_references.cs b/src/NzbDrone.Core/Datastore/Migration/180_fix_invalid_profile_references.cs index 3826d79ed..28d2650eb 100644 --- a/src/NzbDrone.Core/Datastore/Migration/180_fix_invalid_profile_references.cs +++ b/src/NzbDrone.Core/Datastore/Migration/180_fix_invalid_profile_references.cs @@ -21,8 +21,8 @@ namespace NzbDrone.Core.Datastore.Migration private void FixMovies(IDbConnection conn, IDbTransaction tran) { var profiles = GetProfileIds(conn); - var movieRows = conn.Query($"SELECT Id, ProfileId FROM Movies"); - var listRows = conn.Query($"SELECT Id, ProfileId FROM NetImport"); + var movieRows = conn.Query($"SELECT \"Id\", \"ProfileId\" FROM \"Movies\""); + var listRows = conn.Query($"SELECT \"Id\", \"ProfileId\" FROM \"NetImport\""); // Only process if there are lists or movies existing in the DB if (movieRows.Any() || listRows.Any()) @@ -54,18 +54,18 @@ namespace NzbDrone.Core.Datastore.Migration } //Correct any Movies that reference profiles that are null - var sql = $"UPDATE Movies SET ProfileId = {mostCommonProfileId} WHERE Id IN(SELECT Movies.Id FROM Movies LEFT OUTER JOIN Profiles ON Movies.ProfileId = Profiles.Id WHERE Profiles.Id IS NULL)"; + var sql = $"UPDATE \"Movies\" SET \"ProfileId\" = {mostCommonProfileId} WHERE \"Id\" IN(SELECT \"Movies\".\"Id\" FROM \"Movies\" LEFT OUTER JOIN \"Profiles\" ON \"Movies\".\"ProfileId\" = \"Profiles\".\"Id\" WHERE \"Profiles\".\"Id\" IS NULL)"; conn.Execute(sql, transaction: tran); //Correct any Lists that reference profiles that are null - sql = $"UPDATE NetImport SET ProfileId = {mostCommonProfileId} WHERE Id IN(SELECT NetImport.Id FROM NetImport LEFT OUTER JOIN Profiles ON NetImport.ProfileId = Profiles.Id WHERE Profiles.Id IS NULL)"; + sql = $"UPDATE \"NetImport\" SET \"ProfileId\" = {mostCommonProfileId} WHERE \"Id\" IN(SELECT \"NetImport\".\"Id\" FROM \"NetImport\" LEFT OUTER JOIN \"Profiles\" ON \"NetImport\".\"ProfileId\" = \"Profiles\".\"Id\" WHERE \"Profiles\".\"Id\" IS NULL)"; conn.Execute(sql, transaction: tran); } } private List GetProfileIds(IDbConnection conn) { - return conn.Query("SELECT Id From Profiles").Select(p => p.Id).ToList(); + return conn.Query("SELECT \"Id\" From \"Profiles\"").Select(p => p.Id).ToList(); } private void InsertDefaultQualityProfiles(IDbConnection conn, IDbTransaction tran) @@ -80,7 +80,16 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand insertNewLanguageProfileCmd = conn.CreateCommand()) { insertNewLanguageProfileCmd.Transaction = tran; - insertNewLanguageProfileCmd.CommandText = "INSERT INTO Profiles (Id, Name, Cutoff, Items, Language, FormatItems, MinFormatScore, CutoffFormatScore, UpgradeAllowed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + if (conn.GetType().FullName == "Npgsql.NpgsqlConnection") + { + insertNewLanguageProfileCmd.CommandText = "INSERT INTO \"Profiles\" (\"Id\", \"Name\", \"Cutoff\", \"Items\", \"Language\", \"FormatItems\", \"MinFormatScore\", \"CutoffFormatScore\", \"UpgradeAllowed\") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)"; + } + else + { + insertNewLanguageProfileCmd.CommandText = "INSERT INTO \"Profiles\" (\"Id\", \"Name\", \"Cutoff\", \"Items\", \"Language\", \"FormatItems\", \"MinFormatScore\", \"CutoffFormatScore\", \"UpgradeAllowed\") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + } + insertNewLanguageProfileCmd.AddParameter(profileId); insertNewLanguageProfileCmd.AddParameter(profile.Name); insertNewLanguageProfileCmd.AddParameter(profile.Cutoff); @@ -111,7 +120,7 @@ namespace NzbDrone.Core.Datastore.Migration var profiles = new List(); //Grab custom formats if any exist and add them to the new profiles - var formats = conn.Query($"SELECT Id FROM CustomFormats").ToList(); + var formats = conn.Query($"SELECT \"Id\" FROM \"CustomFormats\"").ToList(); profiles.Add(GetDefaultProfile("Any", formats, @@ -258,7 +267,7 @@ namespace NzbDrone.Core.Datastore.Migration Language = Language.English, MinFormatScore = 0, CutoffFormatScore = 0, - UpgradeAllowed = 0, + UpgradeAllowed = false, FormatItems = formatItems }; @@ -278,7 +287,7 @@ namespace NzbDrone.Core.Datastore.Migration public int Cutoff { get; set; } public int MinFormatScore { get; set; } public int CutoffFormatScore { get; set; } - public int UpgradeAllowed { get; set; } + public bool UpgradeAllowed { get; set; } public Language Language { get; set; } public List FormatItems { get; set; } public List Items { get; set; } diff --git a/src/NzbDrone.Core/Datastore/Migration/181_list_movies_table.cs b/src/NzbDrone.Core/Datastore/Migration/181_list_movies_table.cs index dbea69bb7..a7866930f 100644 --- a/src/NzbDrone.Core/Datastore/Migration/181_list_movies_table.cs +++ b/src/NzbDrone.Core/Datastore/Migration/181_list_movies_table.cs @@ -11,7 +11,7 @@ namespace NzbDrone.Core.Datastore.Migration Rename.Table("NetImport").To("ImportLists"); Rename.Table("NetImportStatus").To("ImportListStatus"); - Execute.Sql("UPDATE Config SET Key = 'importlistsyncinterval' WHERE Key = 'netimportsyncinterval'"); + Execute.Sql("UPDATE \"Config\" SET \"Key\" = 'importlistsyncinterval' WHERE \"Key\" = 'netimportsyncinterval'"); Alter.Table("ImportLists").AddColumn("SearchOnAdd").AsBoolean().WithDefaultValue(false); diff --git a/src/NzbDrone.Core/Datastore/Migration/183_download_propers_config.cs b/src/NzbDrone.Core/Datastore/Migration/183_download_propers_config.cs index 72312ee1d..7ce2bc106 100644 --- a/src/NzbDrone.Core/Datastore/Migration/183_download_propers_config.cs +++ b/src/NzbDrone.Core/Datastore/Migration/183_download_propers_config.cs @@ -10,7 +10,7 @@ namespace NzbDrone.Core.Datastore.Migration protected override void MainDbUpgrade() { Execute.WithConnection(SetMetadataFileExtension); - Execute.Sql("DELETE FROM Config WHERE Key = 'autodownloadpropers'"); + Execute.Sql("DELETE FROM \"Config\" WHERE \"Key\" = 'autodownloadpropers'"); Delete.Column("PreferredTags").FromTable("Profiles"); } @@ -19,7 +19,7 @@ namespace NzbDrone.Core.Datastore.Migration using (var cmd = conn.CreateCommand()) { cmd.Transaction = tran; - cmd.CommandText = "SELECT Value FROM Config WHERE Key = 'autodownloadpropers'"; + cmd.CommandText = "SELECT \"Value\" FROM \"Config\" WHERE \"Key\" = 'autodownloadpropers'"; using (var reader = cmd.ExecuteReader()) { @@ -31,7 +31,7 @@ namespace NzbDrone.Core.Datastore.Migration using (var updateCmd = conn.CreateCommand()) { updateCmd.Transaction = tran; - updateCmd.CommandText = "INSERT INTO Config (key, value) VALUES ('downloadpropersandrepacks', ?)"; + updateCmd.CommandText = "INSERT INTO \"Config\" (\"key\", \"value\") VALUES ('downloadpropersandrepacks', ?)"; updateCmd.AddParameter(newValue); updateCmd.ExecuteNonQuery(); diff --git a/src/NzbDrone.Core/Datastore/Migration/186_fix_tmdb_duplicates.cs b/src/NzbDrone.Core/Datastore/Migration/186_fix_tmdb_duplicates.cs index 46fd2acf0..70282ee89 100644 --- a/src/NzbDrone.Core/Datastore/Migration/186_fix_tmdb_duplicates.cs +++ b/src/NzbDrone.Core/Datastore/Migration/186_fix_tmdb_duplicates.cs @@ -20,7 +20,7 @@ namespace NzbDrone.Core.Datastore.Migration private void FixMovies(IDbConnection conn, IDbTransaction tran) { - var movieRows = conn.Query($"SELECT Id, TmdbId, Added, LastInfoSync, MovieFileId FROM Movies"); + var movieRows = conn.Query($"SELECT \"Id\", \"TmdbId\", \"Added\", \"LastInfoSync\", \"MovieFileId\" FROM \"Movies\""); // Only process if there are movies existing in the DB if (movieRows.Any()) @@ -61,7 +61,7 @@ namespace NzbDrone.Core.Datastore.Migration if (purgeMovies.Count > 0) { - var deleteSql = "DELETE FROM Movies WHERE Id = @Id"; + var deleteSql = "DELETE FROM \"Movies\" WHERE \"Id\" = @Id"; conn.Execute(deleteSql, purgeMovies, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/187_swap_filechmod_for_folderchmod.cs b/src/NzbDrone.Core/Datastore/Migration/187_swap_filechmod_for_folderchmod.cs index a1580efa4..0316a72ea 100644 --- a/src/NzbDrone.Core/Datastore/Migration/187_swap_filechmod_for_folderchmod.cs +++ b/src/NzbDrone.Core/Datastore/Migration/187_swap_filechmod_for_folderchmod.cs @@ -20,7 +20,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand getFileChmodCmd = conn.CreateCommand()) { getFileChmodCmd.Transaction = tran; - getFileChmodCmd.CommandText = @"SELECT Value FROM Config WHERE Key = 'filechmod'"; + getFileChmodCmd.CommandText = @"SELECT ""Value"" FROM ""Config"" WHERE ""Key"" = 'filechmod'"; var fileChmod = getFileChmodCmd.ExecuteScalar() as string; if (fileChmod != null) @@ -35,7 +35,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand insertCmd = conn.CreateCommand()) { insertCmd.Transaction = tran; - insertCmd.CommandText = "INSERT INTO Config (Key, Value) VALUES ('chmodfolder', ?)"; + insertCmd.CommandText = "INSERT INTO \"Config\" (\"Key\", \"Value\") VALUES ('chmodfolder', ?)"; insertCmd.AddParameter(folderChmod); insertCmd.ExecuteNonQuery(); @@ -45,7 +45,7 @@ namespace NzbDrone.Core.Datastore.Migration using (IDbCommand deleteCmd = conn.CreateCommand()) { deleteCmd.Transaction = tran; - deleteCmd.CommandText = "DELETE FROM Config WHERE Key = 'filechmod'"; + deleteCmd.CommandText = "DELETE FROM \"Config\" WHERE \"Key\" = 'filechmod'"; deleteCmd.ExecuteNonQuery(); } diff --git a/src/NzbDrone.Core/Datastore/Migration/188_mediainfo_channels.cs b/src/NzbDrone.Core/Datastore/Migration/188_mediainfo_channels.cs index 2efee19f2..1268803a4 100644 --- a/src/NzbDrone.Core/Datastore/Migration/188_mediainfo_channels.cs +++ b/src/NzbDrone.Core/Datastore/Migration/188_mediainfo_channels.cs @@ -8,11 +8,12 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Execute.Sql("UPDATE MovieFiles SET MediaInfo = Replace(MediaInfo, '\"audioChannels\"', '\"audioChannelsContainer\"');"); - Execute.Sql("UPDATE MovieFiles SET MediaInfo = Replace(MediaInfo, '\"audioChannelPositionsText\"', '\"audioChannelPositionsTextContainer\"');"); + Execute.Sql("UPDATE \"MovieFiles\" SET \"MediaInfo\" = Replace(\"MediaInfo\", '\"audioChannels\"', '\"audioChannelsContainer\"');"); + Execute.Sql("UPDATE \"MovieFiles\" SET \"MediaInfo\" = Replace(\"MediaInfo\", '\"audioChannelPositionsText\"', '\"audioChannelPositionsTextContainer\"');"); //Change List Interval from Min to Hour - Execute.Sql("UPDATE Config SET Value = max((Value / 60) + 1, 6) WHERE Key = 'importlistsyncinterval'"); + IfDatabase("sqlite").Execute.Sql("UPDATE \"Config\" SET \"Value\" = max((\"Value\" / 60) + 1, 6) WHERE \"Key\" = 'importlistsyncinterval'"); + IfDatabase("postgres").Execute.Sql("UPDATE \"Config\" SET \"Value\" = greatest((\"Value\"::int / 60) + 1, 6) WHERE \"Key\" = 'importlistsyncinterval'"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/190_update_awesome_hd_link.cs b/src/NzbDrone.Core/Datastore/Migration/190_update_awesome_hd_link.cs index 9f348c2a2..42029d793 100644 --- a/src/NzbDrone.Core/Datastore/Migration/190_update_awesome_hd_link.cs +++ b/src/NzbDrone.Core/Datastore/Migration/190_update_awesome_hd_link.cs @@ -9,8 +9,8 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Execute.Sql("UPDATE Indexers SET Settings = Replace(Settings, 'https://awesome-hd.net', 'https://awesome-hd.club') WHERE Implementation = 'AwesomeHD';"); - Execute.Sql("UPDATE Indexers SET Settings = Replace(Settings, 'https://awesome-hd.me', 'https://awesome-hd.club') WHERE Implementation = 'AwesomeHD';"); + Execute.Sql("UPDATE \"Indexers\" SET \"Settings\" = Replace(\"Settings\", 'https://awesome-hd.net', 'https://awesome-hd.club') WHERE \"Implementation\" = 'AwesomeHD';"); + Execute.Sql("UPDATE \"Indexers\" SET \"Settings\" = Replace(\"Settings\", 'https://awesome-hd.me', 'https://awesome-hd.club') WHERE \"Implementation\" = 'AwesomeHD';"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/192_add_on_delete_to_notifications.cs b/src/NzbDrone.Core/Datastore/Migration/192_add_on_delete_to_notifications.cs index 3c1f0a252..351402c5d 100644 --- a/src/NzbDrone.Core/Datastore/Migration/192_add_on_delete_to_notifications.cs +++ b/src/NzbDrone.Core/Datastore/Migration/192_add_on_delete_to_notifications.cs @@ -9,8 +9,8 @@ namespace NzbDrone.Core.Datastore.Migration protected override void MainDbUpgrade() { Rename.Column("OnDelete").OnTable("Notifications").To("OnMovieDelete"); - Alter.Table("Notifications").AddColumn("OnMovieFileDelete").AsBoolean().WithDefaultValue(0); - Alter.Table("Notifications").AddColumn("OnMovieFileDeleteForUpgrade").AsBoolean().WithDefaultValue(0); + Alter.Table("Notifications").AddColumn("OnMovieFileDelete").AsBoolean().WithDefaultValue(false); + Alter.Table("Notifications").AddColumn("OnMovieFileDeleteForUpgrade").AsBoolean().WithDefaultValue(false); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/194_add_bypass_to_delay_profile.cs b/src/NzbDrone.Core/Datastore/Migration/194_add_bypass_to_delay_profile.cs index bc38a3e67..a146b0909 100644 --- a/src/NzbDrone.Core/Datastore/Migration/194_add_bypass_to_delay_profile.cs +++ b/src/NzbDrone.Core/Datastore/Migration/194_add_bypass_to_delay_profile.cs @@ -11,7 +11,7 @@ namespace NzbDrone.Core.Datastore.Migration Alter.Table("DelayProfiles").AddColumn("BypassIfHighestQuality").AsBoolean().WithDefaultValue(false); // Set to true for existing Delay Profiles to keep behavior the same. - Execute.Sql("UPDATE DelayProfiles SET BypassIfHighestQuality = 1;"); + Update.Table("DelayProfiles").Set(new { BypassIfHighestQuality = true }).AllRows(); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/195_update_notifiarr.cs b/src/NzbDrone.Core/Datastore/Migration/195_update_notifiarr.cs index b2c455271..a8cccfd6a 100644 --- a/src/NzbDrone.Core/Datastore/Migration/195_update_notifiarr.cs +++ b/src/NzbDrone.Core/Datastore/Migration/195_update_notifiarr.cs @@ -9,7 +9,7 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Execute.Sql("UPDATE Notifications SET Implementation = Replace(Implementation, 'DiscordNotifier', 'Notifiarr'),ConfigContract = Replace(ConfigContract, 'DiscordNotifierSettings', 'NotifiarrSettings') WHERE Implementation = 'DiscordNotifier';"); + Execute.Sql("UPDATE \"Notifications\" SET \"Implementation\" = Replace(\"Implementation\", 'DiscordNotifier', 'Notifiarr'),\"ConfigContract\" = Replace(\"ConfigContract\", 'DiscordNotifierSettings', 'NotifiarrSettings') WHERE \"Implementation\" = 'DiscordNotifier';"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/196_legacy_mediainfo_hdr.cs b/src/NzbDrone.Core/Datastore/Migration/196_legacy_mediainfo_hdr.cs index 0d3a7fd45..68c27368f 100644 --- a/src/NzbDrone.Core/Datastore/Migration/196_legacy_mediainfo_hdr.cs +++ b/src/NzbDrone.Core/Datastore/Migration/196_legacy_mediainfo_hdr.cs @@ -8,7 +8,7 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Execute.Sql("UPDATE NamingConfig SET StandardMovieFormat = Replace(StandardMovieFormat, '{MediaInfo HDR}', '{MediaInfo VideoDynamicRange}');"); + Execute.Sql("UPDATE \"NamingConfig\" SET \"StandardMovieFormat\" = Replace(\"StandardMovieFormat\", '{MediaInfo HDR}', '{MediaInfo VideoDynamicRange}');"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/199_mediainfo_to_ffmpeg.cs b/src/NzbDrone.Core/Datastore/Migration/199_mediainfo_to_ffmpeg.cs index 1924e0de7..345c948fb 100644 --- a/src/NzbDrone.Core/Datastore/Migration/199_mediainfo_to_ffmpeg.cs +++ b/src/NzbDrone.Core/Datastore/Migration/199_mediainfo_to_ffmpeg.cs @@ -47,7 +47,7 @@ namespace NzbDrone.Core.Datastore.Migration private void MigrateToFfprobe(IDbConnection conn, IDbTransaction tran) { - var existing = conn.Query("SELECT Id, MediaInfo, SceneName FROM MovieFiles"); + var existing = conn.Query("SELECT \"Id\", \"MediaInfo\", \"SceneName\" FROM \"MovieFiles\""); var updated = new List(); @@ -78,7 +78,7 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var updateSql = "UPDATE MovieFiles SET MediaInfo = @MediaInfo WHERE Id = @Id"; + var updateSql = "UPDATE \"MovieFiles\" SET \"MediaInfo\" = @MediaInfo WHERE \"Id\" = @Id"; conn.Execute(updateSql, updated, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/200_cdh_per_downloadclient.cs b/src/NzbDrone.Core/Datastore/Migration/200_cdh_per_downloadclient.cs index 9e931ce70..68bbdd70a 100644 --- a/src/NzbDrone.Core/Datastore/Migration/200_cdh_per_downloadclient.cs +++ b/src/NzbDrone.Core/Datastore/Migration/200_cdh_per_downloadclient.cs @@ -24,7 +24,7 @@ namespace NzbDrone.Core.Datastore.Migration var removeCompletedDownloads = false; var removeFailedDownloads = true; - using (var removeCompletedDownloadsCmd = conn.CreateCommand(tran, "SELECT Value FROM Config WHERE Key = 'removecompleteddownloads'")) + using (var removeCompletedDownloadsCmd = conn.CreateCommand(tran, "SELECT \"Value\" FROM \"Config\" WHERE \"Key\" = 'removecompleteddownloads'")) { if ((removeCompletedDownloadsCmd.ExecuteScalar() as string)?.ToLower() == "true") { @@ -32,7 +32,7 @@ namespace NzbDrone.Core.Datastore.Migration } } - using (var removeFailedDownloadsCmd = conn.CreateCommand(tran, "SELECT Value FROM Config WHERE Key = 'removefaileddownloads'")) + using (var removeFailedDownloadsCmd = conn.CreateCommand(tran, "SELECT \"Value\" FROM \"Config\" WHERE \"Key\" = 'removefaileddownloads'")) { if ((removeFailedDownloadsCmd.ExecuteScalar() as string)?.ToLower() == "false") { @@ -40,14 +40,25 @@ namespace NzbDrone.Core.Datastore.Migration } } - using (var updateClientCmd = conn.CreateCommand(tran, $"UPDATE DownloadClients SET RemoveCompletedDownloads = (CASE WHEN Implementation IN (\"RTorrent\", \"Flood\") THEN 0 ELSE ? END), RemoveFailedDownloads = ?")) + string commandText; + + if (conn.GetType().FullName == "Npgsql.NpgsqlConnection") + { + commandText = $"UPDATE \"DownloadClients\" SET \"RemoveCompletedDownloads\" = (CASE WHEN \"Implementation\" IN ('RTorrent', 'Flood') THEN 'false' ELSE $1 END), \"RemoveFailedDownloads\" = $2"; + } + else + { + commandText = $"UPDATE \"DownloadClients\" SET \"RemoveCompletedDownloads\" = (CASE WHEN \"Implementation\" IN ('RTorrent', 'Flood') THEN 'false' ELSE ? END), \"RemoveFailedDownloads\" = ?"; + } + + using (var updateClientCmd = conn.CreateCommand(tran, commandText)) { - updateClientCmd.AddParameter(removeCompletedDownloads ? 1 : 0); - updateClientCmd.AddParameter(removeFailedDownloads ? 1 : 0); + updateClientCmd.AddParameter(removeCompletedDownloads); + updateClientCmd.AddParameter(removeFailedDownloads); updateClientCmd.ExecuteNonQuery(); } - using (var removeConfigCmd = conn.CreateCommand(tran, $"DELETE FROM Config WHERE Key IN ('removecompleteddownloads', 'removefaileddownloads')")) + using (var removeConfigCmd = conn.CreateCommand(tran, $"DELETE FROM \"Config\" WHERE \"Key\" IN ('removecompleteddownloads', 'removefaileddownloads')")) { removeConfigCmd.ExecuteNonQuery(); } diff --git a/src/NzbDrone.Core/Datastore/Migration/201_migrate_discord_from_slack.cs b/src/NzbDrone.Core/Datastore/Migration/201_migrate_discord_from_slack.cs index f477d953c..668d2280a 100644 --- a/src/NzbDrone.Core/Datastore/Migration/201_migrate_discord_from_slack.cs +++ b/src/NzbDrone.Core/Datastore/Migration/201_migrate_discord_from_slack.cs @@ -36,7 +36,7 @@ namespace NzbDrone.Core.Datastore.Migration private void MigrateDiscordFromSlack(IDbConnection conn, IDbTransaction tran) { - var notificationRows = conn.Query($"SELECT Id,ConfigContract,Implementation,Name,Settings FROM Notifications WHERE Implementation = 'Slack'"); + var notificationRows = conn.Query($"SELECT \"Id\",\"ConfigContract\",\"Implementation\",\"Name\",\"Settings\" FROM \"Notifications\" WHERE \"Implementation\" = 'Slack'"); var discordSlackNotifications = notificationRows.Where(n => JsonSerializer.Deserialize(n.Settings, _serializerSettings).WebHookUrl.Contains("discord")); @@ -63,11 +63,11 @@ namespace NzbDrone.Core.Datastore.Migration notification.Settings = JsonSerializer.Serialize(discordSettings, _serializerSettings); } - var updateSql = "UPDATE Notifications SET ConfigContract = @ConfigContract, " + - "Implementation = @Implementation, " + - "Name = @Name, " + - "Settings = @Settings " + - "WHERE Id = @Id"; + var updateSql = "UPDATE \"Notifications\" SET \"ConfigContract\" = @ConfigContract, " + + "\"Implementation\" = @Implementation, " + + "\"Name\" = @Name, " + + "\"Settings\" = @Settings " + + "WHERE \"Id\" = @Id"; conn.Execute(updateSql, discordSlackNotifications, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/203_add_on_update_to_notifications.cs b/src/NzbDrone.Core/Datastore/Migration/203_add_on_update_to_notifications.cs index c17d6962d..2d19ea793 100644 --- a/src/NzbDrone.Core/Datastore/Migration/203_add_on_update_to_notifications.cs +++ b/src/NzbDrone.Core/Datastore/Migration/203_add_on_update_to_notifications.cs @@ -8,7 +8,7 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { - Alter.Table("Notifications").AddColumn("OnApplicationUpdate").AsBoolean().WithDefaultValue(0); + Alter.Table("Notifications").AddColumn("OnApplicationUpdate").AsBoolean().WithDefaultValue(false); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/204_ensure_identity_on_id_columns.cs b/src/NzbDrone.Core/Datastore/Migration/204_ensure_identity_on_id_columns.cs index 92bd38315..ba5358ece 100644 --- a/src/NzbDrone.Core/Datastore/Migration/204_ensure_identity_on_id_columns.cs +++ b/src/NzbDrone.Core/Datastore/Migration/204_ensure_identity_on_id_columns.cs @@ -11,17 +11,17 @@ namespace NzbDrone.Core.Datastore.Migration //Purge Commands before reworking tables Delete.FromTable("Commands").AllRows(); - Alter.Column("Id").OnTable("Movies").AsInt32().PrimaryKey().Identity(); - Alter.Column("Id").OnTable("MovieTranslations").AsInt32().PrimaryKey().Identity(); - Alter.Column("Id").OnTable("Commands").AsInt32().PrimaryKey().Identity(); - Alter.Column("Id").OnTable("Credits").AsInt32().PrimaryKey().Identity(); - Alter.Column("Id").OnTable("Profiles").AsInt32().PrimaryKey().Identity(); - Alter.Column("Id").OnTable("PendingReleases").AsInt32().PrimaryKey().Identity(); - Alter.Column("Id").OnTable("NamingConfig").AsInt32().PrimaryKey().Identity(); - Alter.Column("Id").OnTable("History").AsInt32().PrimaryKey().Identity(); - Alter.Column("Id").OnTable("Blocklist").AsInt32().PrimaryKey().Identity(); - Alter.Column("Id").OnTable("MovieFiles").AsInt32().PrimaryKey().Identity(); - Alter.Column("Id").OnTable("CustomFormats").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("Movies").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("MovieTranslations").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("Commands").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("Credits").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("Profiles").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("PendingReleases").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("NamingConfig").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("History").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("Blocklist").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("MovieFiles").AsInt32().PrimaryKey().Identity(); + IfDatabase("sqlite").Alter.Column("Id").OnTable("CustomFormats").AsInt32().PrimaryKey().Identity(); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/206_multiple_ratings_support.cs b/src/NzbDrone.Core/Datastore/Migration/206_multiple_ratings_support.cs index 8c2c41ef6..c9cf376e4 100644 --- a/src/NzbDrone.Core/Datastore/Migration/206_multiple_ratings_support.cs +++ b/src/NzbDrone.Core/Datastore/Migration/206_multiple_ratings_support.cs @@ -28,8 +28,8 @@ namespace NzbDrone.Core.Datastore.Migration protected override void MainDbUpgrade() { - Execute.Sql("UPDATE CustomFilters SET Filters = Replace(Filters, 'ratings', 'tmdbRating') WHERE Type = 'discoverMovie';"); - Execute.Sql("UPDATE CustomFilters SET Filters = Replace(Filters, 'ratings', 'tmdbRating') WHERE Type = 'movieIndex';"); + Execute.Sql("UPDATE \"CustomFilters\" SET \"Filters\" = Replace(\"Filters\", 'ratings', 'tmdbRating') WHERE \"Type\" = 'discoverMovie';"); + Execute.Sql("UPDATE \"CustomFilters\" SET \"Filters\" = Replace(\"Filters\", 'ratings', 'tmdbRating') WHERE \"Type\" = 'movieIndex';"); Execute.WithConnection((conn, tran) => FixRatings(conn, tran, "Movies")); Execute.WithConnection((conn, tran) => FixRatings(conn, tran, "ImportListMovies")); @@ -37,7 +37,7 @@ namespace NzbDrone.Core.Datastore.Migration private void FixRatings(IDbConnection conn, IDbTransaction tran, string table) { - var rows = conn.Query($"SELECT Id, Ratings FROM {table}"); + var rows = conn.Query($"SELECT \"Id\", \"Ratings\" FROM \"{table}\""); var corrected = new List(); @@ -68,7 +68,7 @@ namespace NzbDrone.Core.Datastore.Migration }); } - var updateSql = $"UPDATE {table} SET Ratings = @Ratings WHERE Id = @Id"; + var updateSql = $"UPDATE \"{table}\" SET \"Ratings\" = @Ratings WHERE \"Id\" = @Id"; conn.Execute(updateSql, corrected, transaction: tran); } diff --git a/src/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs b/src/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs index 35c5c6b59..1249dfd8b 100644 --- a/src/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs +++ b/src/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs @@ -2,6 +2,7 @@ using System; using System.Diagnostics; using System.Reflection; using FluentMigrator.Runner; +using FluentMigrator.Runner.Generators; using FluentMigrator.Runner.Initialization; using FluentMigrator.Runner.Processors; using Microsoft.Extensions.DependencyInjection; @@ -34,11 +35,16 @@ namespace NzbDrone.Core.Datastore.Migration.Framework _logger.Info("*** Migrating {0} ***", connectionString); - var serviceProvider = new ServiceCollection() + ServiceProvider serviceProvider; + + var db = connectionString.Contains(".db") ? "sqlite" : "postgres"; + + serviceProvider = new ServiceCollection() .AddLogging(b => b.AddNLog()) .AddFluentMigratorCore() .ConfigureRunner( builder => builder + .AddPostgres() .AddNzbDroneSQLite() .WithGlobalConnectionString(connectionString) .WithMigrationsIn(Assembly.GetExecutingAssembly())) @@ -48,6 +54,14 @@ namespace NzbDrone.Core.Datastore.Migration.Framework opt.PreviewOnly = false; opt.Timeout = TimeSpan.FromSeconds(60); }) + .Configure(cfg => + { + cfg.ProcessorId = db; + }) + .Configure(cfg => + { + cfg.GeneratorId = db; + }) .BuildServiceProvider(); using (var scope = serviceProvider.CreateScope()) diff --git a/src/NzbDrone.Core/Datastore/SqlBuilder.cs b/src/NzbDrone.Core/Datastore/SqlBuilder.cs index e686d4852..8febd5b6a 100644 --- a/src/NzbDrone.Core/Datastore/SqlBuilder.cs +++ b/src/NzbDrone.Core/Datastore/SqlBuilder.cs @@ -8,9 +8,17 @@ namespace NzbDrone.Core.Datastore public class SqlBuilder { private readonly Dictionary _data = new Dictionary(); + private readonly DatabaseType _databaseType; + + public SqlBuilder(DatabaseType databaseType) + { + _databaseType = databaseType; + } public int Sequence { get; private set; } + public DatabaseType DatabaseType => _databaseType; + public Template AddTemplate(string sql, dynamic parameters = null) => new Template(this, sql, parameters); diff --git a/src/NzbDrone.Core/Datastore/TableMapper.cs b/src/NzbDrone.Core/Datastore/TableMapper.cs index f1c3ef7e1..24ab5869e 100644 --- a/src/NzbDrone.Core/Datastore/TableMapper.cs +++ b/src/NzbDrone.Core/Datastore/TableMapper.cs @@ -49,17 +49,17 @@ namespace NzbDrone.Core.Datastore public string SelectTemplate(Type x) { - return $"SELECT /**select**/ FROM {TableMap[x]} /**join**/ /**innerjoin**/ /**leftjoin**/ /**where**/ /**groupby**/ /**having**/ /**orderby**/"; + return $"SELECT /**select**/ FROM \"{TableMap[x]}\" /**join**/ /**innerjoin**/ /**leftjoin**/ /**where**/ /**groupby**/ /**having**/ /**orderby**/"; } public string DeleteTemplate(Type x) { - return $"DELETE FROM {TableMap[x]} /**where**/"; + return $"DELETE FROM \"{TableMap[x]}\" /**where**/"; } public string PageCountTemplate(Type x) { - return $"SELECT /**select**/ FROM {TableMap[x]} /**join**/ /**innerjoin**/ /**leftjoin**/ /**where**/"; + return $"SELECT /**select**/ FROM \"{TableMap[x]}\" /**join**/ /**innerjoin**/ /**leftjoin**/ /**where**/"; } public bool IsValidSortKey(string sortKey) @@ -90,6 +90,35 @@ namespace NzbDrone.Core.Datastore return true; } + + public string GetSortKey(string sortKey) + { + string table = null; + + if (sortKey.Contains('.')) + { + var split = sortKey.Split('.'); + if (split.Length != 2) + { + return sortKey; + } + + table = split[0]; + sortKey = split[1]; + } + + if (table != null && !TableMap.Values.Contains(table, StringComparer.OrdinalIgnoreCase)) + { + return sortKey; + } + + if (!_allowedOrderBy.Contains(sortKey)) + { + return sortKey; + } + + return _allowedOrderBy.First(x => x.Equals(sortKey, StringComparison.OrdinalIgnoreCase)); + } } public class LazyLoadedProperty @@ -154,7 +183,7 @@ namespace NzbDrone.Core.Datastore (db, parent) => { var id = childIdSelector(parent); - return db.Query(new SqlBuilder().Where(x => x.Id == id)).SingleOrDefault(); + return db.Query(new SqlBuilder(db.DatabaseType).Where(x => x.Id == id)).SingleOrDefault(); }, parent => childIdSelector(parent) > 0); } diff --git a/src/NzbDrone.Core/Datastore/WhereBuilder.cs b/src/NzbDrone.Core/Datastore/WhereBuilder.cs index da94e20e1..969364e4f 100644 --- a/src/NzbDrone.Core/Datastore/WhereBuilder.cs +++ b/src/NzbDrone.Core/Datastore/WhereBuilder.cs @@ -1,389 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using System.Text; using Dapper; namespace NzbDrone.Core.Datastore { - public class WhereBuilder : ExpressionVisitor + public abstract class WhereBuilder : ExpressionVisitor { - protected StringBuilder _sb; - - private const DbType EnumerableMultiParameter = (DbType)(-1); - private readonly string _paramNamePrefix; - private readonly bool _requireConcreteValue = false; - private int _paramCount = 0; - private bool _gotConcreteValue = false; - - public WhereBuilder(Expression filter, bool requireConcreteValue, int seq) - { - _paramNamePrefix = string.Format("Clause{0}", seq + 1); - _requireConcreteValue = requireConcreteValue; - _sb = new StringBuilder(); - - Parameters = new DynamicParameters(); - - if (filter != null) - { - Visit(filter); - } - } - - public DynamicParameters Parameters { get; private set; } - - private string AddParameter(object value, DbType? dbType = null) - { - _gotConcreteValue = true; - _paramCount++; - var name = _paramNamePrefix + "_P" + _paramCount; - Parameters.Add(name, value, dbType); - return '@' + name; - } - - protected override Expression VisitBinary(BinaryExpression expression) - { - _sb.Append('('); - - Visit(expression.Left); - - _sb.AppendFormat(" {0} ", Decode(expression)); - - Visit(expression.Right); - - _sb.Append(')'); - - return expression; - } - - protected override Expression VisitMethodCall(MethodCallExpression expression) - { - var method = expression.Method.Name; - - switch (expression.Method.Name) - { - case "Contains": - ParseContainsExpression(expression); - break; - - case "StartsWith": - ParseStartsWith(expression); - break; - - case "EndsWith": - ParseEndsWith(expression); - break; - - default: - var msg = string.Format("'{0}' expressions are not yet implemented in the where clause expression tree parser.", method); - throw new NotImplementedException(msg); - } - - return expression; - } - - protected override Expression VisitMemberAccess(MemberExpression expression) - { - var tableName = expression?.Expression?.Type != null ? TableMapping.Mapper.TableNameMapping(expression.Expression.Type) : null; - var gotValue = TryGetRightValue(expression, out var value); - - // Only use the SQL condition if the expression didn't resolve to an actual value - if (tableName != null && !gotValue) - { - _sb.Append($"\"{tableName}\".\"{expression.Member.Name}\""); - } - else - { - if (value != null) - { - // string is IEnumerable but we don't want to pick up that case - var type = value.GetType(); - var typeInfo = type.GetTypeInfo(); - var isEnumerable = - type != typeof(string) && ( - typeInfo.ImplementedInterfaces.Any(ti => ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) || - (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>))); - - var paramName = isEnumerable ? AddParameter(value, EnumerableMultiParameter) : AddParameter(value); - _sb.Append(paramName); - } - else - { - _gotConcreteValue = true; - _sb.Append("NULL"); - } - } - - return expression; - } - - protected override Expression VisitConstant(ConstantExpression expression) - { - if (expression.Value != null) - { - var paramName = AddParameter(expression.Value); - _sb.Append(paramName); - } - else - { - _gotConcreteValue = true; - _sb.Append("NULL"); - } - - return expression; - } - - private bool TryGetConstantValue(Expression expression, out object result) - { - result = null; - - if (expression is ConstantExpression constExp) - { - result = constExp.Value; - return true; - } - - return false; - } - - private bool TryGetPropertyValue(MemberExpression expression, out object result) - { - result = null; - - if (expression.Expression is MemberExpression nested) - { - // Value is passed in as a property on a parent entity - var container = (nested.Expression as ConstantExpression)?.Value; - - if (container == null) - { - return false; - } - - var entity = GetFieldValue(container, nested.Member); - result = GetFieldValue(entity, expression.Member); - return true; - } - - return false; - } - - private bool TryGetVariableValue(MemberExpression expression, out object result) - { - result = null; - - // Value is passed in as a variable - if (expression.Expression is ConstantExpression nested) - { - result = GetFieldValue(nested.Value, expression.Member); - return true; - } - - return false; - } - - private bool TryGetRightValue(Expression expression, out object value) - { - value = null; - - if (TryGetConstantValue(expression, out value)) - { - return true; - } - - var memberExp = expression as MemberExpression; - - if (TryGetPropertyValue(memberExp, out value)) - { - return true; - } - - if (TryGetVariableValue(memberExp, out value)) - { - return true; - } - - return false; - } - - private object GetFieldValue(object entity, MemberInfo member) - { - if (member.MemberType == MemberTypes.Field) - { - return (member as FieldInfo).GetValue(entity); - } - - if (member.MemberType == MemberTypes.Property) - { - return (member as PropertyInfo).GetValue(entity); - } - - throw new ArgumentException(string.Format("WhereBuilder could not get the value for {0}.{1}.", entity.GetType().Name, member.Name)); - } - - private bool IsNullVariable(Expression expression) - { - if (expression.NodeType == ExpressionType.Constant && - TryGetConstantValue(expression, out var constResult) && - constResult == null) - { - return true; - } - - if (expression.NodeType == ExpressionType.MemberAccess && - expression is MemberExpression member && - ((TryGetPropertyValue(member, out var result) && result == null) || - (TryGetVariableValue(member, out result) && result == null))) - { - return true; - } - - return false; - } - - private string Decode(BinaryExpression expression) - { - if (IsNullVariable(expression.Right)) - { - switch (expression.NodeType) - { - case ExpressionType.Equal: return "IS"; - case ExpressionType.NotEqual: return "IS NOT"; - } - } - - switch (expression.NodeType) - { - case ExpressionType.AndAlso: return "AND"; - case ExpressionType.And: return "AND"; - case ExpressionType.Equal: return "="; - case ExpressionType.GreaterThan: return ">"; - case ExpressionType.GreaterThanOrEqual: return ">="; - case ExpressionType.LessThan: return "<"; - case ExpressionType.LessThanOrEqual: return "<="; - case ExpressionType.NotEqual: return "<>"; - case ExpressionType.OrElse: return "OR"; - case ExpressionType.Or: return "OR"; - default: throw new NotSupportedException(string.Format("{0} statement is not supported", expression.NodeType.ToString())); - } - } - - private void ParseContainsExpression(MethodCallExpression expression) - { - var list = expression.Object; - - if (list != null && (list.Type == typeof(string))) - { - ParseStringContains(expression); - return; - } - - ParseEnumerableContains(expression); - } - - private void ParseEnumerableContains(MethodCallExpression body) - { - // Fish out the list and the item to compare - // It's in a different form for arrays and Lists - var list = body.Object; - Expression item; - - if (list != null) - { - // Generic collection - item = body.Arguments[0]; - } - else - { - // Static method - // Must be Enumerable.Contains(source, item) - if (body.Method.DeclaringType != typeof(Enumerable) || body.Arguments.Count != 2) - { - throw new NotSupportedException("Unexpected form of Enumerable.Contains"); - } - - list = body.Arguments[0]; - item = body.Arguments[1]; - } - - _sb.Append('('); - - Visit(item); - - _sb.Append(" IN "); - - // hardcode the integer list if it exists to bypass parameter limit - if (item.Type == typeof(int) && TryGetRightValue(list, out var value)) - { - var items = (IEnumerable)value; - _sb.Append('('); - _sb.Append(string.Join(", ", items)); - _sb.Append(')'); - - _gotConcreteValue = true; - } - else - { - Visit(list); - } - - _sb.Append(')'); - } - - private void ParseStringContains(MethodCallExpression body) - { - _sb.Append('('); - - Visit(body.Object); - - _sb.Append(" LIKE '%' || "); - - Visit(body.Arguments[0]); - - _sb.Append(" || '%')"); - } - - private void ParseStartsWith(MethodCallExpression body) - { - _sb.Append('('); - - Visit(body.Object); - - _sb.Append(" LIKE "); - - Visit(body.Arguments[0]); - - _sb.Append(" || '%')"); - } - - private void ParseEndsWith(MethodCallExpression body) - { - _sb.Append('('); - - Visit(body.Object); - - _sb.Append(" LIKE '%' || "); - - Visit(body.Arguments[0]); - - _sb.Append(')'); - } - - public override string ToString() - { - var sql = _sb.ToString(); - - if (_requireConcreteValue && !_gotConcreteValue) - { - var e = new InvalidOperationException("WhereBuilder requires a concrete condition"); - e.Data.Add("sql", sql); - throw e; - } - - return sql; - } + public DynamicParameters Parameters { get; protected set; } } } diff --git a/src/NzbDrone.Core/Datastore/WhereBuilderPostgres.cs b/src/NzbDrone.Core/Datastore/WhereBuilderPostgres.cs new file mode 100644 index 000000000..f1854aea6 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/WhereBuilderPostgres.cs @@ -0,0 +1,387 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using Dapper; + +namespace NzbDrone.Core.Datastore +{ + public class WhereBuilderPostgres : WhereBuilder + { + protected StringBuilder _sb; + + private const DbType EnumerableMultiParameter = (DbType)(-1); + private readonly string _paramNamePrefix; + private readonly bool _requireConcreteValue = false; + private int _paramCount = 0; + private bool _gotConcreteValue = false; + + public WhereBuilderPostgres(Expression filter, bool requireConcreteValue, int seq) + { + _paramNamePrefix = string.Format("Clause{0}", seq + 1); + _requireConcreteValue = requireConcreteValue; + _sb = new StringBuilder(); + + Parameters = new DynamicParameters(); + + if (filter != null) + { + Visit(filter); + } + } + + private string AddParameter(object value, DbType? dbType = null) + { + _gotConcreteValue = true; + _paramCount++; + var name = _paramNamePrefix + "_P" + _paramCount; + Parameters.Add(name, value, dbType); + return '@' + name; + } + + protected override Expression VisitBinary(BinaryExpression expression) + { + _sb.Append('('); + + Visit(expression.Left); + + _sb.AppendFormat(" {0} ", Decode(expression)); + + Visit(expression.Right); + + _sb.Append(')'); + + return expression; + } + + protected override Expression VisitMethodCall(MethodCallExpression expression) + { + var method = expression.Method.Name; + + switch (expression.Method.Name) + { + case "Contains": + ParseContainsExpression(expression); + break; + + case "StartsWith": + ParseStartsWith(expression); + break; + + case "EndsWith": + ParseEndsWith(expression); + break; + + default: + var msg = string.Format("'{0}' expressions are not yet implemented in the where clause expression tree parser.", method); + throw new NotImplementedException(msg); + } + + return expression; + } + + protected override Expression VisitMemberAccess(MemberExpression expression) + { + var tableName = expression?.Expression?.Type != null ? TableMapping.Mapper.TableNameMapping(expression.Expression.Type) : null; + var gotValue = TryGetRightValue(expression, out var value); + + // Only use the SQL condition if the expression didn't resolve to an actual value + if (tableName != null && !gotValue) + { + _sb.Append($"\"{tableName}\".\"{expression.Member.Name.ToLower()}\""); + } + else + { + if (value != null) + { + // string is IEnumerable but we don't want to pick up that case + var type = value.GetType(); + var typeInfo = type.GetTypeInfo(); + var isEnumerable = + type != typeof(string) && ( + typeInfo.ImplementedInterfaces.Any(ti => ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) || + (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>))); + + var paramName = isEnumerable ? AddParameter(value, EnumerableMultiParameter) : AddParameter(value); + _sb.Append(paramName); + } + else + { + _gotConcreteValue = true; + _sb.Append("NULL"); + } + } + + return expression; + } + + protected override Expression VisitConstant(ConstantExpression expression) + { + if (expression.Value != null) + { + var paramName = AddParameter(expression.Value); + _sb.Append(paramName); + } + else + { + _gotConcreteValue = true; + _sb.Append("NULL"); + } + + return expression; + } + + private bool TryGetConstantValue(Expression expression, out object result) + { + result = null; + + if (expression is ConstantExpression constExp) + { + result = constExp.Value; + return true; + } + + return false; + } + + private bool TryGetPropertyValue(MemberExpression expression, out object result) + { + result = null; + + if (expression.Expression is MemberExpression nested) + { + // Value is passed in as a property on a parent entity + var container = (nested.Expression as ConstantExpression)?.Value; + + if (container == null) + { + return false; + } + + var entity = GetFieldValue(container, nested.Member); + result = GetFieldValue(entity, expression.Member); + return true; + } + + return false; + } + + private bool TryGetVariableValue(MemberExpression expression, out object result) + { + result = null; + + // Value is passed in as a variable + if (expression.Expression is ConstantExpression nested) + { + result = GetFieldValue(nested.Value, expression.Member); + return true; + } + + return false; + } + + private bool TryGetRightValue(Expression expression, out object value) + { + value = null; + + if (TryGetConstantValue(expression, out value)) + { + return true; + } + + var memberExp = expression as MemberExpression; + + if (TryGetPropertyValue(memberExp, out value)) + { + return true; + } + + if (TryGetVariableValue(memberExp, out value)) + { + return true; + } + + return false; + } + + private object GetFieldValue(object entity, MemberInfo member) + { + if (member.MemberType == MemberTypes.Field) + { + return (member as FieldInfo).GetValue(entity); + } + + if (member.MemberType == MemberTypes.Property) + { + return (member as PropertyInfo).GetValue(entity); + } + + throw new ArgumentException(string.Format("WhereBuilder could not get the value for {0}.{1}.", entity.GetType().Name, member.Name)); + } + + private bool IsNullVariable(Expression expression) + { + if (expression.NodeType == ExpressionType.Constant && + TryGetConstantValue(expression, out var constResult) && + constResult == null) + { + return true; + } + + if (expression.NodeType == ExpressionType.MemberAccess && + expression is MemberExpression member && + ((TryGetPropertyValue(member, out var result) && result == null) || + (TryGetVariableValue(member, out result) && result == null))) + { + return true; + } + + return false; + } + + private string Decode(BinaryExpression expression) + { + if (IsNullVariable(expression.Right)) + { + switch (expression.NodeType) + { + case ExpressionType.Equal: return "IS"; + case ExpressionType.NotEqual: return "IS NOT"; + } + } + + switch (expression.NodeType) + { + case ExpressionType.AndAlso: return "AND"; + case ExpressionType.And: return "AND"; + case ExpressionType.Equal: return "="; + case ExpressionType.GreaterThan: return ">"; + case ExpressionType.GreaterThanOrEqual: return ">="; + case ExpressionType.LessThan: return "<"; + case ExpressionType.LessThanOrEqual: return "<="; + case ExpressionType.NotEqual: return "<>"; + case ExpressionType.OrElse: return "OR"; + case ExpressionType.Or: return "OR"; + default: throw new NotSupportedException(string.Format("{0} statement is not supported", expression.NodeType.ToString())); + } + } + + private void ParseContainsExpression(MethodCallExpression expression) + { + var list = expression.Object; + + if (list != null && (list.Type == typeof(string))) + { + ParseStringContains(expression); + return; + } + + ParseEnumerableContains(expression); + } + + private void ParseEnumerableContains(MethodCallExpression body) + { + // Fish out the list and the item to compare + // It's in a different form for arrays and Lists + var list = body.Object; + Expression item; + + if (list != null) + { + // Generic collection + item = body.Arguments[0]; + } + else + { + // Static method + // Must be Enumerable.Contains(source, item) + if (body.Method.DeclaringType != typeof(Enumerable) || body.Arguments.Count != 2) + { + throw new NotSupportedException("Unexpected form of Enumerable.Contains"); + } + + list = body.Arguments[0]; + item = body.Arguments[1]; + } + + _sb.Append('('); + + Visit(item); + + _sb.Append(" = ANY ("); + + // hardcode the integer list if it exists to bypass parameter limit + if (item.Type == typeof(int) && TryGetRightValue(list, out var value)) + { + var items = (IEnumerable)value; + _sb.Append("('{"); + _sb.Append(string.Join(", ", items)); + _sb.Append("}')"); + + _gotConcreteValue = true; + } + else + { + Visit(list); + } + + _sb.Append("))"); + } + + private void ParseStringContains(MethodCallExpression body) + { + _sb.Append('('); + + Visit(body.Object); + + _sb.Append(" ILIKE '%' || "); + + Visit(body.Arguments[0]); + + _sb.Append(" || '%')"); + } + + private void ParseStartsWith(MethodCallExpression body) + { + _sb.Append('('); + + Visit(body.Object); + + _sb.Append(" ILIKE "); + + Visit(body.Arguments[0]); + + _sb.Append(" || '%')"); + } + + private void ParseEndsWith(MethodCallExpression body) + { + _sb.Append('('); + + Visit(body.Object); + + _sb.Append(" ILIKE '%' || "); + + Visit(body.Arguments[0]); + + _sb.Append(')'); + } + + public override string ToString() + { + var sql = _sb.ToString(); + + if (_requireConcreteValue && !_gotConcreteValue) + { + var e = new InvalidOperationException("WhereBuilder requires a concrete condition"); + e.Data.Add("sql", sql); + throw e; + } + + return sql; + } + } +} diff --git a/src/NzbDrone.Core/Datastore/WhereBuilderSqlite.cs b/src/NzbDrone.Core/Datastore/WhereBuilderSqlite.cs new file mode 100644 index 000000000..54b24d7e1 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/WhereBuilderSqlite.cs @@ -0,0 +1,387 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using Dapper; + +namespace NzbDrone.Core.Datastore +{ + public class WhereBuilderSqlite : WhereBuilder + { + protected StringBuilder _sb; + + private const DbType EnumerableMultiParameter = (DbType)(-1); + private readonly string _paramNamePrefix; + private readonly bool _requireConcreteValue = false; + private int _paramCount = 0; + private bool _gotConcreteValue = false; + + public WhereBuilderSqlite(Expression filter, bool requireConcreteValue, int seq) + { + _paramNamePrefix = string.Format("Clause{0}", seq + 1); + _requireConcreteValue = requireConcreteValue; + _sb = new StringBuilder(); + + Parameters = new DynamicParameters(); + + if (filter != null) + { + Visit(filter); + } + } + + private string AddParameter(object value, DbType? dbType = null) + { + _gotConcreteValue = true; + _paramCount++; + var name = _paramNamePrefix + "_P" + _paramCount; + Parameters.Add(name, value, dbType); + return '@' + name; + } + + protected override Expression VisitBinary(BinaryExpression expression) + { + _sb.Append('('); + + Visit(expression.Left); + + _sb.AppendFormat(" {0} ", Decode(expression)); + + Visit(expression.Right); + + _sb.Append(')'); + + return expression; + } + + protected override Expression VisitMethodCall(MethodCallExpression expression) + { + var method = expression.Method.Name; + + switch (expression.Method.Name) + { + case "Contains": + ParseContainsExpression(expression); + break; + + case "StartsWith": + ParseStartsWith(expression); + break; + + case "EndsWith": + ParseEndsWith(expression); + break; + + default: + var msg = string.Format("'{0}' expressions are not yet implemented in the where clause expression tree parser.", method); + throw new NotImplementedException(msg); + } + + return expression; + } + + protected override Expression VisitMemberAccess(MemberExpression expression) + { + var tableName = expression?.Expression?.Type != null ? TableMapping.Mapper.TableNameMapping(expression.Expression.Type) : null; + var gotValue = TryGetRightValue(expression, out var value); + + // Only use the SQL condition if the expression didn't resolve to an actual value + if (tableName != null && !gotValue) + { + _sb.Append($"\"{tableName}\".\"{expression.Member.Name}\""); + } + else + { + if (value != null) + { + // string is IEnumerable but we don't want to pick up that case + var type = value.GetType(); + var typeInfo = type.GetTypeInfo(); + var isEnumerable = + type != typeof(string) && ( + typeInfo.ImplementedInterfaces.Any(ti => ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) || + (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>))); + + var paramName = isEnumerable ? AddParameter(value, EnumerableMultiParameter) : AddParameter(value); + _sb.Append(paramName); + } + else + { + _gotConcreteValue = true; + _sb.Append("NULL"); + } + } + + return expression; + } + + protected override Expression VisitConstant(ConstantExpression expression) + { + if (expression.Value != null) + { + var paramName = AddParameter(expression.Value); + _sb.Append(paramName); + } + else + { + _gotConcreteValue = true; + _sb.Append("NULL"); + } + + return expression; + } + + private bool TryGetConstantValue(Expression expression, out object result) + { + result = null; + + if (expression is ConstantExpression constExp) + { + result = constExp.Value; + return true; + } + + return false; + } + + private bool TryGetPropertyValue(MemberExpression expression, out object result) + { + result = null; + + if (expression.Expression is MemberExpression nested) + { + // Value is passed in as a property on a parent entity + var container = (nested.Expression as ConstantExpression)?.Value; + + if (container == null) + { + return false; + } + + var entity = GetFieldValue(container, nested.Member); + result = GetFieldValue(entity, expression.Member); + return true; + } + + return false; + } + + private bool TryGetVariableValue(MemberExpression expression, out object result) + { + result = null; + + // Value is passed in as a variable + if (expression.Expression is ConstantExpression nested) + { + result = GetFieldValue(nested.Value, expression.Member); + return true; + } + + return false; + } + + private bool TryGetRightValue(Expression expression, out object value) + { + value = null; + + if (TryGetConstantValue(expression, out value)) + { + return true; + } + + var memberExp = expression as MemberExpression; + + if (TryGetPropertyValue(memberExp, out value)) + { + return true; + } + + if (TryGetVariableValue(memberExp, out value)) + { + return true; + } + + return false; + } + + private object GetFieldValue(object entity, MemberInfo member) + { + if (member.MemberType == MemberTypes.Field) + { + return (member as FieldInfo).GetValue(entity); + } + + if (member.MemberType == MemberTypes.Property) + { + return (member as PropertyInfo).GetValue(entity); + } + + throw new ArgumentException(string.Format("WhereBuilder could not get the value for {0}.{1}.", entity.GetType().Name, member.Name)); + } + + private bool IsNullVariable(Expression expression) + { + if (expression.NodeType == ExpressionType.Constant && + TryGetConstantValue(expression, out var constResult) && + constResult == null) + { + return true; + } + + if (expression.NodeType == ExpressionType.MemberAccess && + expression is MemberExpression member && + ((TryGetPropertyValue(member, out var result) && result == null) || + (TryGetVariableValue(member, out result) && result == null))) + { + return true; + } + + return false; + } + + private string Decode(BinaryExpression expression) + { + if (IsNullVariable(expression.Right)) + { + switch (expression.NodeType) + { + case ExpressionType.Equal: return "IS"; + case ExpressionType.NotEqual: return "IS NOT"; + } + } + + switch (expression.NodeType) + { + case ExpressionType.AndAlso: return "AND"; + case ExpressionType.And: return "AND"; + case ExpressionType.Equal: return "="; + case ExpressionType.GreaterThan: return ">"; + case ExpressionType.GreaterThanOrEqual: return ">="; + case ExpressionType.LessThan: return "<"; + case ExpressionType.LessThanOrEqual: return "<="; + case ExpressionType.NotEqual: return "<>"; + case ExpressionType.OrElse: return "OR"; + case ExpressionType.Or: return "OR"; + default: throw new NotSupportedException(string.Format("{0} statement is not supported", expression.NodeType.ToString())); + } + } + + private void ParseContainsExpression(MethodCallExpression expression) + { + var list = expression.Object; + + if (list != null && (list.Type == typeof(string))) + { + ParseStringContains(expression); + return; + } + + ParseEnumerableContains(expression); + } + + private void ParseEnumerableContains(MethodCallExpression body) + { + // Fish out the list and the item to compare + // It's in a different form for arrays and Lists + var list = body.Object; + Expression item; + + if (list != null) + { + // Generic collection + item = body.Arguments[0]; + } + else + { + // Static method + // Must be Enumerable.Contains(source, item) + if (body.Method.DeclaringType != typeof(Enumerable) || body.Arguments.Count != 2) + { + throw new NotSupportedException("Unexpected form of Enumerable.Contains"); + } + + list = body.Arguments[0]; + item = body.Arguments[1]; + } + + _sb.Append('('); + + Visit(item); + + _sb.Append(" IN "); + + // hardcode the integer list if it exists to bypass parameter limit + if (item.Type == typeof(int) && TryGetRightValue(list, out var value)) + { + var items = (IEnumerable)value; + _sb.Append('('); + _sb.Append(string.Join(", ", items)); + _sb.Append(')'); + + _gotConcreteValue = true; + } + else + { + Visit(list); + } + + _sb.Append(')'); + } + + private void ParseStringContains(MethodCallExpression body) + { + _sb.Append('('); + + Visit(body.Object); + + _sb.Append(" LIKE '%' || "); + + Visit(body.Arguments[0]); + + _sb.Append(" || '%')"); + } + + private void ParseStartsWith(MethodCallExpression body) + { + _sb.Append('('); + + Visit(body.Object); + + _sb.Append(" LIKE "); + + Visit(body.Arguments[0]); + + _sb.Append(" || '%')"); + } + + private void ParseEndsWith(MethodCallExpression body) + { + _sb.Append('('); + + Visit(body.Object); + + _sb.Append(" LIKE '%' || "); + + Visit(body.Arguments[0]); + + _sb.Append(')'); + } + + public override string ToString() + { + var sql = _sb.ToString(); + + if (_requireConcreteValue && !_gotConcreteValue) + { + var e = new InvalidOperationException("WhereBuilder requires a concrete condition"); + e.Data.Add("sql", sql); + throw e; + } + + return sql; + } + } +} diff --git a/src/NzbDrone.Core/History/HistoryRepository.cs b/src/NzbDrone.Core/History/HistoryRepository.cs index cd83e5625..e90888925 100644 --- a/src/NzbDrone.Core/History/HistoryRepository.cs +++ b/src/NzbDrone.Core/History/HistoryRepository.cs @@ -49,16 +49,16 @@ namespace NzbDrone.Core.History public List FindDownloadHistory(int movieId, QualityModel quality) { - var allowed = new[] { MovieHistoryEventType.Grabbed, MovieHistoryEventType.DownloadFailed, MovieHistoryEventType.DownloadFolderImported }; + var allowed = new[] { (int)MovieHistoryEventType.Grabbed, (int)MovieHistoryEventType.DownloadFailed, (int)MovieHistoryEventType.DownloadFolderImported }; return Query(h => h.MovieId == movieId && h.Quality == quality && - allowed.Contains(h.EventType)); + allowed.Contains((int)h.EventType)); } public List GetByMovieId(int movieId, MovieHistoryEventType? eventType) { - var builder = new SqlBuilder() + var builder = new SqlBuilder(_database.DatabaseType) .Join((h, m) => h.MovieId == m.Id) .Join((m, p) => m.ProfileId == p.Id) .Where(h => h.MovieId == movieId); @@ -76,7 +76,7 @@ namespace NzbDrone.Core.History Delete(c => movieIds.Contains(c.MovieId)); } - protected override SqlBuilder PagedBuilder() => new SqlBuilder() + protected override SqlBuilder PagedBuilder() => new SqlBuilder(_database.DatabaseType) .Join((h, m) => h.MovieId == m.Id) .Join((m, p) => m.ProfileId == p.Id); @@ -97,7 +97,7 @@ namespace NzbDrone.Core.History public List Since(DateTime date, MovieHistoryEventType? eventType) { - var builder = new SqlBuilder() + var builder = new SqlBuilder(_database.DatabaseType) .Join((h, m) => h.MovieId == m.Id) .Join((m, p) => m.ProfileId == p.Id) .Where(x => x.Date >= date); diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAbsolutePathMetadataFiles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAbsolutePathMetadataFiles.cs index 1293d4f07..8d50f05de 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAbsolutePathMetadataFiles.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAbsolutePathMetadataFiles.cs @@ -1,4 +1,4 @@ -using Dapper; +using Dapper; using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Housekeeping.Housekeepers @@ -16,16 +16,32 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM MetadataFiles - WHERE Id IN ( - SELECT Id FROM MetadataFiles - WHERE RelativePath + if (_database.DatabaseType == DatabaseType.PostgreSQL) + { + mapper.Execute(@"DELETE FROM ""MetadataFiles"" + WHERE ""Id"" = ANY ( + SELECT ""Id"" FROM ""MetadataFiles"" + WHERE ""RelativePath"" + LIKE '_:\\%' + OR ""RelativePath"" + LIKE '\\%' + OR ""RelativePath"" + LIKE '/%' + )"); + } + else + { + mapper.Execute(@"DELETE FROM ""MetadataFiles"" + WHERE ""Id"" IN ( + SELECT ""Id"" FROM ""MetadataFiles"" + WHERE ""RelativePath"" LIKE '_:\%' - OR RelativePath + OR ""RelativePath"" LIKE '\%' - OR RelativePath + OR ""RelativePath"" LIKE '/%' )"); + } } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAdditionalNamingSpecs.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAdditionalNamingSpecs.cs index a1d9c56b7..d9c61e790 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAdditionalNamingSpecs.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAdditionalNamingSpecs.cs @@ -16,9 +16,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM NamingConfig - WHERE ID NOT IN ( - SELECT ID FROM NamingConfig + mapper.Execute(@"DELETE FROM ""NamingConfig"" + WHERE ""Id"" NOT IN ( + SELECT ""Id"" FROM ""NamingConfig"" LIMIT 1)"); } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAdditionalUsers.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAdditionalUsers.cs index 4460ac83c..3845110f4 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAdditionalUsers.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupAdditionalUsers.cs @@ -16,9 +16,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM Users - WHERE ID NOT IN ( - SELECT ID FROM Users + mapper.Execute(@"DELETE FROM ""Users"" + WHERE ""Id"" NOT IN ( + SELECT ""Id"" FROM ""Users"" LIMIT 1)"); } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupDownloadClientUnavailablePendingReleases.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupDownloadClientUnavailablePendingReleases.cs index a1071af74..ea3ffeea9 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupDownloadClientUnavailablePendingReleases.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupDownloadClientUnavailablePendingReleases.cs @@ -18,14 +18,28 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { var mapper = _database.OpenConnection(); - mapper.Execute(@"DELETE FROM PendingReleases - WHERE Added < @TwoWeeksAgo - AND REASON IN @Reasons", + if (_database.DatabaseType == DatabaseType.PostgreSQL) + { + mapper.Execute(@"DELETE FROM ""PendingReleases"" + WHERE ""Added"" < @TwoWeeksAgo + AND ""Reason"" = ANY (@Reasons)", new { TwoWeeksAgo = DateTime.UtcNow.AddDays(-14), Reasons = new[] { (int)PendingReleaseReason.DownloadClientUnavailable, (int)PendingReleaseReason.Fallback } }); + } + else + { + mapper.Execute(@"DELETE FROM ""PendingReleases"" + WHERE ""Added"" < @TwoWeeksAgo + AND ""REASON"" IN @Reasons", + new + { + TwoWeeksAgo = DateTime.UtcNow.AddDays(-14), + Reasons = new[] { (int)PendingReleaseReason.DownloadClientUnavailable, (int)PendingReleaseReason.Fallback } + }); + } } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupDuplicateMetadataFiles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupDuplicateMetadataFiles.cs index 43bab4d8e..c5d5537b1 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupDuplicateMetadataFiles.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupDuplicateMetadataFiles.cs @@ -22,12 +22,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM MetadataFiles - WHERE Id IN ( - SELECT Id FROM MetadataFiles - WHERE Type = 1 - GROUP BY MovieId, Consumer - HAVING COUNT(MovieId) > 1 + mapper.Execute(@"DELETE FROM ""MetadataFiles"" + WHERE ""Id"" IN ( + SELECT MIN(""Id"") FROM ""MetadataFiles"" + WHERE ""Type"" = 1 + GROUP BY ""MovieId"", ""Consumer"" + HAVING COUNT(""MovieId"") > 1 )"); } } @@ -36,12 +36,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM MetadataFiles - WHERE Id IN ( - SELECT Id FROM MetadataFiles - WHERE Type = 1 - GROUP BY MovieFileId, Consumer - HAVING COUNT(MovieFileId) > 1 + mapper.Execute(@"DELETE FROM ""MetadataFiles"" + WHERE ""Id"" IN ( + SELECT MIN(""Id"") FROM ""MetadataFiles"" + WHERE ""Type"" = 1 + GROUP BY ""MovieFileId"", ""Consumer"" + HAVING COUNT(""MovieFileId"") > 1 )"); } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitles.cs index b535eab20..2f26a28c8 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitles.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitles.cs @@ -16,12 +16,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM AlternativeTitles - WHERE Id IN ( - SELECT AlternativeTitles.Id FROM AlternativeTitles - LEFT OUTER JOIN Movies - ON AlternativeTitles.MovieId = Movies.Id - WHERE Movies.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""AlternativeTitles"" + WHERE ""Id"" IN ( + SELECT ""AlternativeTitles"".""Id"" FROM ""AlternativeTitles"" + LEFT OUTER JOIN ""Movies"" + ON ""AlternativeTitles"".""MovieId"" = ""Movies"".""Id"" + WHERE ""Movies"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedBlocklist.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedBlocklist.cs index aa62d50e9..f43f8f20e 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedBlocklist.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedBlocklist.cs @@ -16,12 +16,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM Blocklist - WHERE Id IN ( - SELECT Blocklist.Id FROM Blocklist - LEFT OUTER JOIN Movies - ON Blocklist.MovieId = Movies.Id - WHERE Movies.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""Blocklist"" + WHERE ""Id"" IN ( + SELECT ""Blocklist"".""Id"" FROM ""Blocklist"" + LEFT OUTER JOIN ""Movies"" + ON ""Blocklist"".""MovieId"" = ""Movies"".""Id"" + WHERE ""Movies"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedCredits.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedCredits.cs index 2bd61c5a3..57eef9ad0 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedCredits.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedCredits.cs @@ -16,12 +16,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM Credits - WHERE Id IN ( - SELECT Credits.Id FROM Credits - LEFT OUTER JOIN Movies - ON Credits.MovieId = Movies.Id - WHERE Movies.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""Credits"" + WHERE ""Id"" IN ( + SELECT ""Credits"".""Id"" FROM ""Credits"" + LEFT OUTER JOIN ""Movies"" + ON ""Credits"".""MovieId"" = ""Movies"".""Id"" + WHERE ""Movies"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedDownloadClientStatus.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedDownloadClientStatus.cs index a5f584797..846ddae2f 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedDownloadClientStatus.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedDownloadClientStatus.cs @@ -16,12 +16,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { var mapper = _database.OpenConnection(); - mapper.Execute(@"DELETE FROM DownloadClientStatus - WHERE Id IN ( - SELECT DownloadClientStatus.Id FROM DownloadClientStatus - LEFT OUTER JOIN DownloadClients - ON DownloadClientStatus.ProviderId = DownloadClients.Id - WHERE DownloadClients.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""DownloadClientStatus"" + WHERE ""Id"" IN ( + SELECT ""DownloadClientStatus"".""Id"" FROM ""DownloadClientStatus"" + LEFT OUTER JOIN ""DownloadClients"" + ON ""DownloadClientStatus"".""ProviderId"" = ""DownloadClients"".""Id"" + WHERE ""DownloadClients"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedExtraFiles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedExtraFiles.cs index 1a16d0499..66d7a01e5 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedExtraFiles.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedExtraFiles.cs @@ -22,12 +22,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM ExtraFiles - WHERE Id IN ( - SELECT ExtraFiles.Id FROM ExtraFiles - LEFT OUTER JOIN Movies - ON ExtraFiles.MovieId = Movies.Id - WHERE Movies.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""ExtraFiles"" + WHERE ""Id"" IN ( + SELECT ""ExtraFiles"".""Id"" FROM ""ExtraFiles"" + LEFT OUTER JOIN ""Movies"" + ON ""ExtraFiles"".""MovieId"" = ""Movies"".""Id"" + WHERE ""Movies"".""Id"" IS NULL)"); } } @@ -35,13 +35,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM ExtraFiles - WHERE Id IN ( - SELECT ExtraFiles.Id FROM ExtraFiles - LEFT OUTER JOIN MovieFiles - ON ExtraFiles.MovieFileId = MovieFiles.Id - WHERE ExtraFiles.MovieFileId > 0 - AND MovieFiles.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""ExtraFiles"" + WHERE ""Id"" IN ( + SELECT ""ExtraFiles"".""Id"" FROM ""ExtraFiles"" + LEFT OUTER JOIN ""MovieFiles"" + ON ""ExtraFiles"".""MovieFileId"" = ""MovieFiles"".""Id"" + WHERE ""ExtraFiles"".""MovieFileId"" > 0 + AND ""MovieFiles"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedHistoryItems.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedHistoryItems.cs index 34a8d03a1..ffe5dd6a2 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedHistoryItems.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedHistoryItems.cs @@ -21,12 +21,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM History - WHERE Id IN ( - SELECT History.Id FROM History - LEFT OUTER JOIN Movies - ON History.MovieId = Movies.Id - WHERE Movies.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""History"" + WHERE ""Id"" IN ( + SELECT ""History"".""Id"" FROM ""History"" + LEFT OUTER JOIN ""Movies"" + ON ""History"".""MovieId"" = ""Movies"".""Id"" + WHERE ""Movies"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedIndexerStatus.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedIndexerStatus.cs index 039db9b52..059f059e4 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedIndexerStatus.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedIndexerStatus.cs @@ -16,12 +16,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM IndexerStatus - WHERE Id IN ( - SELECT IndexerStatus.Id FROM IndexerStatus - LEFT OUTER JOIN Indexers - ON IndexerStatus.ProviderId = Indexers.Id - WHERE Indexers.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""IndexerStatus"" + WHERE ""Id"" IN ( + SELECT ""IndexerStatus"".""Id"" FROM ""IndexerStatus"" + LEFT OUTER JOIN ""Indexers"" + ON ""IndexerStatus"".""ProviderId"" = ""Indexers"".""Id"" + WHERE ""Indexers"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMetadataFiles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMetadataFiles.cs index 4791d355b..de9aa98b4 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMetadataFiles.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMetadataFiles.cs @@ -23,12 +23,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM MetadataFiles - WHERE Id IN ( - SELECT MetadataFiles.Id FROM MetadataFiles - LEFT OUTER JOIN Movies - ON MetadataFiles.MovieId = Movies.Id - WHERE Movies.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""MetadataFiles"" + WHERE ""Id"" IN ( + SELECT ""MetadataFiles"".""Id"" FROM ""MetadataFiles"" + LEFT OUTER JOIN ""Movies"" + ON ""MetadataFiles"".""MovieId"" = ""Movies"".""Id"" + WHERE ""Movies"".""Id"" IS NULL)"); } } @@ -36,13 +36,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM MetadataFiles - WHERE Id IN ( - SELECT MetadataFiles.Id FROM MetadataFiles - LEFT OUTER JOIN MovieFiles - ON MetadataFiles.MovieFileId = MovieFiles.Id - WHERE MetadataFiles.MovieFileId > 0 - AND MovieFiles.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""MetadataFiles"" + WHERE ""Id"" IN ( + SELECT ""MetadataFiles"".""Id"" FROM ""MetadataFiles"" + LEFT OUTER JOIN ""MovieFiles"" + ON ""MetadataFiles"".""MovieFileId"" = ""MovieFiles"".""Id"" + WHERE ""MetadataFiles"".""MovieFileId"" > 0 + AND ""MovieFiles"".""Id"" IS NULL)"); } } @@ -50,11 +50,11 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM MetadataFiles - WHERE Id IN ( - SELECT Id FROM MetadataFiles - WHERE Type IN (1, 2) - AND MovieFileId = 0)"); + mapper.Execute(@"DELETE FROM ""MetadataFiles"" + WHERE ""Id"" IN ( + SELECT ""Id"" FROM ""MetadataFiles"" + WHERE ""Type"" IN (1, 2) + AND ""MovieFileId"" = 0)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieFiles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieFiles.cs index ee94f857e..196d3efc4 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieFiles.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieFiles.cs @@ -16,12 +16,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM MovieFiles - WHERE Id IN ( - SELECT MovieFiles.Id FROM MovieFiles - LEFT OUTER JOIN Movies - ON MovieFiles.Id = Movies.MovieFileId - WHERE Movies.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""MovieFiles"" + WHERE ""Id"" IN ( + SELECT ""MovieFiles"".""Id"" FROM ""MovieFiles"" + LEFT OUTER JOIN ""Movies"" + ON ""MovieFiles"".""Id"" = ""Movies"".""MovieFileId"" + WHERE ""Movies"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieMovieFileIds.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieMovieFileIds.cs index 9bded13b1..f99a1417f 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieMovieFileIds.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieMovieFileIds.cs @@ -16,13 +16,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"UPDATE Movies - SET MovieFileId = 0 - WHERE Id IN ( - SELECT Movies.Id FROM Movies - LEFT OUTER JOIN MovieFiles - ON Movies.MovieFileId = MovieFiles.Id - WHERE MovieFiles.Id IS NULL)"); + mapper.Execute(@"UPDATE ""Movies"" + SET ""MovieFileId"" = 0 + WHERE ""Id"" IN ( + SELECT ""Movies"".""Id"" FROM ""Movies"" + LEFT OUTER JOIN ""MovieFiles"" + ON ""Movies"".""MovieFileId"" = ""MovieFiles"".""Id"" + WHERE ""MovieFiles"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslations.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslations.cs index efb55262a..35500d034 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslations.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslations.cs @@ -16,12 +16,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM MovieTranslations - WHERE Id IN ( - SELECT MovieTranslations.Id FROM MovieTranslations - LEFT OUTER JOIN Movies - ON MovieTranslations.MovieId = Movies.Id - WHERE Movies.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""MovieTranslations"" + WHERE ""Id"" IN ( + SELECT ""MovieTranslations"".""Id"" FROM ""MovieTranslations"" + LEFT OUTER JOIN ""Movies"" + ON ""MovieTranslations"".""MovieId"" = ""Movies"".""Id"" + WHERE ""Movies"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedPendingReleases.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedPendingReleases.cs index 4cd347e30..d2b2afd7f 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedPendingReleases.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedPendingReleases.cs @@ -16,12 +16,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM PendingReleases - WHERE Id IN ( - SELECT PendingReleases.Id FROM PendingReleases - LEFT OUTER JOIN Movies - ON PendingReleases.MovieId = Movies.Id - WHERE Movies.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""PendingReleases"" + WHERE ""Id"" IN ( + SELECT ""PendingReleases"".""Id"" FROM ""PendingReleases"" + LEFT OUTER JOIN ""Movies"" + ON ""PendingReleases"".""MovieId"" = ""Movies"".""Id"" + WHERE ""Movies"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedSubtitleFiles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedSubtitleFiles.cs index 28c61aea1..cf88a30bb 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedSubtitleFiles.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedSubtitleFiles.cs @@ -22,12 +22,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM SubtitleFiles - WHERE Id IN ( - SELECT SubtitleFiles.Id FROM SubtitleFiles - LEFT OUTER JOIN Movies - ON SubtitleFiles.MovieId = Movies.Id - WHERE Movies.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""SubtitleFiles"" + WHERE ""Id"" IN ( + SELECT ""SubtitleFiles"".""Id"" FROM ""SubtitleFiles"" + LEFT OUTER JOIN ""Movies"" + ON ""SubtitleFiles"".""MovieId"" = ""Movies"".""Id"" + WHERE ""Movies"".""Id"" IS NULL)"); } } @@ -35,13 +35,13 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"DELETE FROM SubtitleFiles - WHERE Id IN ( - SELECT SubtitleFiles.Id FROM SubtitleFiles - LEFT OUTER JOIN MovieFiles - ON SubtitleFiles.MovieFileId = MovieFiles.Id - WHERE SubtitleFiles.MovieFileId > 0 - AND MovieFiles.Id IS NULL)"); + mapper.Execute(@"DELETE FROM ""SubtitleFiles"" + WHERE ""Id"" IN ( + SELECT ""SubtitleFiles"".""Id"" FROM ""SubtitleFiles"" + LEFT OUTER JOIN ""MovieFiles"" + ON ""SubtitleFiles"".""MovieFileId"" = ""MovieFiles"".""Id"" + WHERE ""SubtitleFiles"".""MovieFileId"" > 0 + AND ""MovieFiles"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupUnusedTags.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupUnusedTags.cs index e354c3ddb..931bc1cc2 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupUnusedTags.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupUnusedTags.cs @@ -25,14 +25,28 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers .Distinct() .ToList(); - var usedTagsList = usedTags.Select(d => d.ToString()).Join(","); + if (usedTags.Any()) + { + var usedTagsList = usedTags.Select(d => d.ToString()).Join(","); - mapper.Execute($"DELETE FROM Tags WHERE NOT Id IN ({usedTagsList})"); + if (_database.DatabaseType == DatabaseType.PostgreSQL) + { + mapper.Execute($"DELETE FROM \"Tags\" WHERE NOT \"Id\" = ANY (\'{{{usedTagsList}}}\'::int[])"); + } + else + { + mapper.Execute($"DELETE FROM \"Tags\" WHERE NOT \"Id\" IN ({usedTagsList})"); + } + } + else + { + mapper.Execute("DELETE FROM \"Tags\""); + } } private int[] GetUsedTags(string table, IDbConnection mapper) { - return mapper.Query>($"SELECT DISTINCT Tags FROM {table} WHERE NOT Tags = '[]' AND NOT Tags IS NULL") + return mapper.Query>($"SELECT DISTINCT \"Tags\" FROM \"{table}\" WHERE NOT \"Tags\" = '[]' AND NOT \"Tags\" IS NULL") .SelectMany(x => x) .Distinct() .ToArray(); diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/FixFutureRunScheduledTasks.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/FixFutureRunScheduledTasks.cs index 82a7af7fa..47333e596 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/FixFutureRunScheduledTasks.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/FixFutureRunScheduledTasks.cs @@ -26,9 +26,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers using (var mapper = _database.OpenConnection()) { - mapper.Execute(@"UPDATE ScheduledTasks - SET LastExecution = @time - WHERE LastExecution > @time", + mapper.Execute(@"UPDATE ""ScheduledTasks"" + SET ""LastExecution"" = @time + WHERE ""LastExecution"" > @time", new { time = DateTime.UtcNow }); } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/FixWronglyMatchedMovieFiles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/FixWronglyMatchedMovieFiles.cs index bcaf44fbb..33ed6f629 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/FixWronglyMatchedMovieFiles.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/FixWronglyMatchedMovieFiles.cs @@ -15,11 +15,11 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { /*var mapper = _database.GetDataMapper(); - mapper.Execute(@"UPDATE Movies - SET MovieFileId = - (Select Id FROM MovieFiles WHERE Movies.Id == MovieFiles.MovieId) - WHERE MovieFileId != - (SELECT Id FROM MovieFiles WHERE Movies.Id == MovieFiles.MovieId)");*/ + mapper.Execute(@"UPDATE ""Movies"" + SET ""MovieFileId"" = + (Select ""Id"" FROM ""MovieFiles"" WHERE ""Movies"".""Id"" == ""MovieFiles"".""MovieId"") + WHERE ""MovieFileId"" != + (SELECT ""Id"" FROM ""MovieFiles"" WHERE ""Movies"".""Id"" == ""MovieFiles"".""MovieId"")");*/ } } } diff --git a/src/NzbDrone.Core/Instrumentation/DatabaseTarget.cs b/src/NzbDrone.Core/Instrumentation/DatabaseTarget.cs index f761f3f7c..f8348c35e 100644 --- a/src/NzbDrone.Core/Instrumentation/DatabaseTarget.cs +++ b/src/NzbDrone.Core/Instrumentation/DatabaseTarget.cs @@ -1,9 +1,11 @@ -using System.Data; +using System; +using System.Data; using System.Data.SQLite; using NLog; using NLog.Common; using NLog.Config; using NLog.Targets; +using Npgsql; using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Datastore; using NzbDrone.Core.Lifecycle; @@ -13,7 +15,7 @@ namespace NzbDrone.Core.Instrumentation { public class DatabaseTarget : TargetWithLayout, IHandle { - private const string INSERT_COMMAND = "INSERT INTO [Logs]([Message],[Time],[Logger],[Exception],[ExceptionType],[Level]) " + + private const string INSERT_COMMAND = "INSERT INTO \"Logs\" (\"Message\",\"Time\",\"Logger\",\"Exception\",\"ExceptionType\",\"Level\") " + "VALUES(@Message,@Time,@Logger,@Exception,@ExceptionType,@Level)"; private readonly IConnectionStringFactory _connectionStringFactory; @@ -83,23 +85,16 @@ namespace NzbDrone.Core.Instrumentation log.Level = logEvent.Level.Name; - using (var connection = - SQLiteFactory.Instance.CreateConnection()) + var connectionString = _connectionStringFactory.LogDbConnectionString; + + //TODO: Probably need more robust way to differentiate what's being used + if (connectionString.Contains(".db")) { - connection.ConnectionString = _connectionStringFactory.LogDbConnectionString; - connection.Open(); - using (var sqlCommand = connection.CreateCommand()) - { - sqlCommand.CommandText = INSERT_COMMAND; - sqlCommand.Parameters.Add(new SQLiteParameter("Message", DbType.String) { Value = log.Message }); - sqlCommand.Parameters.Add(new SQLiteParameter("Time", DbType.DateTime) { Value = log.Time.ToUniversalTime() }); - sqlCommand.Parameters.Add(new SQLiteParameter("Logger", DbType.String) { Value = log.Logger }); - sqlCommand.Parameters.Add(new SQLiteParameter("Exception", DbType.String) { Value = log.Exception }); - sqlCommand.Parameters.Add(new SQLiteParameter("ExceptionType", DbType.String) { Value = log.ExceptionType }); - sqlCommand.Parameters.Add(new SQLiteParameter("Level", DbType.String) { Value = log.Level }); - - sqlCommand.ExecuteNonQuery(); - } + WriteSqliteLog(log, connectionString); + } + else + { + WritePostgresLog(log, connectionString); } } catch (SQLiteException ex) @@ -109,6 +104,48 @@ namespace NzbDrone.Core.Instrumentation } } + private void WritePostgresLog(Log log, string connectionString) + { + using (var connection = + new NpgsqlConnection(connectionString)) + { + connection.Open(); + using (var sqlCommand = connection.CreateCommand()) + { + sqlCommand.CommandText = INSERT_COMMAND; + sqlCommand.Parameters.Add(new NpgsqlParameter("Message", DbType.String) { Value = log.Message }); + sqlCommand.Parameters.Add(new NpgsqlParameter("Time", DbType.DateTime) { Value = log.Time.ToUniversalTime() }); + sqlCommand.Parameters.Add(new NpgsqlParameter("Logger", DbType.String) { Value = log.Logger }); + sqlCommand.Parameters.Add(new NpgsqlParameter("Exception", DbType.String) { Value = log.Exception == null ? DBNull.Value : log.Exception }); + sqlCommand.Parameters.Add(new NpgsqlParameter("ExceptionType", DbType.String) { Value = log.ExceptionType == null ? DBNull.Value : log.ExceptionType }); + sqlCommand.Parameters.Add(new NpgsqlParameter("Level", DbType.String) { Value = log.Level }); + + sqlCommand.ExecuteNonQuery(); + } + } + } + + private void WriteSqliteLog(Log log, string connectionString) + { + using (var connection = + SQLiteFactory.Instance.CreateConnection()) + { + connection.ConnectionString = connectionString; + connection.Open(); + using (var sqlCommand = connection.CreateCommand()) + { + sqlCommand.CommandText = INSERT_COMMAND; + sqlCommand.Parameters.Add(new SQLiteParameter("Message", DbType.String) { Value = log.Message }); + sqlCommand.Parameters.Add(new SQLiteParameter("Time", DbType.DateTime) { Value = log.Time.ToUniversalTime() }); + sqlCommand.Parameters.Add(new SQLiteParameter("Logger", DbType.String) { Value = log.Logger }); + sqlCommand.Parameters.Add(new SQLiteParameter("Exception", DbType.String) { Value = log.Exception }); + sqlCommand.Parameters.Add(new SQLiteParameter("ExceptionType", DbType.String) { Value = log.ExceptionType }); + sqlCommand.Parameters.Add(new SQLiteParameter("Level", DbType.String) { Value = log.Level }); + sqlCommand.ExecuteNonQuery(); + } + } + } + public void Handle(ApplicationShutdownRequested message) { if (LogManager.Configuration?.LoggingRules?.Contains(Rule) == true) diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 15dcbe8ef..ed11b2abb 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -177,6 +177,7 @@ "CutoffFormatScoreHelpText": "Once this custom format score is reached Radarr will no longer download movies", "CutoffHelpText": "Once this quality is reached Radarr will no longer download movies", "CutoffUnmet": "Cut-off Unmet", + "Database": "Database", "Date": "Date", "Dates": "Dates", "Day": "Day", diff --git a/src/NzbDrone.Core/Messaging/Commands/CommandRepository.cs b/src/NzbDrone.Core/Messaging/Commands/CommandRepository.cs index 1bf894ecc..d41f2fbba 100644 --- a/src/NzbDrone.Core/Messaging/Commands/CommandRepository.cs +++ b/src/NzbDrone.Core/Messaging/Commands/CommandRepository.cs @@ -31,7 +31,7 @@ namespace NzbDrone.Core.Messaging.Commands public void OrphanStarted() { - var sql = @"UPDATE Commands SET Status = @Orphaned, EndedAt = @Ended WHERE Status = @Started"; + var sql = @"UPDATE ""Commands"" SET ""Status"" = @Orphaned, ""EndedAt"" = @Ended WHERE ""Status"" = @Started"; var args = new { Orphaned = (int)CommandStatus.Orphaned, diff --git a/src/NzbDrone.Core/Movies/MovieRepository.cs b/src/NzbDrone.Core/Movies/MovieRepository.cs index 777cf50b6..8844f0539 100644 --- a/src/NzbDrone.Core/Movies/MovieRepository.cs +++ b/src/NzbDrone.Core/Movies/MovieRepository.cs @@ -49,7 +49,7 @@ namespace NzbDrone.Core.Movies _alternativeTitleRepository = alternativeTitleRepository; } - protected override SqlBuilder Builder() => new SqlBuilder() + protected override SqlBuilder Builder() => new SqlBuilder(_database.DatabaseType) .Join((m, p) => m.ProfileId == p.Id) .LeftJoin((m, t) => m.Id == t.MovieId) .LeftJoin((m, f) => m.Id == f.MovieId); @@ -94,7 +94,7 @@ namespace NzbDrone.Core.Movies { // the skips the join on profile and alternative title and populates manually // to avoid repeatedly deserializing the same profile / movie - var builder = new SqlBuilder() + var builder = new SqlBuilder(_database.DatabaseType) .LeftJoin((m, f) => m.MovieFileId == f.Id); var profiles = _profileRepository.All().ToDictionary(x => x.Id); @@ -142,12 +142,26 @@ namespace NzbDrone.Core.Movies { var movieDictionary = new Dictionary(); - var builder = new SqlBuilder() + SqlBuilder builder; + + if (_database.DatabaseType == DatabaseType.PostgreSQL) + { + builder = new SqlBuilder(_database.DatabaseType) + .LeftJoin((m, t) => m.Id == t.MovieId) + .LeftJoin((m, f) => m.Id == f.MovieId) + .LeftJoin((m, tr) => m.Id == tr.MovieId) + .Join((m, p) => m.ProfileId == p.Id) + .WherePostgres(x => titles.Contains(x.CleanTitle)); + } + else + { + builder = new SqlBuilder(_database.DatabaseType) .LeftJoin((m, t) => m.Id == t.MovieId) .LeftJoin((m, f) => m.Id == f.MovieId) .LeftJoin((m, tr) => m.Id == tr.MovieId) .Join((m, p) => m.ProfileId == p.Id) .Where(x => titles.Contains(x.CleanTitle)); + } _ = _database.QueryJoined( builder, @@ -160,12 +174,26 @@ namespace NzbDrone.Core.Movies { var movieDictionary = new Dictionary(); - var builder = new SqlBuilder() + SqlBuilder builder; + + if (_database.DatabaseType == DatabaseType.PostgreSQL) + { + builder = new SqlBuilder(_database.DatabaseType) + .LeftJoin((m, p) => m.ProfileId == p.Id) + .LeftJoin((m, f) => m.Id == f.MovieId) + .LeftJoin((m, tr) => m.Id == tr.MovieId) + .Join((t, m) => t.MovieId == m.Id) + .WherePostgres(x => titles.Contains(x.CleanTitle)); + } + else + { + builder = new SqlBuilder(_database.DatabaseType) .LeftJoin((t, m) => t.MovieId == m.Id) .LeftJoin((m, f) => m.Id == f.MovieId) .LeftJoin((m, tr) => m.Id == tr.MovieId) .Join((m, p) => m.ProfileId == p.Id) .Where(x => titles.Contains(x.CleanTitle)); + } _ = _database.QueryJoined( builder, @@ -182,12 +210,26 @@ namespace NzbDrone.Core.Movies { var movieDictionary = new Dictionary(); - var builder = new SqlBuilder() + SqlBuilder builder; + + if (_database.DatabaseType == DatabaseType.PostgreSQL) + { + builder = new SqlBuilder(_database.DatabaseType) + .LeftJoin((m, p) => m.ProfileId == p.Id) + .LeftJoin((m, t) => m.Id == t.MovieId) + .LeftJoin((m, f) => m.Id == f.MovieId) + .Join((tr, m) => tr.MovieId == m.Id) + .WherePostgres(x => titles.Contains(x.CleanTitle)); + } + else + { + builder = new SqlBuilder(_database.DatabaseType) .LeftJoin((tr, m) => tr.MovieId == m.Id) .LeftJoin((m, t) => m.Id == t.MovieId) .LeftJoin((m, f) => m.Id == f.MovieId) .Join((m, p) => m.ProfileId == p.Id) .Where(x => titles.Contains(x.CleanTitle)); + } _ = _database.QueryJoined( builder, @@ -294,7 +336,7 @@ namespace NzbDrone.Core.Movies { using (var conn = _database.OpenConnection()) { - var strSql = "SELECT Id AS [Key], Path AS [Value] FROM Movies"; + var strSql = "SELECT \"Id\" AS \"Key\", \"Path\" AS \"Value\" FROM \"Movies\""; return conn.Query>(strSql).ToDictionary(x => x.Key, x => x.Value); } } @@ -303,7 +345,7 @@ namespace NzbDrone.Core.Movies { using (var conn = _database.OpenConnection()) { - var strSql = "SELECT Id AS [Key], TitleSlug AS [Value] FROM Movies"; + var strSql = "SELECT \"Id\" AS \"Key\", \"TitleSlug\" AS \"Value\" FROM \"Movies\""; return conn.Query>(strSql).ToDictionary(x => x.Key, x => x.Value); } } @@ -312,7 +354,7 @@ namespace NzbDrone.Core.Movies { using (var conn = _database.OpenConnection()) { - return conn.Query("SELECT TmdbId FROM Movies").ToList(); + return conn.Query("SELECT \"TmdbId\" FROM \"Movies\"").ToList(); } } @@ -320,7 +362,7 @@ namespace NzbDrone.Core.Movies { using (var conn = _database.OpenConnection()) { - var strSql = "SELECT Id AS [Key], Tags AS [Value] FROM Movies"; + var strSql = "SELECT \"Id\" AS \"Key\", \"Tags\" AS \"Value\" FROM \"Movies\""; return conn.Query>>(strSql).ToDictionary(x => x.Key, x => x.Value); } } @@ -336,21 +378,42 @@ namespace NzbDrone.Core.Movies using (var conn = _database.OpenConnection()) { - recommendations = conn.Query(@"SELECT DISTINCT Rec FROM ( - SELECT DISTINCT Rec FROM + if (_database.DatabaseType == DatabaseType.PostgreSQL) + { + recommendations = conn.Query(@"SELECT DISTINCT ""Rec"" FROM ( + SELECT DISTINCT ""Rec"" FROM ( - SELECT DISTINCT CAST(j.value AS INT) AS Rec FROM Movies CROSS JOIN json_each(Movies.Recommendations) AS j - WHERE Rec NOT IN (SELECT TmdbId FROM Movies union SELECT TmdbId from ImportExclusions) LIMIT 10 + SELECT DISTINCT CAST(""value"" AS INT) AS ""Rec"" FROM ""Movies"", json_array_elements_text((""Movies"".""Recommendations"")::json) + WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub1) LIMIT 10 + ) as sub2 + UNION + SELECT ""Rec"" FROM + ( + SELECT CAST(""value"" AS INT) AS ""Rec"" FROM ""Movies"", json_array_elements_text((""Movies"".""Recommendations"")::json) + WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub2) + GROUP BY ""Rec"" ORDER BY count(*) DESC LIMIT 120 + ) as sub4 + ) as sub5 + LIMIT 100;").ToList(); + } + else + { + recommendations = conn.Query(@"SELECT DISTINCT ""Rec"" FROM ( + SELECT DISTINCT ""Rec"" FROM + ( + SELECT DISTINCT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""Movies"" CROSS JOIN json_each(""Movies"".""Recommendations"") AS ""j"" + WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"") LIMIT 10 ) UNION - SELECT Rec FROM + SELECT ""Rec"" FROM ( - SELECT CAST(j.value AS INT) AS Rec FROM Movies CROSS JOIN json_each(Movies.Recommendations) AS j - WHERE Rec NOT IN (SELECT TmdbId FROM Movies union SELECT TmdbId from ImportExclusions) - GROUP BY Rec ORDER BY count(*) DESC LIMIT 120 + SELECT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""Movies"" CROSS JOIN json_each(""Movies"".""Recommendations"") AS ""j"" + WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"") + GROUP BY ""Rec"" ORDER BY count(*) DESC LIMIT 120 ) ) LIMIT 100;").ToList(); + } } return recommendations; diff --git a/src/NzbDrone.Core/Radarr.Core.csproj b/src/NzbDrone.Core/Radarr.Core.csproj index 12c20b65a..95cb5ae7f 100644 --- a/src/NzbDrone.Core/Radarr.Core.csproj +++ b/src/NzbDrone.Core/Radarr.Core.csproj @@ -4,7 +4,9 @@ + + diff --git a/src/NzbDrone.Core/Update/UpdatePackageProvider.cs b/src/NzbDrone.Core/Update/UpdatePackageProvider.cs index 13aee9b6e..40f91fbfb 100644 --- a/src/NzbDrone.Core/Update/UpdatePackageProvider.cs +++ b/src/NzbDrone.Core/Update/UpdatePackageProvider.cs @@ -5,6 +5,7 @@ using NzbDrone.Common.Cloud; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Http; using NzbDrone.Core.Analytics; +using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Update { @@ -20,13 +21,15 @@ namespace NzbDrone.Core.Update private readonly IHttpRequestBuilderFactory _requestBuilder; private readonly IPlatformInfo _platformInfo; private readonly IAnalyticsService _analyticsService; + private readonly IMainDatabase _mainDatabase; - public UpdatePackageProvider(IHttpClient httpClient, IRadarrCloudRequestBuilder requestBuilder, IAnalyticsService analyticsService, IPlatformInfo platformInfo) + public UpdatePackageProvider(IHttpClient httpClient, IRadarrCloudRequestBuilder requestBuilder, IAnalyticsService analyticsService, IPlatformInfo platformInfo, IMainDatabase mainDatabase) { _platformInfo = platformInfo; _analyticsService = analyticsService; _requestBuilder = requestBuilder.Services; _httpClient = httpClient; + _mainDatabase = mainDatabase; } public UpdatePackage GetLatestUpdate(string branch, Version currentVersion) @@ -38,6 +41,7 @@ namespace NzbDrone.Core.Update .AddQueryParam("arch", RuntimeInformation.OSArchitecture) .AddQueryParam("runtime", PlatformInfo.Platform.ToString().ToLowerInvariant()) .AddQueryParam("runtimeVer", _platformInfo.Version) + .AddQueryParam("dbType", _mainDatabase.DatabaseType) .SetSegment("branch", branch); if (_analyticsService.IsEnabled) diff --git a/src/Radarr.Api.V3/System/SystemController.cs b/src/Radarr.Api.V3/System/SystemController.cs index 4fdef2677..747f1c245 100644 --- a/src/Radarr.Api.V3/System/SystemController.cs +++ b/src/Radarr.Api.V3/System/SystemController.cs @@ -77,7 +77,8 @@ namespace Radarr.Api.V3.System Mode = _runtimeInfo.Mode, Branch = _configFileProvider.Branch, Authentication = _configFileProvider.AuthenticationMethod, - SqliteVersion = _database.Version, + DatabaseType = _database.DatabaseType, + DatabaseVersion = _database.Version, MigrationVersion = _database.Migration, UrlBase = _configFileProvider.UrlBase, RuntimeVersion = _platformInfo.Version,