Fix episodes count calculation on dapper

This commit is contained in:
Zoe Roux 2023-12-04 22:57:57 +01:00
parent e70174cb24
commit 0bc6512bcc
5 changed files with 29 additions and 19 deletions

View File

@ -137,7 +137,7 @@ namespace Kyoo.Abstractions.Models
from
episodes as e
where
e.season_id = id) as episode_count
e.season_id = id) as episodes_count
"""
)]
public int EpisodesCount { get; set; }

View File

@ -179,10 +179,22 @@ namespace Kyoo.Abstractions.Models
.FirstOrDefault();
/// <summary>
/// The number of episodes in this season.
/// The number of episodes in this show.
/// </summary>
[Projectable(UseMemberBody = nameof(_EpisodesCount), OnlyOnInclude = true)]
[NotMapped]
[LoadableRelation(
// language=PostgreSQL
Projected = """
(
select
count(*)::int
from
episodes as e
where
e.show_id = "this".id) as episodes_count
"""
)]
public int EpisodesCount { get; set; }
private int _EpisodesCount => Episodes!.Count;

View File

@ -204,13 +204,14 @@ public static class DapperHelper
return $"\nwhere {Process(filter)}";
}
public static string ExpendProjections(string type, string? prefix, Include include)
public static string ExpendProjections(Type type, string? prefix, Include include)
{
IEnumerable<string> projections = include.Metadatas
.Select(x => x is Include.ProjectedRelation(var name, var sql) ? sql : null!)
.Select(x => (x as Include.ProjectedRelation)!)
.Where(x => x != null)
.Select(x => x.Replace("\"this\".", prefix));
return string.Join(string.Empty, projections.Select(x => $", {x}"));
.Where(x => type.GetProperty(x.Name) != null)
.Select(x => x.Sql.Replace("\"this\".", prefix));
return string.Join(", ", projections);
}
public static async Task<ICollection<T>> Query<T>(
@ -265,18 +266,20 @@ public static class DapperHelper
string? prefix = match.Groups[4].Value;
prefix = !string.IsNullOrEmpty(prefix) ? $"{prefix}." : string.Empty;
Type typeV = types.First(x => x.Name == type);
// Only project top level items with explicit includes.
string? projection = config.Any(x => x.Value.Name == type)
? ExpendProjections(type, prefix, include)
? ExpendProjections(typeV, prefix, include)
: null;
Type? typeV = types.FirstOrDefault(x => x.Name == type);
if (typeV?.IsAssignableTo(typeof(IThumbnails)) == true)
if (typeV.IsAssignableTo(typeof(IThumbnails)))
{
string posterProj = string.Join(", ", new[] { "poster", "thumbnail", "logo" }
.Select(x => $"{prefix}{x}_source as source, {prefix}{x}_blurhash as blurhash"));
projection = string.IsNullOrEmpty(projection)
? posterProj
: $"{posterProj}, {projection}";
: $"{projection}, {posterProj}";
types.InsertRange(types.IndexOf(typeV) + 1, Enumerable.Repeat(typeof(Image), 3));
}

View File

@ -19,7 +19,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;

View File

@ -89,14 +89,6 @@ export const ShowP = withImages(
* The studio that made this show.
*/
studio: StudioP.optional().nullable(),
/**
* The collection this movie is part of.
*/
collections: z.array(CollectionP).optional(),
/**
* The list of seasons of this show.
*/
seasons: z.array(SeasonP).optional(),
/**
* The first episode of this show
*/
@ -109,6 +101,10 @@ export const ShowP = withImages(
* Metadata of what an user as started/planned to watch.
*/
watchStatus: ShowWatchStatusP.nullable().optional(),
/**
* The number of episodes in this show.
*/
episodesCount: z.number().int().gte(0).optional(),
}),
"shows",
)