From ea2c794cb2520ccb2d322da8c186875b7cebe006 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Sat, 22 Aug 2026 17:22:41 +0200 Subject: Adapt to master --- .../DescendantQueryHelper.cs | 43 ++++++++++++---------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/DescendantQueryHelper.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/DescendantQueryHelper.cs index ac47f00a18..b821476390 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/DescendantQueryHelper.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/DescendantQueryHelper.cs @@ -32,23 +32,15 @@ public static class DescendantQueryHelper { ArgumentNullException.ThrowIfNull(context); - var (closureRoots, linkRoots) = ResolveLinkedRoots(context, parentId); - - var hierarchyDescendants = ClosureDescendants(context, closureRoots); - - var linkedDescendants = context.LinkedChildren - .WhereOneOrMany(linkRoots, e => e.ParentId) - .Select(e => e.ChildId); - - return hierarchyDescendants - .Concat(linkedDescendants) + return AllDescendants(context, [parentId]) .Where(e => !e.Equals(parentId)) .Distinct(); } /// /// Gets all descendant IDs for multiple parent items in a single traversal. - /// Traverses AncestorIds and LinkedChildren, like . + /// Traverses AncestorIds and LinkedChildren, like , but resolves + /// the roots once for all seeds instead of once per seed. /// /// Database context. /// Parent item IDs. @@ -63,10 +55,11 @@ public static class DescendantQueryHelper return []; } - var seedSet = new HashSet(parentIds); - var descendants = TraverseHierarchyDown(context, seedSet); + var descendants = AllDescendants(context, parentIds) + .Distinct() + .ToHashSet(); - descendants.ExceptWith(seedSet); + descendants.ExceptWith(parentIds); return descendants; } @@ -241,6 +234,18 @@ public static class DescendantQueryHelper return query; } + private static IQueryable AllDescendants(JellyfinDbContext context, IReadOnlyList parentIds) + { + var (closureRoots, linkRoots) = ResolveLinkedRoots(context, parentIds); + + var linkedDescendants = context.LinkedChildren + .WhereOneOrMany(linkRoots, e => e.ParentId) + .Select(e => e.ChildId); + + return ClosureDescendants(context, closureRoots) + .Concat(linkedDescendants); + } + private static IQueryable ClosureDescendants(JellyfinDbContext context, IReadOnlyList roots) { var direct = context.AncestorIds @@ -311,12 +316,12 @@ public static class DescendantQueryHelper // Resolves the roots the descendant sub-selects are anchored on: those contributing their closure, // and those contributing their linked children. - private static (List ClosureRoots, List LinkRoots) ResolveLinkedRoots(JellyfinDbContext context, Guid parentId) + private static (List ClosureRoots, List LinkRoots) ResolveLinkedRoots(JellyfinDbContext context, IReadOnlyList parentIds) { - var closureRoots = new List { parentId }; - var linkRoots = new List { parentId }; - var visited = new HashSet { parentId }; - var frontier = new List { parentId }; + var visited = new HashSet(parentIds); + var closureRoots = visited.ToList(); + var linkRoots = visited.ToList(); + var frontier = visited.ToList(); while (frontier.Count != 0) { -- cgit v1.2.3