diff options
Diffstat (limited to 'Emby.Server.Implementations/Data/SqliteItemRepository.cs')
| -rw-r--r-- | Emby.Server.Implementations/Data/SqliteItemRepository.cs | 929 |
1 files changed, 332 insertions, 597 deletions
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index beae7e243..85fa79cba 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -248,42 +248,6 @@ namespace Emby.Server.Implementations.Data BaseItemKind.AudioBook }; - private static readonly Type[] _knownTypes = - { - typeof(LiveTvProgram), - typeof(LiveTvChannel), - typeof(Series), - typeof(Audio), - typeof(MusicAlbum), - typeof(MusicArtist), - typeof(MusicGenre), - typeof(MusicVideo), - typeof(Movie), - typeof(Playlist), - typeof(AudioBook), - typeof(Trailer), - typeof(BoxSet), - typeof(Episode), - typeof(Season), - typeof(Series), - typeof(Book), - typeof(CollectionFolder), - typeof(Folder), - typeof(Genre), - typeof(Person), - typeof(Photo), - typeof(PhotoAlbum), - typeof(Studio), - typeof(UserRootFolder), - typeof(UserView), - typeof(Video), - typeof(Year), - typeof(Channel), - typeof(AggregateFolder) - }; - - private readonly Dictionary<string, string> _types = GetTypeMapDictionary(); - private static readonly Dictionary<BaseItemKind, string> _baseItemKindNames = new() { { BaseItemKind.AggregateFolder, typeof(AggregateFolder).FullName }, @@ -353,11 +317,6 @@ namespace Emby.Server.Implementations.Data IImageProcessor imageProcessor) : base(logger) { - if (config == null) - { - throw new ArgumentNullException(nameof(config)); - } - _config = config; _appHost = appHost; _localization = localization; @@ -370,9 +329,6 @@ namespace Emby.Server.Implementations.Data } /// <inheritdoc /> - public string Name => "SQLite"; - - /// <inheritdoc /> protected override int? CacheSize => 20000; /// <inheritdoc /> @@ -498,109 +454,110 @@ namespace Emby.Server.Implementations.Data connection.RunQueries(queries); connection.RunInTransaction( - db => - { - var existingColumnNames = GetColumnNames(db, "AncestorIds"); - AddColumn(db, "AncestorIds", "AncestorIdText", "Text", existingColumnNames); - - existingColumnNames = GetColumnNames(db, "TypedBaseItems"); - - AddColumn(db, "TypedBaseItems", "Path", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "StartDate", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "EndDate", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ChannelId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsMovie", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "CommunityRating", "Float", existingColumnNames); - AddColumn(db, "TypedBaseItems", "CustomRating", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IndexNumber", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsLocked", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Name", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "OfficialRating", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "MediaType", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Overview", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ParentIndexNumber", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "PremiereDate", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ProductionYear", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ParentId", "GUID", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Genres", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "DateCreated", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "EpisodeTitle", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsRepeat", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "PreferredMetadataLanguage", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "PreferredMetadataCountryCode", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "DateLastRefreshed", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "DateLastSaved", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsInMixedFolder", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "LockedFields", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Studios", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Audio", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ExternalServiceId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Tags", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsFolder", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "InheritedParentalRatingValue", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "UnratedType", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "TopParentId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames); - AddColumn(db, "TypedBaseItems", "CleanName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "PresentationUniqueKey", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "OriginalTitle", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "PrimaryVersionId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "DateLastMediaAdded", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Album", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsVirtualItem", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeriesName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "UserDataKey", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeasonName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeasonId", "GUID", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ProviderIds", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Images", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ProductionLocations", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ExtraIds", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "TotalBitrate", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ExtraType", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Artists", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "AlbumArtists", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ExternalId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeriesPresentationUniqueKey", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ShowId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "OwnerId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Width", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Height", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Size", "BIGINT", existingColumnNames); - - existingColumnNames = GetColumnNames(db, "ItemValues"); - AddColumn(db, "ItemValues", "CleanValue", "Text", existingColumnNames); - - existingColumnNames = GetColumnNames(db, ChaptersTableName); - AddColumn(db, ChaptersTableName, "ImageDateModified", "DATETIME", existingColumnNames); - - existingColumnNames = GetColumnNames(db, "MediaStreams"); - AddColumn(db, "MediaStreams", "IsAvc", "BIT", existingColumnNames); - AddColumn(db, "MediaStreams", "TimeBase", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "CodecTimeBase", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "Title", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "NalLengthSize", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "Comment", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "CodecTag", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "PixelFormat", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "BitDepth", "INT", existingColumnNames); - AddColumn(db, "MediaStreams", "RefFrames", "INT", existingColumnNames); - AddColumn(db, "MediaStreams", "KeyFrames", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "IsAnamorphic", "BIT", existingColumnNames); - - AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames); - }, TransactionMode); + db => + { + var existingColumnNames = GetColumnNames(db, "AncestorIds"); + AddColumn(db, "AncestorIds", "AncestorIdText", "Text", existingColumnNames); + + existingColumnNames = GetColumnNames(db, "TypedBaseItems"); + + AddColumn(db, "TypedBaseItems", "Path", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "StartDate", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "EndDate", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ChannelId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsMovie", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "CommunityRating", "Float", existingColumnNames); + AddColumn(db, "TypedBaseItems", "CustomRating", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IndexNumber", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsLocked", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Name", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "OfficialRating", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "MediaType", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Overview", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ParentIndexNumber", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "PremiereDate", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ProductionYear", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ParentId", "GUID", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Genres", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "DateCreated", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "EpisodeTitle", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsRepeat", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "PreferredMetadataLanguage", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "PreferredMetadataCountryCode", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "DateLastRefreshed", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "DateLastSaved", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsInMixedFolder", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "LockedFields", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Studios", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Audio", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ExternalServiceId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Tags", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsFolder", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "InheritedParentalRatingValue", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "UnratedType", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "TopParentId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames); + AddColumn(db, "TypedBaseItems", "CleanName", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "PresentationUniqueKey", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "OriginalTitle", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "PrimaryVersionId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "DateLastMediaAdded", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Album", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsVirtualItem", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SeriesName", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "UserDataKey", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SeasonName", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SeasonId", "GUID", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ProviderIds", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Images", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ProductionLocations", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ExtraIds", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "TotalBitrate", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ExtraType", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Artists", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "AlbumArtists", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ExternalId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SeriesPresentationUniqueKey", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ShowId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "OwnerId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Width", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Height", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Size", "BIGINT", existingColumnNames); + + existingColumnNames = GetColumnNames(db, "ItemValues"); + AddColumn(db, "ItemValues", "CleanValue", "Text", existingColumnNames); + + existingColumnNames = GetColumnNames(db, ChaptersTableName); + AddColumn(db, ChaptersTableName, "ImageDateModified", "DATETIME", existingColumnNames); + + existingColumnNames = GetColumnNames(db, "MediaStreams"); + AddColumn(db, "MediaStreams", "IsAvc", "BIT", existingColumnNames); + AddColumn(db, "MediaStreams", "TimeBase", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "CodecTimeBase", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "Title", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "NalLengthSize", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "Comment", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "CodecTag", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "PixelFormat", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "BitDepth", "INT", existingColumnNames); + AddColumn(db, "MediaStreams", "RefFrames", "INT", existingColumnNames); + AddColumn(db, "MediaStreams", "KeyFrames", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "IsAnamorphic", "BIT", existingColumnNames); + + AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames); + }, + TransactionMode); connection.RunQueries(postQueries); } @@ -608,22 +565,6 @@ namespace Emby.Server.Implementations.Data userDataRepo.Initialize(userManager, WriteLock, WriteConnection); } - /// <summary> - /// Save a standard item in the repo. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <exception cref="ArgumentNullException"><paramref name="item"/> is <c>null</c>.</exception> - public void SaveItem(BaseItem item, CancellationToken cancellationToken) - { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } - - SaveItems(new[] { item }, cancellationToken); - } - public void SaveImages(BaseItem item) { if (item == null) @@ -636,16 +577,17 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - using (var saveImagesStatement = PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id")) + db => { - saveImagesStatement.TryBind("@Id", item.Id.ToByteArray()); - saveImagesStatement.TryBind("@Images", SerializeImages(item.ImageInfos)); + using (var saveImagesStatement = PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id")) + { + saveImagesStatement.TryBind("@Id", item.Id); + saveImagesStatement.TryBind("@Images", SerializeImages(item.ImageInfos)); - saveImagesStatement.MoveNext(); - } - }, TransactionMode); + saveImagesStatement.MoveNext(); + } + }, + TransactionMode); } } @@ -686,14 +628,15 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - SaveItemsInTranscation(db, tuples); - }, TransactionMode); + db => + { + SaveItemsInTransaction(db, tuples); + }, + TransactionMode); } } - private void SaveItemsInTranscation(IDatabaseConnection db, IEnumerable<(BaseItem, List<Guid>, BaseItem, string, List<string>)> tuples) + private void SaveItemsInTransaction(IDatabaseConnection db, IEnumerable<(BaseItem Item, List<Guid> AncestorIds, BaseItem TopParent, string UserDataKey, List<string> InheritedTags)> tuples) { var statements = PrepareAll(db, new string[] { @@ -712,17 +655,17 @@ namespace Emby.Server.Implementations.Data saveItemStatement.Reset(); } - var item = tuple.Item1; - var topParent = tuple.Item3; - var userDataKey = tuple.Item4; + var item = tuple.Item; + var topParent = tuple.TopParent; + var userDataKey = tuple.UserDataKey; SaveItem(item, topParent, userDataKey, saveItemStatement); - var inheritedTags = tuple.Item5; + var inheritedTags = tuple.InheritedTags; if (item.SupportsAncestors) { - UpdateAncestors(item.Id, tuple.Item2, db, deleteAncestorsStatement); + UpdateAncestors(item.Id, tuple.AncestorIds, db, deleteAncestorsStatement); } UpdateItemValues(item.Id, GetItemValuesToSave(item, inheritedTags), db); @@ -783,7 +726,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBindNull("@EndDate"); } - saveItemStatement.TryBind("@ChannelId", item.ChannelId.Equals(Guid.Empty) ? null : item.ChannelId.ToString("N", CultureInfo.InvariantCulture)); + saveItemStatement.TryBind("@ChannelId", item.ChannelId.Equals(default) ? null : item.ChannelId.ToString("N", CultureInfo.InvariantCulture)); if (item is IHasProgramAttributes hasProgramAttributes) { @@ -813,7 +756,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@ProductionYear", item.ProductionYear); var parentId = item.ParentId; - if (parentId.Equals(Guid.Empty)) + if (parentId.Equals(default)) { saveItemStatement.TryBindNull("@ParentId"); } @@ -1008,7 +951,7 @@ namespace Emby.Server.Implementations.Data { saveItemStatement.TryBind("@SeasonName", episode.SeasonName); - var nullableSeasonId = episode.SeasonId == Guid.Empty ? (Guid?)null : episode.SeasonId; + var nullableSeasonId = episode.SeasonId.Equals(default) ? (Guid?)null : episode.SeasonId; saveItemStatement.TryBind("@SeasonId", nullableSeasonId); } @@ -1020,7 +963,7 @@ namespace Emby.Server.Implementations.Data if (item is IHasSeries hasSeries) { - var nullableSeriesId = hasSeries.SeriesId.Equals(Guid.Empty) ? (Guid?)null : hasSeries.SeriesId; + var nullableSeriesId = hasSeries.SeriesId.Equals(default) ? (Guid?)null : hasSeries.SeriesId; saveItemStatement.TryBind("@SeriesId", nullableSeriesId); saveItemStatement.TryBind("@SeriesPresentationUniqueKey", hasSeries.SeriesPresentationUniqueKey); @@ -1093,7 +1036,7 @@ namespace Emby.Server.Implementations.Data } Guid ownerId = item.OwnerId; - if (ownerId == Guid.Empty) + if (ownerId.Equals(default)) { saveItemStatement.TryBindNull("@OwnerId"); } @@ -1231,13 +1174,15 @@ namespace Emby.Server.Implementations.Data bldr.Append(Delimiter) // Replace delimiters with other characters. // This can be removed when we migrate to a proper DB. - .Append(hash.Replace('*', '/').Replace('|', '\\')); + .Append(hash.Replace(Delimiter, '/').Replace('|', '\\')); } } internal ItemImageInfo ItemImageInfoFromValueString(ReadOnlySpan<char> value) { - var nextSegment = value.IndexOf('*'); + const char Delimiter = '*'; + + var nextSegment = value.IndexOf(Delimiter); if (nextSegment == -1) { return null; @@ -1245,7 +1190,7 @@ namespace Emby.Server.Implementations.Data ReadOnlySpan<char> path = value[..nextSegment]; value = value[(nextSegment + 1)..]; - nextSegment = value.IndexOf('*'); + nextSegment = value.IndexOf(Delimiter); if (nextSegment == -1) { return null; @@ -1253,7 +1198,7 @@ namespace Emby.Server.Implementations.Data ReadOnlySpan<char> dateModified = value[..nextSegment]; value = value[(nextSegment + 1)..]; - nextSegment = value.IndexOf('*'); + nextSegment = value.IndexOf(Delimiter); if (nextSegment == -1) { nextSegment = value.Length; @@ -1290,7 +1235,7 @@ namespace Emby.Server.Implementations.Data if (nextSegment + 1 < value.Length - 1) { value = value[(nextSegment + 1)..]; - nextSegment = value.IndexOf('*'); + nextSegment = value.IndexOf(Delimiter); if (nextSegment == -1 || nextSegment == value.Length) { return image; @@ -1299,7 +1244,7 @@ namespace Emby.Server.Implementations.Data ReadOnlySpan<char> widthSpan = value[..nextSegment]; value = value[(nextSegment + 1)..]; - nextSegment = value.IndexOf('*'); + nextSegment = value.IndexOf(Delimiter); if (nextSegment == -1) { nextSegment = value.Length; @@ -1325,7 +1270,7 @@ namespace Emby.Server.Implementations.Data var c = value[i]; blurHashSpan[i] = c switch { - '/' => '*', + '/' => Delimiter, '\\' => '|', _ => c }; @@ -1347,7 +1292,7 @@ namespace Emby.Server.Implementations.Data /// <exception cref="ArgumentException"><paramr name="id"/> is <seealso cref="Guid.Empty"/>.</exception> public BaseItem RetrieveItem(Guid id) { - if (id == Guid.Empty) + if (id.Equals(default)) { throw new ArgumentException("Guid can't be empty", nameof(id)); } @@ -2119,7 +2064,7 @@ namespace Emby.Server.Implementations.Data { CheckDisposed(); - if (id.Equals(Guid.Empty)) + if (id.Equals(default)) { throw new ArgumentNullException(nameof(id)); } @@ -2134,13 +2079,14 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - // First delete chapters - db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob); + db => + { + // First delete chapters + db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob); - InsertChapters(idBlob, chapters, db); - }, TransactionMode); + InsertChapters(idBlob, chapters, db); + }, + TransactionMode); } } @@ -2199,7 +2145,7 @@ namespace Emby.Server.Implementations.Data return false; } - var sortingFields = new HashSet<string>(query.OrderBy.Select(i => i.Item1), StringComparer.OrdinalIgnoreCase); + var sortingFields = new HashSet<string>(query.OrderBy.Select(i => i.OrderBy), StringComparer.OrdinalIgnoreCase); return sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked) || sortingFields.Contains(ItemSortBy.IsPlayed) @@ -2524,12 +2470,12 @@ namespace Emby.Server.Implementations.Data searchTerm = GetCleanValue(searchTerm); var commandText = statement.SQL; - if (commandText.IndexOf("@SearchTermStartsWith", StringComparison.OrdinalIgnoreCase) != -1) + if (commandText.Contains("@SearchTermStartsWith", StringComparison.OrdinalIgnoreCase)) { statement.TryBind("@SearchTermStartsWith", searchTerm + "%"); } - if (commandText.IndexOf("@SearchTermContains", StringComparison.OrdinalIgnoreCase) != -1) + if (commandText.Contains("@SearchTermContains", StringComparison.OrdinalIgnoreCase)) { statement.TryBind("@SearchTermContains", "%" + searchTerm + "%"); } @@ -2546,17 +2492,17 @@ namespace Emby.Server.Implementations.Data var commandText = statement.SQL; - if (commandText.IndexOf("@ItemOfficialRating", StringComparison.OrdinalIgnoreCase) != -1) + if (commandText.Contains("@ItemOfficialRating", StringComparison.OrdinalIgnoreCase)) { statement.TryBind("@ItemOfficialRating", item.OfficialRating); } - if (commandText.IndexOf("@ItemProductionYear", StringComparison.OrdinalIgnoreCase) != -1) + if (commandText.Contains("@ItemProductionYear", StringComparison.OrdinalIgnoreCase)) { statement.TryBind("@ItemProductionYear", item.ProductionYear ?? 0); } - if (commandText.IndexOf("@SimilarItemId", StringComparison.OrdinalIgnoreCase) != -1) + if (commandText.Contains("@SimilarItemId", StringComparison.OrdinalIgnoreCase)) { statement.TryBind("@SimilarItemId", item.Id); } @@ -2790,12 +2736,12 @@ namespace Emby.Server.Implementations.Data foreach (var providerId in newItem.ProviderIds) { - if (providerId.Key == MetadataProvider.TmdbCollection.ToString()) + if (string.Equals(providerId.Key, nameof(MetadataProvider.TmdbCollection), StringComparison.Ordinal)) { continue; } - if (item.GetProviderId(providerId.Key) == providerId.Value) + if (string.Equals(item.GetProviderId(providerId.Key), providerId.Value, StringComparison.Ordinal)) { if (newItem.SourceType == SourceType.Library) { @@ -2842,11 +2788,10 @@ namespace Emby.Server.Implementations.Data if (!query.EnableTotalRecordCount || (!query.Limit.HasValue && (query.StartIndex ?? 0) == 0)) { var returnList = GetItemList(query); - return new QueryResult<BaseItem> - { - Items = returnList, - TotalRecordCount = returnList.Count - }; + return new QueryResult<BaseItem>( + query.StartIndex, + returnList.Count, + returnList); } var now = DateTime.UtcNow; @@ -2944,71 +2889,73 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection(true)) { connection.RunInTransaction( - db => - { - var itemQueryStatement = PrepareStatement(db, itemQuery); - var totalRecordCountQueryStatement = PrepareStatement(db, totalRecordCountQuery); - - if (!isReturningZeroItems) + db => { - using (var statement = itemQueryStatement) + var itemQueryStatement = PrepareStatement(db, itemQuery); + var totalRecordCountQueryStatement = PrepareStatement(db, totalRecordCountQuery); + + if (!isReturningZeroItems) { - if (EnableJoinUserData(query)) + using (var statement = itemQueryStatement) { - statement.TryBind("@UserId", query.User.InternalId); - } + if (EnableJoinUserData(query)) + { + statement.TryBind("@UserId", query.User.InternalId); + } - BindSimilarParams(query, statement); - BindSearchParams(query, statement); + BindSimilarParams(query, statement); + BindSearchParams(query, statement); - // Running this again will bind the params - GetWhereClauses(query, statement); + // Running this again will bind the params + GetWhereClauses(query, statement); - var hasEpisodeAttributes = HasEpisodeAttributes(query); - var hasServiceName = HasServiceName(query); - var hasProgramAttributes = HasProgramAttributes(query); - var hasStartDate = HasStartDate(query); - var hasTrailerTypes = HasTrailerTypes(query); - var hasArtistFields = HasArtistFields(query); - var hasSeriesFields = HasSeriesFields(query); + var hasEpisodeAttributes = HasEpisodeAttributes(query); + var hasServiceName = HasServiceName(query); + var hasProgramAttributes = HasProgramAttributes(query); + var hasStartDate = HasStartDate(query); + var hasTrailerTypes = HasTrailerTypes(query); + var hasArtistFields = HasArtistFields(query); + var hasSeriesFields = HasSeriesFields(query); - foreach (var row in statement.ExecuteQuery()) - { - var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields); - if (item != null) + foreach (var row in statement.ExecuteQuery()) { - list.Add(item); + var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields); + if (item != null) + { + list.Add(item); + } } } - } - LogQueryTime("GetItems.ItemQuery", itemQuery, now); - } + LogQueryTime("GetItems.ItemQuery", itemQuery, now); + } - now = DateTime.UtcNow; - if (query.EnableTotalRecordCount) - { - using (var statement = totalRecordCountQueryStatement) + now = DateTime.UtcNow; + if (query.EnableTotalRecordCount) { - if (EnableJoinUserData(query)) + using (var statement = totalRecordCountQueryStatement) { - statement.TryBind("@UserId", query.User.InternalId); - } + if (EnableJoinUserData(query)) + { + statement.TryBind("@UserId", query.User.InternalId); + } - BindSimilarParams(query, statement); - BindSearchParams(query, statement); + BindSimilarParams(query, statement); + BindSearchParams(query, statement); - // Running this again will bind the params - GetWhereClauses(query, statement); + // Running this again will bind the params + GetWhereClauses(query, statement); - result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); - } + result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); + } - LogQueryTime("GetItems.TotalRecordCount", totalRecordCountQuery, now); - } - }, ReadTransactionMode); + LogQueryTime("GetItems.TotalRecordCount", totalRecordCountQuery, now); + } + }, + ReadTransactionMode); } + result.StartIndex = query.StartIndex ?? 0; result.Items = list; return result; } @@ -3046,88 +2993,101 @@ namespace Emby.Server.Implementations.Data return " ORDER BY " + string.Join(',', orderBy.Select(i => { - var columnMap = MapOrderByField(i.Item1, query); - - var sortOrder = i.Item2 == SortOrder.Ascending ? "ASC" : "DESC"; - - return columnMap.Item1 + " " + sortOrder; + var sortBy = MapOrderByField(i.OrderBy, query); + var sortOrder = i.SortOrder == SortOrder.Ascending ? "ASC" : "DESC"; + return sortBy + " " + sortOrder; })); } - private (string, bool) MapOrderByField(string name, InternalItemsQuery query) + private string MapOrderByField(string name, InternalItemsQuery query) { if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase)) { // TODO - return ("SortName", false); + return "SortName"; } - else if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase)) { - return ("RuntimeTicks", false); + return "RuntimeTicks"; } - else if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) { - return ("RANDOM()", false); + return "RANDOM()"; } - else if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase)) { if (query.GroupBySeriesPresentationUniqueKey) { - return ("MAX(LastPlayedDate)", false); + return "MAX(LastPlayedDate)"; } - return ("LastPlayedDate", false); + return "LastPlayedDate"; } - else if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase)) { - return ("PlayCount", false); + return "PlayCount"; } - else if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase)) { - return ("(Select Case When IsFavorite is null Then 0 Else IsFavorite End )", true); + return "(Select Case When IsFavorite is null Then 0 Else IsFavorite End )"; } - else if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) { - return ("IsFolder", true); + return "IsFolder"; } - else if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase)) { - return ("played", true); + return "played"; } - else if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase)) { - return ("played", false); + return "played"; } - else if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase)) { - return ("DateLastMediaAdded", false); + return "DateLastMediaAdded"; } - else if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase)) { - return ("(select CleanValue from itemvalues where ItemId=Guid and Type=0 LIMIT 1)", false); + return "(select CleanValue from itemvalues where ItemId=Guid and Type=0 LIMIT 1)"; } - else if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase)) { - return ("(select CleanValue from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", false); + return "(select CleanValue from itemvalues where ItemId=Guid and Type=1 LIMIT 1)"; } - else if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase)) { - return ("InheritedParentalRatingValue", false); + return "InheritedParentalRatingValue"; } - else if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase)) { - return ("(select CleanValue from itemvalues where ItemId=Guid and Type=3 LIMIT 1)", false); + return "(select CleanValue from itemvalues where ItemId=Guid and Type=3 LIMIT 1)"; } - else if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) { - return ("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false); + return "(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)"; } - else if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase)) { - return ("SeriesName", false); + return "SeriesName"; } - return (name, false); + return name; } public List<Guid> GetItemIdsList(InternalItemsQuery query) @@ -3203,219 +3163,6 @@ namespace Emby.Server.Implementations.Data return list; } - public List<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query) - { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } - - CheckDisposed(); - - var now = DateTime.UtcNow; - - var columns = new List<string> { "guid", "path" }; - SetFinalColumnsToSelect(query, columns); - var commandText = "select " + string.Join(',', columns) + FromText; - - var whereClauses = GetWhereClauses(query, null); - if (whereClauses.Count != 0) - { - commandText += " where " + string.Join(" AND ", whereClauses); - } - - commandText += GetGroupBy(query) - + GetOrderByText(query); - - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var offset = query.StartIndex ?? 0; - - if (query.Limit.HasValue || offset > 0) - { - commandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture); - } - - if (offset > 0) - { - commandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture); - } - } - - var list = new List<Tuple<Guid, string>>(); - using (var connection = GetConnection(true)) - { - using (var statement = PrepareStatement(connection, commandText)) - { - if (EnableJoinUserData(query)) - { - statement.TryBind("@UserId", query.User.InternalId); - } - - // Running this again will bind the params - GetWhereClauses(query, statement); - - foreach (var row in statement.ExecuteQuery()) - { - var id = row.GetGuid(0); - - row.TryGetString(1, out var path); - - list.Add(new Tuple<Guid, string>(id, path)); - } - } - } - - LogQueryTime("GetItemIdsWithPath", commandText, now); - - return list; - } - - public QueryResult<Guid> GetItemIds(InternalItemsQuery query) - { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } - - CheckDisposed(); - - if (!query.EnableTotalRecordCount || (!query.Limit.HasValue && (query.StartIndex ?? 0) == 0)) - { - var returnList = GetItemIdsList(query); - return new QueryResult<Guid> - { - Items = returnList, - TotalRecordCount = returnList.Count - }; - } - - var now = DateTime.UtcNow; - - var columns = new List<string> { "guid" }; - SetFinalColumnsToSelect(query, columns); - var commandText = "select " - + string.Join(',', columns) - + FromText - + GetJoinUserDataText(query); - - var whereClauses = GetWhereClauses(query, null); - - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses); - - commandText += whereText - + GetGroupBy(query) - + GetOrderByText(query); - - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var offset = query.StartIndex ?? 0; - - if (query.Limit.HasValue || offset > 0) - { - commandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture); - } - - if (offset > 0) - { - commandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture); - } - } - - var isReturningZeroItems = query.Limit.HasValue && query.Limit <= 0; - - var statementTexts = new List<string>(); - if (!isReturningZeroItems) - { - statementTexts.Add(commandText); - } - - if (query.EnableTotalRecordCount) - { - commandText = string.Empty; - - List<string> columnsToSelect; - if (EnableGroupByPresentationUniqueKey(query)) - { - columnsToSelect = new List<string> { "count (distinct PresentationUniqueKey)" }; - } - else if (query.GroupBySeriesPresentationUniqueKey) - { - columnsToSelect = new List<string> { "count (distinct SeriesPresentationUniqueKey)" }; - } - else - { - columnsToSelect = new List<string> { "count (guid)" }; - } - - SetFinalColumnsToSelect(query, columnsToSelect); - commandText += " select " + string.Join(',', columnsToSelect) + FromText; - - commandText += GetJoinUserDataText(query) - + whereText; - statementTexts.Add(commandText); - } - - var list = new List<Guid>(); - var result = new QueryResult<Guid>(); - using (var connection = GetConnection(true)) - { - connection.RunInTransaction( - db => - { - var statements = PrepareAll(db, statementTexts); - - if (!isReturningZeroItems) - { - using (var statement = statements[0]) - { - if (EnableJoinUserData(query)) - { - statement.TryBind("@UserId", query.User.InternalId); - } - - BindSimilarParams(query, statement); - BindSearchParams(query, statement); - - // Running this again will bind the params - GetWhereClauses(query, statement); - - foreach (var row in statement.ExecuteQuery()) - { - list.Add(row[0].ReadGuidFromBlob()); - } - } - } - - if (query.EnableTotalRecordCount) - { - using (var statement = statements[statements.Length - 1]) - { - if (EnableJoinUserData(query)) - { - statement.TryBind("@UserId", query.User.InternalId); - } - - BindSimilarParams(query, statement); - BindSearchParams(query, statement); - - // Running this again will bind the params - GetWhereClauses(query, statement); - - result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); - } - } - }, ReadTransactionMode); - } - - LogQueryTime("GetItemIds", commandText, now); - - result.Items = list; - return result; - } - private bool IsAlphaNumeric(string str) { if (string.IsNullOrWhiteSpace(str)) @@ -3434,11 +3181,6 @@ namespace Emby.Server.Implementations.Data return true; } - private bool IsValidType(string value) - { - return IsAlphaNumeric(value); - } - private bool IsValidMediaType(string value) { return IsAlphaNumeric(value); @@ -3687,7 +3429,7 @@ namespace Emby.Server.Implementations.Data whereClauses.Add($"ChannelId in ({inClause})"); } - if (!query.ParentId.Equals(Guid.Empty)) + if (!query.ParentId.Equals(default)) { whereClauses.Add("ParentId=@ParentId"); statement?.TryBind("@ParentId", query.ParentId); @@ -4047,7 +3789,7 @@ namespace Emby.Server.Implementations.Data clauses.Add("(guid in (select itemid from itemvalues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type<=1))"); if (statement != null) { - statement.TryBind(paramName, artistId.ToByteArray()); + statement.TryBind(paramName, artistId); } index++; @@ -4068,7 +3810,7 @@ namespace Emby.Server.Implementations.Data clauses.Add("(guid in (select itemid from itemvalues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type=1))"); if (statement != null) { - statement.TryBind(paramName, artistId.ToByteArray()); + statement.TryBind(paramName, artistId); } index++; @@ -4089,7 +3831,7 @@ namespace Emby.Server.Implementations.Data clauses.Add("((select CleanName from TypedBaseItems where guid=" + paramName + ") in (select CleanValue from itemvalues where ItemId=Guid and Type=0) AND (select CleanName from TypedBaseItems where guid=" + paramName + ") not in (select CleanValue from itemvalues where ItemId=Guid and Type=1))"); if (statement != null) { - statement.TryBind(paramName, artistId.ToByteArray()); + statement.TryBind(paramName, artistId); } index++; @@ -4110,7 +3852,7 @@ namespace Emby.Server.Implementations.Data clauses.Add("Album in (select Name from typedbaseitems where guid=" + paramName + ")"); if (statement != null) { - statement.TryBind(paramName, albumId.ToByteArray()); + statement.TryBind(paramName, albumId); } index++; @@ -4131,7 +3873,7 @@ namespace Emby.Server.Implementations.Data clauses.Add("(guid not in (select itemid from itemvalues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type<=1))"); if (statement != null) { - statement.TryBind(paramName, artistId.ToByteArray()); + statement.TryBind(paramName, artistId); } index++; @@ -4152,7 +3894,7 @@ namespace Emby.Server.Implementations.Data clauses.Add("(guid in (select itemid from itemvalues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type=2))"); if (statement != null) { - statement.TryBind(paramName, genreId.ToByteArray()); + statement.TryBind(paramName, genreId); } index++; @@ -4231,7 +3973,7 @@ namespace Emby.Server.Implementations.Data if (statement != null) { - statement.TryBind(paramName, studioId.ToByteArray()); + statement.TryBind(paramName, studioId); } index++; @@ -4516,7 +4258,7 @@ namespace Emby.Server.Implementations.Data var index = 0; foreach (var pair in query.ExcludeProviderIds) { - if (string.Equals(pair.Key, MetadataProvider.TmdbCollection.ToString(), StringComparison.OrdinalIgnoreCase)) + if (string.Equals(pair.Key, nameof(MetadataProvider.TmdbCollection), StringComparison.OrdinalIgnoreCase)) { continue; } @@ -4546,7 +4288,7 @@ namespace Emby.Server.Implementations.Data var index = 0; foreach (var pair in query.HasAnyProviderId) { - if (string.Equals(pair.Key, MetadataProvider.TmdbCollection.ToString(), StringComparison.OrdinalIgnoreCase)) + if (string.Equals(pair.Key, nameof(MetadataProvider.TmdbCollection), StringComparison.OrdinalIgnoreCase)) { continue; } @@ -4705,7 +4447,7 @@ namespace Emby.Server.Implementations.Data if (statement == null) { int index = 0; - string excludedTags = string.Join(',', query.ExcludeInheritedTags.Select(t => paramName + index++)); + string excludedTags = string.Join(',', query.ExcludeInheritedTags.Select(_ => paramName + index++)); whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + excludedTags + ")) is null)"); } else @@ -4954,31 +4696,17 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - connection.ExecuteAll(sql); - }, TransactionMode); - } - } - - private static Dictionary<string, string> GetTypeMapDictionary() - { - var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - - foreach (var t in _knownTypes) - { - dict[t.Name] = t.FullName; + db => + { + connection.ExecuteAll(sql); + }, + TransactionMode); } - - dict["Program"] = typeof(LiveTvProgram).FullName; - dict["TvChannel"] = typeof(LiveTvChannel).FullName; - - return dict; } public void DeleteItem(Guid id) { - if (id == Guid.Empty) + if (id.Equals(default)) { throw new ArgumentNullException(nameof(id)); } @@ -4988,28 +4716,30 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - var idBlob = id.ToByteArray(); + db => + { + Span<byte> idBlob = stackalloc byte[16]; + id.TryWriteBytes(idBlob); - // Delete people - ExecuteWithSingleParam(db, "delete from People where ItemId=@Id", idBlob); + // Delete people + ExecuteWithSingleParam(db, "delete from People where ItemId=@Id", idBlob); - // Delete chapters - ExecuteWithSingleParam(db, "delete from " + ChaptersTableName + " where ItemId=@Id", idBlob); + // Delete chapters + ExecuteWithSingleParam(db, "delete from " + ChaptersTableName + " where ItemId=@Id", idBlob); - // Delete media streams - ExecuteWithSingleParam(db, "delete from mediastreams where ItemId=@Id", idBlob); + // Delete media streams + ExecuteWithSingleParam(db, "delete from mediastreams where ItemId=@Id", idBlob); - // Delete ancestors - ExecuteWithSingleParam(db, "delete from AncestorIds where ItemId=@Id", idBlob); + // Delete ancestors + ExecuteWithSingleParam(db, "delete from AncestorIds where ItemId=@Id", idBlob); - // Delete item values - ExecuteWithSingleParam(db, "delete from ItemValues where ItemId=@Id", idBlob); + // Delete item values + ExecuteWithSingleParam(db, "delete from ItemValues where ItemId=@Id", idBlob); - // Delete the item - ExecuteWithSingleParam(db, "delete from TypedBaseItems where guid=@Id", idBlob); - }, TransactionMode); + // Delete the item + ExecuteWithSingleParam(db, "delete from TypedBaseItems where guid=@Id", idBlob); + }, + TransactionMode); } } @@ -5038,7 +4768,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type if (whereClauses.Count != 0) { - commandText.Append(" where ").Append(string.Join(" AND ", whereClauses)); + commandText.Append(" where ").AppendJoin(" AND ", whereClauses); } commandText.Append(" order by ListOrder"); @@ -5124,16 +4854,16 @@ AND Type = @InternalPersonType)"); statement?.TryBind("@InternalPersonType", typeof(Person).FullName); } - if (!query.ItemId.Equals(Guid.Empty)) + if (!query.ItemId.Equals(default)) { whereClauses.Add("ItemId=@ItemId"); - statement?.TryBind("@ItemId", query.ItemId.ToByteArray()); + statement?.TryBind("@ItemId", query.ItemId); } - if (!query.AppearsInItemId.Equals(Guid.Empty)) + if (!query.AppearsInItemId.Equals(default)) { whereClauses.Add("p.Name in (Select Name from People where ItemId=@AppearsInItemId)"); - statement?.TryBind("@AppearsInItemId", query.AppearsInItemId.ToByteArray()); + statement?.TryBind("@AppearsInItemId", query.AppearsInItemId); } var queryPersonTypes = query.PersonTypes.Where(IsValidPersonType).ToList(); @@ -5186,7 +4916,7 @@ AND Type = @InternalPersonType)"); private void UpdateAncestors(Guid itemId, List<Guid> ancestorIds, IDatabaseConnection db, IStatement deleteAncestorsStatement) { - if (itemId.Equals(Guid.Empty)) + if (itemId.Equals(default)) { throw new ArgumentNullException(nameof(itemId)); } @@ -5244,32 +4974,32 @@ AND Type = @InternalPersonType)"); } } - public QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery query) { return GetItemValues(query, new[] { 0, 1 }, typeof(MusicArtist).FullName); } - public QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery query) { return GetItemValues(query, new[] { 0 }, typeof(MusicArtist).FullName); } - public QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery query) { return GetItemValues(query, new[] { 1 }, typeof(MusicArtist).FullName); } - public QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery query) { return GetItemValues(query, new[] { 3 }, typeof(Studio).FullName); } - public QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery query) { return GetItemValues(query, new[] { 2 }, typeof(Genre).FullName); } - public QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery query) { return GetItemValues(query, new[] { 2 }, typeof(MusicGenre).FullName); } @@ -5365,7 +5095,7 @@ AND Type = @InternalPersonType)"); return list; } - private QueryResult<(BaseItem, ItemCounts)> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType) + private QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType) { if (query == null) { @@ -5634,6 +5364,7 @@ AND Type = @InternalPersonType)"); result.TotalRecordCount = list.Count; } + result.StartIndex = query.StartIndex ?? 0; result.Items = list; return result; @@ -5690,7 +5421,7 @@ AND Type = @InternalPersonType)"); return counts; } - private List<(int, string)> GetItemValuesToSave(BaseItem item, List<string> inheritedTags) + private List<(int MagicNumber, string Value)> GetItemValuesToSave(BaseItem item, List<string> inheritedTags) { var list = new List<(int, string)>(); @@ -5715,9 +5446,9 @@ AND Type = @InternalPersonType)"); return list; } - private void UpdateItemValues(Guid itemId, List<(int, string)> values, IDatabaseConnection db) + private void UpdateItemValues(Guid itemId, List<(int MagicNumber, string Value)> values, IDatabaseConnection db) { - if (itemId.Equals(Guid.Empty)) + if (itemId.Equals(default)) { throw new ArgumentNullException(nameof(itemId)); } @@ -5737,7 +5468,7 @@ AND Type = @InternalPersonType)"); InsertItemValues(guidBlob, values, db); } - private void InsertItemValues(byte[] idBlob, List<(int, string)> values, IDatabaseConnection db) + private void InsertItemValues(byte[] idBlob, List<(int MagicNumber, string Value)> values, IDatabaseConnection db) { const int Limit = 100; var startIndex = 0; @@ -5769,7 +5500,7 @@ AND Type = @InternalPersonType)"); var currentValueInfo = values[i]; - var itemValue = currentValueInfo.Item2; + var itemValue = currentValueInfo.Value; // Don't save if invalid if (string.IsNullOrWhiteSpace(itemValue)) @@ -5777,7 +5508,7 @@ AND Type = @InternalPersonType)"); continue; } - statement.TryBind("@Type" + index, currentValueInfo.Item1); + statement.TryBind("@Type" + index, currentValueInfo.MagicNumber); statement.TryBind("@Value" + index, itemValue); statement.TryBind("@CleanValue" + index, GetCleanValue(itemValue)); } @@ -5793,7 +5524,7 @@ AND Type = @InternalPersonType)"); public void UpdatePeople(Guid itemId, List<PersonInfo> people) { - if (itemId.Equals(Guid.Empty)) + if (itemId.Equals(default)) { throw new ArgumentNullException(nameof(itemId)); } @@ -5808,15 +5539,16 @@ AND Type = @InternalPersonType)"); using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - var itemIdBlob = itemId.ToByteArray(); + db => + { + var itemIdBlob = itemId.ToByteArray(); - // First delete chapters - db.Execute("delete from People where ItemId=@ItemId", itemIdBlob); + // First delete chapters + db.Execute("delete from People where ItemId=@ItemId", itemIdBlob); - InsertPeople(itemIdBlob, people, db); - }, TransactionMode); + InsertPeople(itemIdBlob, people, db); + }, + TransactionMode); } } @@ -5925,7 +5657,7 @@ AND Type = @InternalPersonType)"); using (var statement = PrepareStatement(connection, cmdText)) { - statement.TryBind("@ItemId", query.ItemId.ToByteArray()); + statement.TryBind("@ItemId", query.ItemId); if (query.Type.HasValue) { @@ -5947,11 +5679,11 @@ AND Type = @InternalPersonType)"); } } - public void SaveMediaStreams(Guid id, List<MediaStream> streams, CancellationToken cancellationToken) + public void SaveMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, CancellationToken cancellationToken) { CheckDisposed(); - if (id == Guid.Empty) + if (id.Equals(default)) { throw new ArgumentNullException(nameof(id)); } @@ -5974,11 +5706,12 @@ AND Type = @InternalPersonType)"); db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob); InsertMediaStreams(itemIdBlob, streams, db); - }, TransactionMode); + }, + TransactionMode); } } - private void InsertMediaStreams(byte[] idBlob, List<MediaStream> streams, IDatabaseConnection db) + private void InsertMediaStreams(byte[] idBlob, IReadOnlyList<MediaStream> streams, IDatabaseConnection db) { const int Limit = 10; var startIndex = 0; @@ -6237,6 +5970,7 @@ AND Type = @InternalPersonType)"); item.LocalizedUndefined = _localization.GetLocalizedString("Undefined"); item.LocalizedDefault = _localization.GetLocalizedString("Default"); item.LocalizedForced = _localization.GetLocalizedString("Forced"); + item.LocalizedExternal = _localization.GetLocalizedString("External"); } return item; @@ -6286,7 +6020,7 @@ AND Type = @InternalPersonType)"); CancellationToken cancellationToken) { CheckDisposed(); - if (id == Guid.Empty) + if (id.Equals(default)) { throw new ArgumentException("Guid can't be empty.", nameof(id)); } @@ -6308,7 +6042,8 @@ AND Type = @InternalPersonType)"); db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob); InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken); - }, TransactionMode); + }, + TransactionMode); } } |
