From b0281b79fd8c6e103fa7a1cb183028541d280ed4 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Mon, 1 Jun 2020 20:12:34 -0400 Subject: [PATCH 1/2] Fix a bug where very old Emby databases didn't use proper Guid's --- .../Routines/MigrateActivityLogDb.cs | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs index b3cc297082..270c36f857 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs @@ -64,6 +64,7 @@ namespace Jellyfin.Server.Migrations.Routines ConnectionFlags.ReadOnly, null)) { + using var userDbConnection = SQLite3.Open(Path.Combine(dataPath, "users.db"), ConnectionFlags.ReadOnly, null); _logger.LogWarning("Migrating the activity database may take a while, do not stop Jellyfin."); using var dbContext = _provider.CreateContext(); @@ -76,17 +77,38 @@ namespace Jellyfin.Server.Migrations.Routines dbContext.Database.ExecuteSqlRaw("UPDATE sqlite_sequence SET seq = 0 WHERE name = 'ActivityLog';"); dbContext.SaveChanges(); - var newEntries = queryResult.Select(entry => + var newEntries = new List(); + + foreach (var entry in queryResult) { if (!logLevelDictionary.TryGetValue(entry[8].ToString(), out var severity)) { severity = LogLevel.Trace; } + Guid guid; + if (entry[6].SQLiteType == SQLiteType.Null) + { + guid = Guid.Empty; + } + else if (!Guid.TryParse(entry[6].ToString(), out guid)) + { + // This is not a valid Guid, see if it is an internal ID from an old Emby schema + var userEntry = userDbConnection + .Query($"SELECT guid FROM LocalUsersv2 WHERE Id = {entry[6].ToString()}") + .FirstOrDefault(); + + if (userEntry.Count == 0 || !Guid.TryParse(userEntry[0].ToString(), out guid)) + { + // Give up, just use Guid.Empty + guid = Guid.Empty; + } + } + var newEntry = new ActivityLog( entry[1].ToString(), entry[4].ToString(), - entry[6].SQLiteType == SQLiteType.Null ? Guid.Empty : Guid.Parse(entry[6].ToString())) + guid) { DateCreated = entry[7].ReadDateTime(), LogSeverity = severity @@ -107,8 +129,8 @@ namespace Jellyfin.Server.Migrations.Routines newEntry.ItemId = entry[5].ToString(); } - return newEntry; - }); + newEntries.Add(newEntry); + } dbContext.ActivityLogs.AddRange(newEntries); dbContext.SaveChanges(); From ef7bbb3b8425f4873282525c607f86e9f3fcc87a Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 4 Jun 2020 14:54:43 -0400 Subject: [PATCH 2/2] Use data binding instead of raw SQL --- .../Routines/MigrateActivityLogDb.cs | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs index 270c36f857..fb3466e13e 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using Emby.Server.Implementations.Data; using Jellyfin.Data.Entities; using Jellyfin.Server.Implementations; @@ -68,7 +67,7 @@ namespace Jellyfin.Server.Migrations.Routines _logger.LogWarning("Migrating the activity database may take a while, do not stop Jellyfin."); using var dbContext = _provider.CreateContext(); - var queryResult = connection.Query("SELECT * FROM ActivityLog ORDER BY Id ASC"); + var queryResult = connection.Query("SELECT * FROM ActivityLog ORDER BY Id"); // Make sure that the database is empty in case of failed migration due to power outages, etc. dbContext.ActivityLogs.RemoveRange(dbContext.ActivityLogs); @@ -86,29 +85,26 @@ namespace Jellyfin.Server.Migrations.Routines severity = LogLevel.Trace; } - Guid guid; - if (entry[6].SQLiteType == SQLiteType.Null) - { - guid = Guid.Empty; - } - else if (!Guid.TryParse(entry[6].ToString(), out guid)) + var guid = Guid.Empty; + if (entry[6].SQLiteType != SQLiteType.Null && !Guid.TryParse(entry[6].ToString(), out guid)) { // This is not a valid Guid, see if it is an internal ID from an old Emby schema - var userEntry = userDbConnection - .Query($"SELECT guid FROM LocalUsersv2 WHERE Id = {entry[6].ToString()}") - .FirstOrDefault(); + _logger.LogWarning("Invalid Guid in UserId column: ", entry[6].ToString()); - if (userEntry.Count == 0 || !Guid.TryParse(userEntry[0].ToString(), out guid)) + using var statement = userDbConnection.PrepareStatement("SELECT guid FROM LocalUsersv2 WHERE Id=@Id"); + statement.TryBind("@Id", entry[6].ToString()); + + foreach (var row in statement.Query()) { - // Give up, just use Guid.Empty - guid = Guid.Empty; + if (row.Count > 0 && Guid.TryParse(row[0].ToString(), out guid)) + { + // Successfully parsed a Guid from the user table. + break; + } } } - var newEntry = new ActivityLog( - entry[1].ToString(), - entry[4].ToString(), - guid) + var newEntry = new ActivityLog(entry[1].ToString(), entry[4].ToString(), guid) { DateCreated = entry[7].ReadDateTime(), LogSeverity = severity