Add folder-aware filter extensions and descendant query provider

- Add FolderAwareFilterExtensions for LinkedChildren-based filtering
- Add IDescendantQueryProvider interface for database-specific queries
- Add MatchCriteria classes for folder filtering
- Add SqliteDescendantQueryProvider implementation
This commit is contained in:
Shadowghost
2026-01-17 15:58:00 +01:00
parent f260585917
commit 912a963a2b
7 changed files with 256 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
using System;
using System.Linq;
using Jellyfin.Database.Implementations.MatchCriteria;
namespace Jellyfin.Database.Implementations;
/// <summary>
/// Provider interface for descendant queries using recursive CTEs.
/// Each database provider implements this with provider-specific SQL.
/// </summary>
public interface IDescendantQueryProvider
{
/// <summary>
/// Gets a queryable of all descendant IDs for a parent item.
/// Uses recursive CTE to traverse AncestorIds and LinkedChildren infinitely.
/// </summary>
/// <param name="context">Database context.</param>
/// <param name="parentId">Parent item ID.</param>
/// <returns>Queryable of descendant item IDs.</returns>
IQueryable<Guid> GetAllDescendantIds(JellyfinDbContext context, Guid parentId);
/// <summary>
/// Gets a queryable of all folder IDs that have any descendant matching the specified criteria.
/// Uses recursive CTE for infinite depth traversal. Can be used in LINQ .Contains() expressions.
/// </summary>
/// <param name="context">Database context.</param>
/// <param name="criteria">The matching criteria to apply.</param>
/// <returns>Queryable of folder IDs.</returns>
IQueryable<Guid> GetFolderIdsMatching(JellyfinDbContext context, FolderMatchCriteria criteria);
}

View File

@@ -0,0 +1,6 @@
namespace Jellyfin.Database.Implementations.MatchCriteria;
/// <summary>
/// Base type for folder matching criteria using discriminated union pattern.
/// </summary>
public abstract record FolderMatchCriteria;

View File

@@ -0,0 +1,6 @@
namespace Jellyfin.Database.Implementations.MatchCriteria;
/// <summary>
/// Matches folders containing descendants with chapter images.
/// </summary>
public sealed record HasChapterImages : FolderMatchCriteria;

View File

@@ -0,0 +1,14 @@
using Jellyfin.Database.Implementations.Entities;
namespace Jellyfin.Database.Implementations.MatchCriteria;
/// <summary>
/// Matches folders containing descendants with a specific media stream type and language.
/// </summary>
/// <param name="StreamType">The type of media stream to match (Audio, Subtitle, etc.).</param>
/// <param name="Language">The language to match.</param>
/// <param name="IsExternal">If not null, filters by internal (false) or external (true) streams. Only applicable to subtitles.</param>
public sealed record HasMediaStreamType(
MediaStreamTypeEntity StreamType,
string Language,
bool? IsExternal = null) : FolderMatchCriteria;

View File

@@ -0,0 +1,6 @@
namespace Jellyfin.Database.Implementations.MatchCriteria;
/// <summary>
/// Matches folders containing descendants with subtitles.
/// </summary>
public sealed record HasSubtitles : FolderMatchCriteria;