From 5a496a1fc8d9ee2e728d6f712ae6bdf4862183f1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 6 May 2016 00:50:39 -0400 Subject: [PATCH] reduce recursive querying --- MediaBrowser.Api/BaseApiService.cs | 189 ++++++++---------- MediaBrowser.Api/VideosService.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 20 ++ MediaBrowser.Controller/Entities/Folder.cs | 4 +- .../Entities/InternalItemsQuery.cs | 7 +- .../Entities/Movies/BoxSet.cs | 3 +- MediaBrowser.Controller/Entities/Video.cs | 147 +++++++------- .../Dto/DtoService.cs | 45 ----- .../Library/Validators/StudiosValidator.cs | 44 +--- .../Persistence/SqliteItemRepository.cs | 59 +++++- 10 files changed, 247 insertions(+), 273 deletions(-) diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 30750b3741..44d459a01e 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Api } } } - + /// /// To the optimized serialized result using cache. /// @@ -118,9 +118,6 @@ namespace MediaBrowser.Api return ResultFactory.GetStaticFileResult(Request, path); } - private readonly char[] _dashReplaceChars = { '?', '/', '&' }; - private const char SlugChar = '-'; - protected DtoOptions GetDtoOptions(object request) { var options = new DtoOptions(); @@ -154,152 +151,122 @@ namespace MediaBrowser.Api protected MusicArtist GetArtist(string name, ILibraryManager libraryManager) { - return libraryManager.GetArtist(DeSlugArtistName(name, libraryManager)); - } - - protected Studio GetStudio(string name, ILibraryManager libraryManager) - { - return libraryManager.GetStudio(DeSlugStudioName(name, libraryManager)); - } - - protected Genre GetGenre(string name, ILibraryManager libraryManager) - { - return libraryManager.GetGenre(DeSlugGenreName(name, libraryManager)); - } + if (name.IndexOf(BaseItem.SlugChar) != -1) + { + var result = libraryManager.GetItemList(new InternalItemsQuery + { + SlugName = name, + IncludeItemTypes = new[] { typeof(MusicArtist).Name } - protected MusicGenre GetMusicGenre(string name, ILibraryManager libraryManager) - { - return libraryManager.GetMusicGenre(DeSlugGenreName(name, libraryManager)); - } + }).OfType().FirstOrDefault(); - protected GameGenre GetGameGenre(string name, ILibraryManager libraryManager) - { - return libraryManager.GetGameGenre(DeSlugGameGenreName(name, libraryManager)); - } + if (result != null) + { + return result; + } + } - protected Person GetPerson(string name, ILibraryManager libraryManager) - { - return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager)); + return libraryManager.GetArtist(name); } - /// - /// Deslugs an artist name by finding the correct entry in the library - /// - /// - /// - /// - protected string DeSlugArtistName(string name, ILibraryManager libraryManager) + protected Studio GetStudio(string name, ILibraryManager libraryManager) { - if (name.IndexOf(SlugChar) == -1) - { - return name; - } - - var items = libraryManager.GetItemList(new InternalItemsQuery + if (name.IndexOf(BaseItem.SlugChar) != -1) { - IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name } - }); - - return items - .OfType() - .SelectMany(i => i.AllArtists) - .DistinctNames() - .FirstOrDefault(i => + var result = libraryManager.GetItemList(new InternalItemsQuery { - i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar)); + SlugName = name, + IncludeItemTypes = new[] { typeof(Studio).Name } - return string.Equals(i, name, StringComparison.OrdinalIgnoreCase); + }).OfType().FirstOrDefault(); + + if (result != null) + { + return result; + } + } - }) ?? name; + return libraryManager.GetStudio(name); } - /// - /// Deslugs a genre name by finding the correct entry in the library - /// - protected string DeSlugGenreName(string name, ILibraryManager libraryManager) + protected Genre GetGenre(string name, ILibraryManager libraryManager) { - if (name.IndexOf(SlugChar) == -1) + if (name.IndexOf(BaseItem.SlugChar) != -1) { - return name; - } - - return libraryManager.RootFolder.GetRecursiveChildren() - .SelectMany(i => i.Genres) - .DistinctNames() - .FirstOrDefault(i => + var result = libraryManager.GetItemList(new InternalItemsQuery { - i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar)); + SlugName = name, + IncludeItemTypes = new[] { typeof(Genre).Name } - return string.Equals(i, name, StringComparison.OrdinalIgnoreCase); + }).OfType().FirstOrDefault(); + + if (result != null) + { + return result; + } + } - }) ?? name; + return libraryManager.GetGenre(name); } - protected string DeSlugGameGenreName(string name, ILibraryManager libraryManager) + protected MusicGenre GetMusicGenre(string name, ILibraryManager libraryManager) { - if (name.IndexOf(SlugChar) == -1) + if (name.IndexOf(BaseItem.SlugChar) != -1) { - return name; - } + var result = libraryManager.GetItemList(new InternalItemsQuery + { + SlugName = name, + IncludeItemTypes = new[] { typeof(MusicGenre).Name } - var items = libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Game).Name } - }); + }).OfType().FirstOrDefault(); - return items - .SelectMany(i => i.Genres) - .DistinctNames() - .FirstOrDefault(i => + if (result != null) { - i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar)); - - return string.Equals(i, name, StringComparison.OrdinalIgnoreCase); + return result; + } + } - }) ?? name; + return libraryManager.GetMusicGenre(name); } - /// - /// Deslugs a studio name by finding the correct entry in the library - /// - protected string DeSlugStudioName(string name, ILibraryManager libraryManager) + protected GameGenre GetGameGenre(string name, ILibraryManager libraryManager) { - if (name.IndexOf(SlugChar) == -1) + if (name.IndexOf(BaseItem.SlugChar) != -1) { - return name; - } - - return libraryManager.RootFolder - .GetRecursiveChildren() - .SelectMany(i => i.Studios) - .DistinctNames() - .FirstOrDefault(i => + var result = libraryManager.GetItemList(new InternalItemsQuery { - i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar)); + SlugName = name, + IncludeItemTypes = new[] { typeof(GameGenre).Name } - return string.Equals(i, name, StringComparison.OrdinalIgnoreCase); + }).OfType().FirstOrDefault(); - }) ?? name; + if (result != null) + { + return result; + } + } + + return libraryManager.GetGameGenre(name); } - /// - /// Deslugs a person name by finding the correct entry in the library - /// - protected string DeSlugPersonName(string name, ILibraryManager libraryManager) + protected Person GetPerson(string name, ILibraryManager libraryManager) { - if (name.IndexOf(SlugChar) == -1) + if (name.IndexOf(BaseItem.SlugChar) != -1) { - return name; - } - - return libraryManager.GetPeopleNames(new InternalPeopleQuery()) - .FirstOrDefault(i => + var result = libraryManager.GetItemList(new InternalItemsQuery { - i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar)); + SlugName = name, + IncludeItemTypes = new[] { typeof(Person).Name } - return string.Equals(i, name, StringComparison.OrdinalIgnoreCase); + }).OfType().FirstOrDefault(); + + if (result != null) + { + return result; + } + } - }) ?? name; + return libraryManager.GetPerson(name); } protected string GetPathValue(int index) diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs index 6cefda3a35..c8dbb7bb26 100644 --- a/MediaBrowser.Api/VideosService.cs +++ b/MediaBrowser.Api/VideosService.cs @@ -175,7 +175,7 @@ namespace MediaBrowser.Api foreach (var item in items.Where(i => i.Id != primaryVersion.Id)) { - item.PrimaryVersionId = primaryVersion.Id; + item.PrimaryVersionId = primaryVersion.Id.ToString("N"); await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 6bf55e108c..2e968c8803 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -44,6 +44,9 @@ namespace MediaBrowser.Controller.Entities ImageInfos = new List(); } + public static readonly char[] SlugReplaceChars = { '?', '/', '&' }; + public static char SlugChar = '-'; + /// /// The supported image extensions /// @@ -125,6 +128,21 @@ namespace MediaBrowser.Controller.Entities } } + [IgnoreDataMember] + public string SlugName + { + get + { + var name = Name; + if (string.IsNullOrWhiteSpace(name)) + { + return string.Empty; + } + + return SlugReplaceChars.Aggregate(name, (current, c) => current.Replace(c, SlugChar)); + } + } + public string OriginalTitle { get; set; } /// @@ -728,12 +746,14 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the critic rating. /// /// The critic rating. + [IgnoreDataMember] public float? CriticRating { get; set; } /// /// Gets or sets the critic rating summary. /// /// The critic rating summary. + [IgnoreDataMember] public string CriticRatingSummary { get; set; } /// diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index f57e2fa17a..d9c0b7bfe3 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -707,8 +707,8 @@ namespace MediaBrowser.Controller.Entities { return ItemRepository.GetItemIdsList(new InternalItemsQuery { - ParentId = Id - + ParentId = Id, + GroupByPresentationUniqueKey = false }); } diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 6838fde714..2615f351ad 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -49,6 +49,7 @@ namespace MediaBrowser.Controller.Entities public string PresentationUniqueKey { get; set; } public string Path { get; set; } public string Name { get; set; } + public string SlugName { get; set; } public string Person { get; set; } public string[] PersonIds { get; set; } @@ -133,9 +134,13 @@ namespace MediaBrowser.Controller.Entities public string[] AlbumNames { get; set; } public string[] ArtistNames { get; set; } - + + public bool GroupByPresentationUniqueKey { get; set; } + public InternalItemsQuery() { + GroupByPresentationUniqueKey = true; + AlbumNames = new string[] { }; ArtistNames = new string[] { }; diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index cd3e07ea38..09a9d97bcf 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using MediaBrowser.Controller.Entities.Audio; namespace MediaBrowser.Controller.Entities.Movies { @@ -118,7 +119,7 @@ namespace MediaBrowser.Controller.Entities.Movies // Gather all possible ratings var ratings = GetRecursiveChildren() .Concat(GetLinkedChildren()) - .Where(i => i is Movie || i is Series) + .Where(i => i is Movie || i is Series || i is MusicAlbum || i is Game) .Select(i => i.OfficialRating) .Where(i => !string.IsNullOrEmpty(i)) .Distinct(StringComparer.OrdinalIgnoreCase) diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 67b710534c..6a9d7cb511 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -28,7 +28,8 @@ namespace MediaBrowser.Controller.Entities IThemeMedia, IArchivable { - public Guid? PrimaryVersionId { get; set; } + [IgnoreDataMember] + public string PrimaryVersionId { get; set; } public List AdditionalParts { get; set; } public List LocalAlternateVersions { get; set; } @@ -49,9 +50,9 @@ namespace MediaBrowser.Controller.Entities { get { - if (PrimaryVersionId.HasValue) + if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) { - return PrimaryVersionId.Value.ToString("N"); + return PrimaryVersionId; } return base.PresentationUniqueKey; @@ -70,6 +71,72 @@ namespace MediaBrowser.Controller.Entities /// The timestamp. public TransportStreamTimestamp? Timestamp { get; set; } + /// + /// Gets or sets the subtitle paths. + /// + /// The subtitle paths. + public List SubtitleFiles { get; set; } + + /// + /// Gets or sets a value indicating whether this instance has subtitles. + /// + /// true if this instance has subtitles; otherwise, false. + public bool HasSubtitles { get; set; } + + public bool IsPlaceHolder { get; set; } + public bool IsShortcut { get; set; } + public string ShortcutPath { get; set; } + + /// + /// Gets or sets the video bit rate. + /// + /// The video bit rate. + public int? VideoBitRate { get; set; } + + /// + /// Gets or sets the default index of the video stream. + /// + /// The default index of the video stream. + public int? DefaultVideoStreamIndex { get; set; } + + /// + /// Gets or sets the type of the video. + /// + /// The type of the video. + public VideoType VideoType { get; set; } + + /// + /// Gets or sets the type of the iso. + /// + /// The type of the iso. + public IsoType? IsoType { get; set; } + + /// + /// Gets or sets the video3 D format. + /// + /// The video3 D format. + public Video3DFormat? Video3DFormat { get; set; } + + /// + /// If the video is a folder-rip, this will hold the file list for the largest playlist + /// + public List PlayableStreamFileNames { get; set; } + + /// + /// Gets the playable stream files. + /// + /// List{System.String}. + public List GetPlayableStreamFiles() + { + return GetPlayableStreamFiles(Path); + } + + /// + /// Gets or sets the aspect ratio. + /// + /// The aspect ratio. + public string AspectRatio { get; set; } + public Video() { PlayableStreamFileNames = new List(); @@ -104,9 +171,9 @@ namespace MediaBrowser.Controller.Entities { get { - if (PrimaryVersionId.HasValue) + if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) { - var item = LibraryManager.GetItemById(PrimaryVersionId.Value) as Video; + var item = LibraryManager.GetItemById(PrimaryVersionId) as Video; if (item != null) { return item.MediaSourceCount; @@ -238,72 +305,6 @@ namespace MediaBrowser.Controller.Entities .OrderBy(i => i.SortName); } - /// - /// Gets or sets the subtitle paths. - /// - /// The subtitle paths. - public List SubtitleFiles { get; set; } - - /// - /// Gets or sets a value indicating whether this instance has subtitles. - /// - /// true if this instance has subtitles; otherwise, false. - public bool HasSubtitles { get; set; } - - public bool IsPlaceHolder { get; set; } - public bool IsShortcut { get; set; } - public string ShortcutPath { get; set; } - - /// - /// Gets or sets the video bit rate. - /// - /// The video bit rate. - public int? VideoBitRate { get; set; } - - /// - /// Gets or sets the default index of the video stream. - /// - /// The default index of the video stream. - public int? DefaultVideoStreamIndex { get; set; } - - /// - /// Gets or sets the type of the video. - /// - /// The type of the video. - public VideoType VideoType { get; set; } - - /// - /// Gets or sets the type of the iso. - /// - /// The type of the iso. - public IsoType? IsoType { get; set; } - - /// - /// Gets or sets the video3 D format. - /// - /// The video3 D format. - public Video3DFormat? Video3DFormat { get; set; } - - /// - /// If the video is a folder-rip, this will hold the file list for the largest playlist - /// - public List PlayableStreamFileNames { get; set; } - - /// - /// Gets the playable stream files. - /// - /// List{System.String}. - public List GetPlayableStreamFiles() - { - return GetPlayableStreamFiles(Path); - } - - /// - /// Gets or sets the aspect ratio. - /// - /// The aspect ratio. - public string AspectRatio { get; set; } - [IgnoreDataMember] public override string ContainingFolderPath { @@ -520,9 +521,9 @@ namespace MediaBrowser.Controller.Entities list.Add(new Tuple(this, MediaSourceType.Default)); list.AddRange(GetLinkedAlternateVersions().Select(i => new Tuple(i, MediaSourceType.Grouping))); - if (PrimaryVersionId.HasValue) + if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) { - var primary = LibraryManager.GetItemById(PrimaryVersionId.Value) as Video; + var primary = LibraryManager.GetItemById(PrimaryVersionId) as Video; if (primary != null) { var existingIds = list.Select(i => i.Item1.Id).ToList(); diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index ff94552dad..0aec3230da 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -397,12 +397,6 @@ namespace MediaBrowser.Server.Implementations.Dto collectionFolder.GetViewType(user); } - var playlist = item as Playlist; - if (playlist != null) - { - AttachLinkedChildImages(dto, playlist, user, options); - } - if (fields.Contains(ItemFields.CanDelete)) { dto.CanDelete = user == null @@ -1564,45 +1558,6 @@ namespace MediaBrowser.Server.Implementations.Dto } } - private void AttachLinkedChildImages(BaseItemDto dto, Folder folder, User user, DtoOptions options) - { - List linkedChildren = null; - - var backdropLimit = options.GetImageLimit(ImageType.Backdrop); - - if (backdropLimit > 0 && dto.BackdropImageTags.Count == 0) - { - linkedChildren = user == null - ? folder.GetRecursiveChildren().ToList() - : folder.GetRecursiveChildren(user).ToList(); - - var parentWithBackdrop = linkedChildren.FirstOrDefault(i => i.GetImages(ImageType.Backdrop).Any()); - - if (parentWithBackdrop != null) - { - dto.ParentBackdropItemId = GetDtoId(parentWithBackdrop); - dto.ParentBackdropImageTags = GetBackdropImageTags(parentWithBackdrop, backdropLimit); - } - } - - if (!dto.ImageTags.ContainsKey(ImageType.Primary) && options.GetImageLimit(ImageType.Primary) > 0) - { - if (linkedChildren == null) - { - linkedChildren = user == null - ? folder.GetRecursiveChildren().ToList() - : folder.GetRecursiveChildren(user).ToList(); - } - var parentWithImage = linkedChildren.FirstOrDefault(i => i.GetImages(ImageType.Primary).Any()); - - if (parentWithImage != null) - { - dto.ParentPrimaryImageItemId = GetDtoId(parentWithImage); - dto.ParentPrimaryImageTag = GetImageCacheTag(parentWithImage, ImageType.Primary); - } - } - } - private string GetMappedPath(IHasMetadata item) { var path = item.Path; diff --git a/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs index c122d64d30..00dc8e6a10 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs @@ -2,7 +2,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Logging; using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -35,25 +34,20 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// Task. public async Task Run(IProgress progress, CancellationToken cancellationToken) { - var items = _libraryManager.RootFolder.GetRecursiveChildren() - .SelectMany(i => i.Studios) - .DistinctNames() - .ToList(); + var items = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = new[] { typeof(Studio).Name } + + }).ToList(); var numComplete = 0; var count = items.Count; - var validIds = new List(); - - foreach (var name in items) + foreach (var item in items) { try { - var itemByName = _libraryManager.GetStudio(name); - - validIds.Add(itemByName.Id); - - await itemByName.RefreshMetadata(cancellationToken).ConfigureAwait(false); + await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { @@ -62,7 +56,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.ErrorException("Error refreshing {0}", ex, name); + _logger.ErrorException("Error refreshing {0}", ex, item.Name); } numComplete++; @@ -73,28 +67,6 @@ namespace MediaBrowser.Server.Implementations.Library.Validators progress.Report(percent); } - var allIds = _libraryManager.GetItemIds(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Studio).Name } - }); - - var invalidIds = allIds - .Except(validIds) - .ToList(); - - foreach (var id in invalidIds) - { - cancellationToken.ThrowIfCancellationRequested(); - - var item = _libraryManager.GetItemById(id); - - await _libraryManager.DeleteItem(item, new DeleteOptions - { - DeleteFileLocation = false - - }).ConfigureAwait(false); - } - progress.Report(100); } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index d825a8de96..7199301af5 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -82,7 +82,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - public const int LatestSchemaVersion = 69; + public const int LatestSchemaVersion = 71; /// /// Initializes a new instance of the class. @@ -226,6 +226,9 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "CleanName", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "PresentationUniqueKey", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "SlugName", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "OriginalTitle", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "PrimaryVersionId", "Text"); string[] postQueries = { @@ -367,7 +370,9 @@ namespace MediaBrowser.Server.Implementations.Persistence "Tags", "SourceType", "TrailerTypes", - "DateModifiedDuringLastRefresh" + "DateModifiedDuringLastRefresh", + "OriginalTitle", + "PrimaryVersionId" }; private readonly string[] _mediaStreamSaveColumns = @@ -476,7 +481,10 @@ namespace MediaBrowser.Server.Implementations.Persistence "DateModifiedDuringLastRefresh", "InheritedTags", "CleanName", - "PresentationUniqueKey" + "PresentationUniqueKey", + "SlugName", + "OriginalTitle", + "PrimaryVersionId" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -810,7 +818,20 @@ namespace MediaBrowser.Server.Implementations.Persistence { _saveItemCommand.GetParameter(index++).Value = item.Name.RemoveDiacritics(); } + _saveItemCommand.GetParameter(index++).Value = item.PresentationUniqueKey; + _saveItemCommand.GetParameter(index++).Value = item.SlugName; + _saveItemCommand.GetParameter(index++).Value = item.OriginalTitle; + + var video = item as Video; + if (video != null) + { + _saveItemCommand.GetParameter(index++).Value = video.PrimaryVersionId; + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } _saveItemCommand.Transaction = transaction; @@ -1189,6 +1210,20 @@ namespace MediaBrowser.Server.Implementations.Persistence item.DateModifiedDuringLastRefresh = reader.GetDateTime(51).ToUniversalTime(); } + if (!reader.IsDBNull(52)) + { + item.OriginalTitle = reader.GetString(52); + } + + var video = item as Video; + if (video != null) + { + if (!reader.IsDBNull(53)) + { + video.PrimaryVersionId = reader.GetString(53); + } + } + return item; } @@ -2070,6 +2105,19 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.Parameters.Add(cmd, "@PersonName", DbType.String).Value = query.Person; } + if (!string.IsNullOrWhiteSpace(query.SlugName)) + { + if (_config.Configuration.SchemaVersion >= 70) + { + whereClauses.Add("SlugName=@SlugName"); + } + else + { + whereClauses.Add("Name=@SlugName"); + } + cmd.Parameters.Add(cmd, "@SlugName", DbType.String).Value = query.SlugName; + } + if (!string.IsNullOrWhiteSpace(query.Name)) { if (_config.Configuration.SchemaVersion >= 66) @@ -2340,6 +2388,11 @@ namespace MediaBrowser.Server.Implementations.Persistence private bool EnableGroupByPresentationUniqueKey(InternalItemsQuery query) { + if (!query.GroupByPresentationUniqueKey) + { + return false; + } + if (!string.IsNullOrWhiteSpace(query.PresentationUniqueKey)) { return false;