diff options
| author | Shadowghost <Ghost_of_Stone@web.de> | 2026-01-17 15:58:00 +0100 |
|---|---|---|
| committer | Shadowghost <Ghost_of_Stone@web.de> | 2026-01-18 19:47:02 +0100 |
| commit | 912a963a2bf7f9534e9395d1a2da8d910f249b5b (patch) | |
| tree | 6b2889505322416228e175cb97cab8cb12aad092 /src/Jellyfin.Database/Jellyfin.Database.Implementations | |
| parent | f26058591729e2c381feca7e1e195dd8e8017a0b (diff) | |
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
Diffstat (limited to 'src/Jellyfin.Database/Jellyfin.Database.Implementations')
5 files changed, 62 insertions, 0 deletions
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/IDescendantQueryProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/IDescendantQueryProvider.cs new file mode 100644 index 0000000000..9e3d510b9c --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/IDescendantQueryProvider.cs @@ -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); +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/FolderMatchCriteria.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/FolderMatchCriteria.cs new file mode 100644 index 0000000000..d9f2d91806 --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/FolderMatchCriteria.cs @@ -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; diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasChapterImages.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasChapterImages.cs new file mode 100644 index 0000000000..3dd84bbd27 --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasChapterImages.cs @@ -0,0 +1,6 @@ +namespace Jellyfin.Database.Implementations.MatchCriteria; + +/// <summary> +/// Matches folders containing descendants with chapter images. +/// </summary> +public sealed record HasChapterImages : FolderMatchCriteria; diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasMediaStreamType.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasMediaStreamType.cs new file mode 100644 index 0000000000..68f2ca2786 --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasMediaStreamType.cs @@ -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; diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasSubtitles.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasSubtitles.cs new file mode 100644 index 0000000000..e50b9f3e12 --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasSubtitles.cs @@ -0,0 +1,6 @@ +namespace Jellyfin.Database.Implementations.MatchCriteria; + +/// <summary> +/// Matches folders containing descendants with subtitles. +/// </summary> +public sealed record HasSubtitles : FolderMatchCriteria; |
