aboutsummaryrefslogtreecommitdiff
path: root/src/Jellyfin.Database/Jellyfin.Database.Implementations
diff options
context:
space:
mode:
authorShadowghost <Ghost_of_Stone@web.de>2026-01-17 15:58:00 +0100
committerShadowghost <Ghost_of_Stone@web.de>2026-01-18 19:47:02 +0100
commit912a963a2bf7f9534e9395d1a2da8d910f249b5b (patch)
tree6b2889505322416228e175cb97cab8cb12aad092 /src/Jellyfin.Database/Jellyfin.Database.Implementations
parentf26058591729e2c381feca7e1e195dd8e8017a0b (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')
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/IDescendantQueryProvider.cs30
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/FolderMatchCriteria.cs6
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasChapterImages.cs6
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasMediaStreamType.cs14
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/MatchCriteria/HasSubtitles.cs6
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;