You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Radarr/src/NzbDrone.Core/Datastore/Migration/180_fix_invalid_profile_ref...

318 lines
12 KiB

using System.Collections.Generic;
using System.Data;
using System.Linq;
using Dapper;
using FluentMigrator;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(180)]
public class fix_invalid_profile_references : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Execute.WithConnection(FixMovies);
}
private void FixMovies(IDbConnection conn, IDbTransaction tran)
{
var profiles = GetProfileIds(conn);
var movieRows = conn.Query<ProfileEntity179>($"SELECT \"Id\", \"ProfileId\" FROM \"Movies\"");
var listRows = conn.Query<ProfileEntity179>($"SELECT \"Id\", \"ProfileId\" FROM \"NetImport\"");
// Only process if there are lists or movies existing in the DB
if (movieRows.Any() || listRows.Any())
{
// If there are no Profiles lets add the defaults
if (!profiles.Any())
{
InsertDefaultQualityProfiles(conn, tran);
profiles = GetProfileIds(conn);
}
var mostCommonProfileId = 0;
// If we have some movies, lets determine the most common profile used and use it for the bad entries
if (movieRows.Any())
{
mostCommonProfileId = movieRows.Select(x => x.ProfileId)
.Where(x => profiles.Contains(x))
.GroupBy(p => p)
.OrderByDescending(g => g.Count())
.Select(g => g.Key)
.FirstOrDefault();
}
// If all the movie profiles are bad or there are no movies, just use the first profile for bad movies and lsits
if (mostCommonProfileId == 0)
{
mostCommonProfileId = profiles.First();
}
// 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)";
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)";
conn.Execute(sql, transaction: tran);
}
}
private List<int> GetProfileIds(IDbConnection conn)
{
return conn.Query<QualityProfile180>("SELECT \"Id\" From \"Profiles\"").Select(p => p.Id).ToList();
}
private void InsertDefaultQualityProfiles(IDbConnection conn, IDbTransaction tran)
{
var profiles = GetDefaultQualityProfiles(conn);
var formatItemConverter = new EmbeddedDocumentConverter<List<ProfileFormatItem180>>(new CustomFormatIntConverter());
var profileItemConverter = new EmbeddedDocumentConverter<List<QualityProfileItem111>>(new QualityIntConverter());
var profileId = 1;
foreach (var profile in profiles.OrderBy(p => p.Id))
{
using (IDbCommand insertNewLanguageProfileCmd = conn.CreateCommand())
{
insertNewLanguageProfileCmd.Transaction = tran;
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);
var paramItems = insertNewLanguageProfileCmd.CreateParameter();
profileItemConverter.SetValue(paramItems, profile.Items);
insertNewLanguageProfileCmd.Parameters.Add(paramItems);
insertNewLanguageProfileCmd.AddParameter(profile.Language.Id);
var paramFormats = insertNewLanguageProfileCmd.CreateParameter();
formatItemConverter.SetValue(paramFormats, profile.FormatItems);
insertNewLanguageProfileCmd.Parameters.Add(paramFormats);
insertNewLanguageProfileCmd.AddParameter(profile.MinFormatScore);
insertNewLanguageProfileCmd.AddParameter(profile.CutoffFormatScore);
insertNewLanguageProfileCmd.AddParameter(profile.UpgradeAllowed);
insertNewLanguageProfileCmd.ExecuteNonQuery();
}
profileId += 1;
}
}
private List<QualityProfile180> GetDefaultQualityProfiles(IDbConnection conn)
{
var profiles = new List<QualityProfile180>();
// Grab custom formats if any exist and add them to the new profiles
var formats = conn.Query<CustomFormat180>($"SELECT \"Id\" FROM \"CustomFormats\"").ToList();
profiles.Add(GetDefaultProfile("Any",
formats,
Quality.Bluray480p,
Quality.WORKPRINT,
Quality.CAM,
Quality.TELESYNC,
Quality.TELECINE,
Quality.DVDSCR,
Quality.REGIONAL,
Quality.SDTV,
Quality.DVD,
Quality.DVDR,
Quality.HDTV720p,
Quality.HDTV1080p,
Quality.HDTV2160p,
Quality.WEBDL480p,
Quality.WEBRip480p,
Quality.WEBDL720p,
Quality.WEBRip720p,
Quality.WEBDL1080p,
Quality.WEBRip1080p,
Quality.WEBDL2160p,
Quality.WEBRip2160p,
Quality.Bluray480p,
Quality.Bluray576p,
Quality.Bluray720p,
Quality.Bluray1080p,
Quality.Bluray2160p,
Quality.Remux1080p,
Quality.Remux2160p,
Quality.BRDISK));
profiles.Add(GetDefaultProfile("SD",
formats,
Quality.Bluray480p,
Quality.WORKPRINT,
Quality.CAM,
Quality.TELESYNC,
Quality.TELECINE,
Quality.DVDSCR,
Quality.REGIONAL,
Quality.SDTV,
Quality.DVD,
Quality.WEBDL480p,
Quality.WEBRip480p,
Quality.Bluray480p,
Quality.Bluray576p));
profiles.Add(GetDefaultProfile("HD-720p",
formats,
Quality.Bluray720p,
Quality.HDTV720p,
Quality.WEBDL720p,
Quality.WEBRip720p,
Quality.Bluray720p));
profiles.Add(GetDefaultProfile("HD-1080p",
formats,
Quality.Bluray1080p,
Quality.HDTV1080p,
Quality.WEBDL1080p,
Quality.WEBRip1080p,
Quality.Bluray1080p,
Quality.Remux1080p));
profiles.Add(GetDefaultProfile("Ultra-HD",
formats,
Quality.Remux2160p,
Quality.HDTV2160p,
Quality.WEBDL2160p,
Quality.WEBRip2160p,
Quality.Bluray2160p,
Quality.Remux2160p));
profiles.Add(GetDefaultProfile("HD - 720p/1080p",
formats,
Quality.Bluray720p,
Quality.HDTV720p,
Quality.HDTV1080p,
Quality.WEBDL720p,
Quality.WEBRip720p,
Quality.WEBDL1080p,
Quality.WEBRip1080p,
Quality.Bluray720p,
Quality.Bluray1080p,
Quality.Remux1080p));
return profiles;
}
private QualityProfile180 GetDefaultProfile(string name, List<CustomFormat180> formats, Quality cutoff = null, params Quality[] allowed)
{
var groupedQualites = Quality.DefaultQualityDefinitions.GroupBy(q => q.Weight);
var items = new List<QualityProfileItem111>();
var groupId = 1000;
var profileCutoff = cutoff == null ? Quality.Unknown.Id : cutoff.Id;
foreach (var group in groupedQualites)
{
if (group.Count() == 1)
{
var quality = group.First().Quality;
items.Add(new QualityProfileItem111 { Quality = group.First().Quality, Allowed = allowed.Contains(quality), Items = new List<QualityProfileItem111>() });
continue;
}
var groupAllowed = group.Any(g => allowed.Contains(g.Quality));
items.Add(new QualityProfileItem111
{
Id = groupId,
Name = group.First().GroupName,
Items = group.Select(g => new QualityProfileItem111
{
Quality = g.Quality,
Allowed = groupAllowed,
Items = new List<QualityProfileItem111>()
}).ToList(),
Allowed = groupAllowed
});
if (group.Any(g => g.Quality.Id == profileCutoff))
{
profileCutoff = groupId;
}
groupId++;
}
var formatItems = formats.Select(format => new ProfileFormatItem180
{
Id = format.Id,
Score = 0,
Format = format.Id
}).ToList();
var qualityProfile = new QualityProfile180
{
Name = name,
Cutoff = profileCutoff,
Items = items,
Language = Language.English,
MinFormatScore = 0,
CutoffFormatScore = 0,
UpgradeAllowed = false,
FormatItems = formatItems
};
return qualityProfile;
}
private class ProfileEntity179
{
public int Id { get; set; }
public int ProfileId { get; set; }
}
private class QualityProfile180
{
public int Id { get; set; }
public string Name { get; set; }
public int Cutoff { get; set; }
public int MinFormatScore { get; set; }
public int CutoffFormatScore { get; set; }
public bool UpgradeAllowed { get; set; }
public Language Language { get; set; }
public List<ProfileFormatItem180> FormatItems { get; set; }
public List<QualityProfileItem111> Items { get; set; }
}
private class QualityProfileItem111
{
public int Id { get; set; }
public string Name { get; set; }
public Quality Quality { get; set; }
public List<QualityProfileItem111> Items { get; set; }
public bool Allowed { get; set; }
}
private class ProfileFormatItem180
{
public int Id { get; set; }
public int Format { get; set; }
public int Score { get; set; }
}
private class CustomFormat180
{
public int Id { get; set; }
}
}
}