From 3eff6228be09d38e41ccc658c55d25a0a5913fa9 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 24 Nov 2023 00:18:59 +0100 Subject: [PATCH] Use new filter in dapper --- .../Repositories/LibraryItemRepository.cs | 52 +++++++++++++------ .../Kyoo.Postgresql/Kyoo.Postgresql.csproj | 1 + back/src/Kyoo.Postgresql/PostgresModule.cs | 2 + 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs index 3b3a8a8f..25f01a6b 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs @@ -177,7 +177,7 @@ namespace Kyoo.Core.Controllers return (retConfig, join.ToString(), Map); } - public static string ExpendProjections(string? prefix, Include include) + public static FormattableString ExpendProjections(string? prefix, Include include) { prefix = prefix != null ? $"{prefix}." : string.Empty; IEnumerable projections = include.Metadatas @@ -185,18 +185,40 @@ namespace Kyoo.Core.Controllers .Where(x => x != null) .Select(x => x.Replace("\"this\".", prefix)); string projStr = string.Join(string.Empty, projections.Select(x => $", {x}")); - return $"{prefix}*" + projStr; + return $"{prefix:raw}*{projStr:raw}"; } - public static string ProcessFilter(Filter filter, Dictionary config) + public static FormattableString ProcessFilter(Filter filter, Dictionary config) { - return filter switch + FormattableString Format(string key, FormattableString op) { - Filter.And(var first, var second) => $"({ProcessFilter(first, config)} and {ProcessFilter(second, config)})", - Filter.Or(var first, var second) => $"({ProcessFilter(first, config)} or {ProcessFilter(second, config)})", - Filter.Not(var inner) => $"(not {ProcessFilter(inner, config)})", - Filter.Eq(var property, var value) => $"({_Property(property, config)} = {value})", - }; + IEnumerable properties = config + .Where(x => key == "id" || x.Value.GetProperty(key) != null) + .Select(x => $"{x.Key}.{x.Value.GetProperty(key)?.GetCustomAttribute()?.Name ?? key.ToSnakeCase()}"); + + FormattableString ret = $"{properties.First():raw} {op}"; + foreach (string property in properties.Skip(1)) + ret = $"{ret} or {property:raw} {op}"; + return $"({ret})"; + } + + FormattableString Process(Filter fil) + { + return fil switch + { + Filter.And(var first, var second) => $"({Process(first)} and {Process(second)})", + Filter.Or(var first, var second) => $"({Process(first)} or {Process(second)})", + Filter.Not(var inner) => $"(not {Process(inner)})", + Filter.Eq(var property, var value) => Format(property, $"= {value}"), + Filter.Ne(var property, var value) => Format(property, $"!= {value}"), + Filter.Gt(var property, var value) => Format(property, $"> {value}"), + Filter.Ge(var property, var value) => Format(property, $">= {value}"), + Filter.Lt(var property, var value) => Format(property, $"< {value}"), + Filter.Le(var property, var value) => Format(property, $"> {value}"), + Filter.Lambda(var lambda) => throw new NotSupportedException(), + }; + } + return $"where {Process(filter)}"; } public async Task> GetAll(Filter? filter = null, @@ -217,7 +239,7 @@ namespace Kyoo.Core.Controllers // language=PostgreSQL var query = _database.SqlBuilder($""" select - {ExpendProjections("s", include):raw}, + {ExpendProjections("s", include)}, m.*, c.* {string.Join(string.Empty, includeConfig.Select(x => $", {x.Key}.*")):raw} @@ -225,21 +247,21 @@ namespace Kyoo.Core.Controllers shows as s full outer join ( select - {ExpendProjections(null, include):raw} + {ExpendProjections(null, include)} from movies) as m on false full outer join ( select - {ExpendProjections(null, include):raw} + {ExpendProjections(null, include)} from collections) as c on false {includeJoin:raw} - order by {ProcessSort(sort, config):raw} - limit {limit.Limit} """); if (filter != null) - query += $"where {ProcessFilter(filter, config):raw}"; + query += ProcessFilter(filter, config); + query += $"order by {ProcessSort(sort, config):raw}"; + query += $"limit {limit.Limit}"; Type[] types = config.Select(x => x.Value) .Concat(includeConfig.Select(x => x.Value)) diff --git a/back/src/Kyoo.Postgresql/Kyoo.Postgresql.csproj b/back/src/Kyoo.Postgresql/Kyoo.Postgresql.csproj index b852ee67..be3a7ff6 100644 --- a/back/src/Kyoo.Postgresql/Kyoo.Postgresql.csproj +++ b/back/src/Kyoo.Postgresql/Kyoo.Postgresql.csproj @@ -9,6 +9,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/back/src/Kyoo.Postgresql/PostgresModule.cs b/back/src/Kyoo.Postgresql/PostgresModule.cs index 7f8785d2..5fe9bdf8 100644 --- a/back/src/Kyoo.Postgresql/PostgresModule.cs +++ b/back/src/Kyoo.Postgresql/PostgresModule.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Text.RegularExpressions; using Dapper; +using InterpolatedSql.SqlBuilders; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Postgresql.Utils; @@ -87,6 +88,7 @@ namespace Kyoo.Postgresql SqlMapper.AddTypeHandler(typeof(Dictionary), new JsonTypeHandler>()); SqlMapper.AddTypeHandler(typeof(List), new ListTypeHandler()); SqlMapper.AddTypeHandler(typeof(List), new ListTypeHandler()); + InterpolatedSqlBuilderOptions.DefaultOptions.ReuseIdenticalParameters = true; } ///