diff --git a/Orm/Xtensive.Orm/Orm/Providers/DomainHandler.cs b/Orm/Xtensive.Orm/Orm/Providers/DomainHandler.cs index 8ad99b7e8..709fb62ce 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/DomainHandler.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/DomainHandler.cs @@ -22,8 +22,6 @@ namespace Xtensive.Orm.Providers /// public abstract class DomainHandler : DomainBoundHandler { - private static readonly OrderingCorrector OrderingCorrector = new OrderingCorrector(ResolveOrderingDescriptor); - private Dictionary memberCompilerProviders; /// @@ -93,16 +91,20 @@ protected virtual IPreCompiler CreatePreCompiler(CompilerConfiguration configura { var providerInfo = Handlers.ProviderInfo; - var applyCorrector = new ApplyProviderCorrector( - !providerInfo.Supports(ProviderFeatures.Apply)); - var skipTakeCorrector = new SkipTakeCorrector( - providerInfo.Supports(ProviderFeatures.NativeTake), - providerInfo.Supports(ProviderFeatures.NativeSkip)); + var applyCorrector = providerInfo.Supports(ProviderFeatures.Apply) + ? ApplyProviderCorrector.SilentCorrector + : ApplyProviderCorrector.ExceptionThrowingCorrector; + + var skipTakeCorrector = (providerInfo.Supports(ProviderFeatures.NativeTake | ProviderFeatures.NativeSkip)) + ? SkipTakeCorrector.FullPaginationSupportCorrector + : new SkipTakeCorrector(providerInfo.Supports(ProviderFeatures.NativeTake), + providerInfo.Supports(ProviderFeatures.NativeSkip)); + return new CompositePreCompiler( applyCorrector, skipTakeCorrector, RedundantColumnOptimizer.Instance, - OrderingCorrector); + OrderingCorrector.DefaultInstance); } /// @@ -194,29 +196,6 @@ private void BuildQueryPreprocessors() QueryPreprocessors = ordered ?? throw new InvalidOperationException(Strings.ExCyclicDependencyInQueryPreprocessorGraphIsDetected); } - private static ProviderOrderingDescriptor ResolveOrderingDescriptor(CompilableProvider provider) - { - var isOrderSensitive = provider.Type is ProviderType.Skip - or ProviderType.Take - or ProviderType.Seek - or ProviderType.Paging - or ProviderType.RowNumber; - var preservesOrder = provider.Type is ProviderType.Skip - or ProviderType.Take - or ProviderType.Seek - or ProviderType.Paging - or ProviderType.RowNumber - or ProviderType.Distinct - or ProviderType.Alias; - var isOrderBreaker = provider.Type is ProviderType.Except - or ProviderType.Intersect - or ProviderType.Union - or ProviderType.Concat - or ProviderType.Existence; - var isSorter = provider.Type is ProviderType.Sort or ProviderType.Index; - return new ProviderOrderingDescriptor(isOrderSensitive, preservesOrder, isOrderBreaker, isSorter); - } - #endregion diff --git a/Orm/Xtensive.Orm/Orm/Rse/Transformation/ApplyProviderCorrector.cs b/Orm/Xtensive.Orm/Orm/Rse/Transformation/ApplyProviderCorrector.cs index d7061d222..4aef68858 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/Transformation/ApplyProviderCorrector.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/Transformation/ApplyProviderCorrector.cs @@ -15,6 +15,10 @@ namespace Xtensive.Orm.Rse.Transformation /// public sealed class ApplyProviderCorrector : IPreCompiler { + public static ApplyProviderCorrector ExceptionThrowingCorrector { get; } = new ApplyProviderCorrector(true); + public static ApplyProviderCorrector SilentCorrector { get; } = new ApplyProviderCorrector(false); + + private readonly bool throwOnCorrectionFault; /// diff --git a/Orm/Xtensive.Orm/Orm/Rse/Transformation/OrderingCorrector.cs b/Orm/Xtensive.Orm/Orm/Rse/Transformation/OrderingCorrector.cs index 5a3a10c7c..30eb41bd0 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/Transformation/OrderingCorrector.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/Transformation/OrderingCorrector.cs @@ -18,6 +18,9 @@ namespace Xtensive.Orm.Rse.Transformation [Serializable] public sealed class OrderingCorrector : IPreCompiler { + public static OrderingCorrector DefaultInstance { get; } = new OrderingCorrector(); + + private readonly Func orderingDescriptorResolver; /// @@ -26,6 +29,29 @@ CompilableProvider IPreCompiler.Process(CompilableProvider rootProvider) return OrderingRewriter.Rewrite(rootProvider, orderingDescriptorResolver); } + private static ProviderOrderingDescriptor ResolveOrderingDescriptor(CompilableProvider provider) + { + var isOrderSensitive = provider.Type is ProviderType.Skip + or ProviderType.Take + or ProviderType.Seek + or ProviderType.Paging + or ProviderType.RowNumber; + var preservesOrder = provider.Type is ProviderType.Skip + or ProviderType.Take + or ProviderType.Seek + or ProviderType.Paging + or ProviderType.RowNumber + or ProviderType.Distinct + or ProviderType.Alias; + var isOrderBreaker = provider.Type is ProviderType.Except + or ProviderType.Intersect + or ProviderType.Union + or ProviderType.Concat + or ProviderType.Existence; + var isSorter = provider.Type is ProviderType.Sort or ProviderType.Index; + return new ProviderOrderingDescriptor(isOrderSensitive, preservesOrder, isOrderBreaker, isSorter); + } + // Constructors @@ -38,5 +64,10 @@ public OrderingCorrector(Func or { this.orderingDescriptorResolver = orderingDescriptorResolver ?? throw new ArgumentNullException(nameof(orderingDescriptorResolver)); } + + private OrderingCorrector() + { + this.orderingDescriptorResolver = ResolveOrderingDescriptor; + } } } \ No newline at end of file diff --git a/Orm/Xtensive.Orm/Orm/Rse/Transformation/SkipTakeCorrector.cs b/Orm/Xtensive.Orm/Orm/Rse/Transformation/SkipTakeCorrector.cs index 47ab3e89a..00b11ee52 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/Transformation/SkipTakeCorrector.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/Transformation/SkipTakeCorrector.cs @@ -16,6 +16,8 @@ namespace Xtensive.Orm.Rse.Transformation [Serializable] public sealed class SkipTakeCorrector : IPreCompiler { + public static SkipTakeCorrector FullPaginationSupportCorrector { get; } = new(true, true); + private readonly bool takeSupported; private readonly bool skipSupported;