From de9ac4b074fd40b6bbb2b3dc57b663039aadd72a Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Mon, 6 Sep 2021 16:30:35 +0200 Subject: [PATCH] Incremental fix for YesSQL provider with And/Or specifications Fixes #1472 --- .../Specifications/AndSpecification.cs | 18 ++++++------ .../Specifications/NotSpecification.cs | 2 +- .../Specifications/OrSpecification.cs | 2 +- .../Stores/YesSqlWorkflowDefinitionStore.cs | 29 +++++++++++++++++++ 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/core/Elsa.Abstractions/Persistence/Specifications/AndSpecification.cs b/src/core/Elsa.Abstractions/Persistence/Specifications/AndSpecification.cs index ffd351ff6..17de4b2bf 100644 --- a/src/core/Elsa.Abstractions/Persistence/Specifications/AndSpecification.cs +++ b/src/core/Elsa.Abstractions/Persistence/Specifications/AndSpecification.cs @@ -4,18 +4,18 @@ using LinqKit; namespace Elsa.Persistence.Specifications { - internal struct AndSpecification : ISpecification + public struct AndSpecification : ISpecification { - private readonly ISpecification _left; - private readonly ISpecification _right; - public AndSpecification(ISpecification left, ISpecification right) { - _right = right; - _left = left; + Right = right; + Left = left; } - public bool IsSatisfiedBy(T entity) => _left.IsSatisfiedBy(entity) && _right.IsSatisfiedBy(entity); - public Expression> ToExpression() => _left.ToExpression().And(_right.ToExpression()); + public bool IsSatisfiedBy(T entity) => Left.IsSatisfiedBy(entity) && Right.IsSatisfiedBy(entity); + public Expression> ToExpression() => Left.ToExpression().And(Right.ToExpression()); + + public ISpecification Left { get; } + public ISpecification Right { get; } } -} +} \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Persistence/Specifications/NotSpecification.cs b/src/core/Elsa.Abstractions/Persistence/Specifications/NotSpecification.cs index 332676af3..de0d78b23 100644 --- a/src/core/Elsa.Abstractions/Persistence/Specifications/NotSpecification.cs +++ b/src/core/Elsa.Abstractions/Persistence/Specifications/NotSpecification.cs @@ -4,7 +4,7 @@ using System.Linq.Expressions; namespace Elsa.Persistence.Specifications { - internal struct NotSpecification : ISpecification + public struct NotSpecification : ISpecification { private readonly ISpecification _specification; diff --git a/src/core/Elsa.Abstractions/Persistence/Specifications/OrSpecification.cs b/src/core/Elsa.Abstractions/Persistence/Specifications/OrSpecification.cs index 0fdc94436..28fe0993c 100644 --- a/src/core/Elsa.Abstractions/Persistence/Specifications/OrSpecification.cs +++ b/src/core/Elsa.Abstractions/Persistence/Specifications/OrSpecification.cs @@ -4,7 +4,7 @@ using LinqKit; namespace Elsa.Persistence.Specifications { - internal struct OrSpecification : ISpecification + public struct OrSpecification : ISpecification { private readonly ISpecification _left; private readonly ISpecification _right; diff --git a/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlWorkflowDefinitionStore.cs b/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlWorkflowDefinitionStore.cs index 68ca64e04..47850674e 100644 --- a/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlWorkflowDefinitionStore.cs +++ b/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlWorkflowDefinitionStore.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using AutoMapper; @@ -40,6 +41,7 @@ namespace Elsa.Persistence.YesSql.Stores : Query(session, x => x.DefinitionId.IsIn(s.Ids)).WithVersion(s.VersionOptions), WorkflowDefinitionVersionIdSpecification s => Query(session, x => x.DefinitionVersionId == s.VersionId), + AndSpecification s => MapAndSpecification(session, s), VersionOptionsSpecification s => Query(session).WithVersion(s.VersionOptions), _ => AutoMapSpecification(session, specification) }; @@ -51,5 +53,32 @@ namespace Elsa.Persistence.YesSql.Stores var indexedQuery = query.With(); return orderBy.SortDirection == SortDirection.Ascending ? indexedQuery.OrderBy(expression) : indexedQuery.OrderByDescending(expression); } + + /// TODO: This is a workaround. The real fix might be to remove the specification pattern and replace with repository abstractions with finite methods, or automatically dig into And and Or specifications and map each branch into a YesSQL queryable predicate. + private IQuery MapAndSpecification(ISession session, AndSpecification and) + { + var left = and.Left; + var right = and.Right; + + if(left is ManyWorkflowDefinitionIdsSpecification manyWorkflowDefinitionIdsSpecification && right is TenantSpecification tenantSpecification) + { + return CreateQuery(session, manyWorkflowDefinitionIdsSpecification.Ids, manyWorkflowDefinitionIdsSpecification.VersionOptions, tenantSpecification.TenantId); + } + + return AutoMapSpecification(session, and); + } + + private IQuery CreateQuery(ISession session, IEnumerable definitionIds, VersionOptions? versionOptions = default, string? tenantId = default) + { + var query = Query(session).Where(x => x.DefinitionId.IsIn(definitionIds)); + + if (versionOptions != null) + query.WithVersion(versionOptions); + + if (!string.IsNullOrWhiteSpace(tenantId)) + query.Where(x => x.TenantId == tenantId); + + return query; + } } } \ No newline at end of file