diff options
| author | Shadowghost <Ghost_of_Stone@web.de> | 2026-08-02 22:12:57 +0200 |
|---|---|---|
| committer | Shadowghost <Ghost_of_Stone@web.de> | 2026-08-02 22:12:57 +0200 |
| commit | 80445347740955f0121fec5d1bf649212da3c63b (patch) | |
| tree | beb9ccb575879d8cc14d21fdd7fee6f8188d21c6 /Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs | |
| parent | 705368ee495cfb8967d3f1651318fbdb85ad89e6 (diff) | |
| parent | cac463d4c3c6eee34dff4faec95b8de2c639bd44 (diff) | |
Merge remote-tracking branch 'upstream/master' into fix-byname-queries
Diffstat (limited to 'Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs')
| -rw-r--r-- | Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs index 5aa2d7c46b..05ff720ddf 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs @@ -35,11 +35,40 @@ public sealed partial class BaseItemRepository { dbQuery = TranslateQuery(dbQuery, context, filter); dbQuery = ApplyGroupingFilter(context, dbQuery, filter); + dbQuery = ApplyAdjacencyFilter(context, dbQuery, filter); dbQuery = ApplyQueryPaging(dbQuery, filter); dbQuery = ApplyNavigations(dbQuery, filter); return dbQuery; } + /// <summary> + /// Trims an ordered query down to the AdjacentTo item and its immediate neighbours. + /// </summary> + private IQueryable<BaseItemEntity> ApplyAdjacencyFilter(JellyfinDbContext context, IQueryable<BaseItemEntity> dbQuery, InternalItemsQuery filter) + { + if (filter.AdjacentTo.IsNullOrEmpty()) + { + return dbQuery; + } + + // Adjacency is relative to the result set and the order the query asked for, so the ids have + // to be read back in that order. + var orderedIds = dbQuery.Select(e => e.Id).ToList(); + var index = orderedIds.IndexOf(filter.AdjacentTo.Value); + if (index < 0) + { + // The item isn't part of this result set, so it has no neighbours in it either. + return dbQuery.Take(0); + } + + var start = Math.Max(index - 1, 0); + var adjacentIds = orderedIds.GetRange(start, Math.Min(index + 2, orderedIds.Count) - start); + + var adjacentQuery = context.BaseItems.AsNoTracking().AsSingleQuery().Where(e => adjacentIds.Contains(e.Id)); + + return ApplyOrder(adjacentQuery, filter, context); + } + private IQueryable<BaseItemEntity> ApplyQueryPaging(IQueryable<BaseItemEntity> dbQuery, InternalItemsQuery filter) { if (filter.Limit.HasValue || filter.StartIndex.HasValue) @@ -244,8 +273,8 @@ public sealed partial class BaseItemRepository dbQuery = dbQuery.Include(e => e.Images); } - // Include LinkedChildEntities for container types and videos that use them - // (BoxSet, Playlist, CollectionFolder for manual linking; Video, Movie for alternate versions). + // Include LinkedChildEntities for container types and videos that use them (BoxSet, Playlist, + // CollectionFolder for manual linking; every video type for alternate versions). // When IncludeItemTypes is empty (any type may be returned), always include them to ensure // LinkedChildren are loaded before items are saved back, preventing accidental deletion. var linkedChildTypes = new[] @@ -254,7 +283,10 @@ public sealed partial class BaseItemRepository BaseItemKind.Playlist, BaseItemKind.CollectionFolder, BaseItemKind.Video, - BaseItemKind.Movie + BaseItemKind.Movie, + BaseItemKind.Episode, + BaseItemKind.MusicVideo, + BaseItemKind.Trailer }; if (filter.IncludeItemTypes.Length == 0 || filter.IncludeItemTypes.Any(linkedChildTypes.Contains)) { @@ -390,7 +422,8 @@ public sealed partial class BaseItemRepository var baseQuery = context.BaseItems .AsNoTracking() - .Where(b => allDescendantIds.Contains(b.Id) && !b.IsFolder && !b.IsVirtualItem); + .Where(b => allDescendantIds.Contains(b.Id)) + .Where(DescendantQueryHelper.IsCountableLeaf); return ApplyAccessFiltering(context, baseQuery, filter); } @@ -628,7 +661,7 @@ public sealed partial class BaseItemRepository var leafItems = context.BaseItems .AsNoTracking() - .Where(e => !e.IsFolder && !e.IsVirtualItem); + .Where(DescendantQueryHelper.IsCountableLeaf); return ApplyAccessFiltering(context, leafItems, new InternalItemsQuery(user) { IncludeOwnedItems = includeOwnedItems }); } |
