Skip to content

Commit 63ebab5

Browse files
committed
Caching IPreCompiler wrappers for rewriters
1 parent c23c81e commit 63ebab5

4 files changed

Lines changed: 77 additions & 35 deletions

File tree

Orm/Xtensive.Orm/Orm/Providers/DomainHandler.cs

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ namespace Xtensive.Orm.Providers
2020
/// </summary>
2121
public abstract class DomainHandler : DomainBoundHandler
2222
{
23-
private static readonly OrderingCorrector OrderingCorrector = new OrderingCorrector(ResolveOrderingDescriptor);
24-
2523
private Dictionary<Type, IMemberCompilerProvider> memberCompilerProviders;
2624

2725
/// <summary>
@@ -91,16 +89,13 @@ protected virtual IPreCompiler CreatePreCompiler(CompilerConfiguration configura
9189
{
9290
var providerInfo = Handlers.ProviderInfo;
9391

94-
var applyCorrector = new ApplyProviderCorrector(
95-
!providerInfo.Supports(ProviderFeatures.Apply));
96-
var skipTakeCorrector = new SkipTakeCorrector(
97-
providerInfo.Supports(ProviderFeatures.NativeTake),
98-
providerInfo.Supports(ProviderFeatures.NativeSkip));
9992
return new CompositePreCompiler(
100-
applyCorrector,
101-
skipTakeCorrector,
93+
ApplyProviderCorrector.GetOrCreate(!providerInfo.Supports(ProviderFeatures.Apply)),
94+
SkipTakeCorrector.GetOrCreate(
95+
providerInfo.Supports(ProviderFeatures.NativeTake),
96+
providerInfo.Supports(ProviderFeatures.NativeSkip)),
10297
RedundantColumnOptimizer.Instance,
103-
OrderingCorrector);
98+
OrderingCorrector.DefaultResolverInstance);
10499
}
105100

106101
/// <summary>
@@ -171,29 +166,6 @@ private void BuildQueryPreprocessors()
171166
QueryPreprocessors = ordered ?? throw new InvalidOperationException(Strings.ExCyclicDependencyInQueryPreprocessorGraphIsDetected);
172167
}
173168

174-
private static ProviderOrderingDescriptor ResolveOrderingDescriptor(CompilableProvider provider)
175-
{
176-
var isOrderSensitive = provider.Type is ProviderType.Skip
177-
or ProviderType.Take
178-
or ProviderType.Seek
179-
or ProviderType.Paging
180-
or ProviderType.RowNumber;
181-
var preservesOrder = provider.Type is ProviderType.Skip
182-
or ProviderType.Take
183-
or ProviderType.Seek
184-
or ProviderType.Paging
185-
or ProviderType.RowNumber
186-
or ProviderType.Distinct
187-
or ProviderType.Alias;
188-
var isOrderBreaker = provider.Type is ProviderType.Except
189-
or ProviderType.Intersect
190-
or ProviderType.Union
191-
or ProviderType.Concat
192-
or ProviderType.Existence;
193-
var isSorter = provider.Type is ProviderType.Sort or ProviderType.Index;
194-
return new ProviderOrderingDescriptor(isOrderSensitive, preservesOrder, isOrderBreaker, isSorter);
195-
}
196-
197169
#endregion
198170

199171

Orm/Xtensive.Orm/Orm/Rse/Transformation/ApplyProviderCorrector.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,24 @@ namespace Xtensive.Orm.Rse.Transformation
1515
/// </summary>
1616
public sealed class ApplyProviderCorrector : IPreCompiler
1717
{
18+
private static readonly Lazy<ApplyProviderCorrector> exceptionThrowingCorrector = new(() => new ApplyProviderCorrector(true));
19+
private static readonly Lazy<ApplyProviderCorrector> silentCorrector = new(() => new ApplyProviderCorrector(false));
20+
1821
private readonly bool throwOnCorrectionFault;
1922

23+
/// <summary>
24+
/// Gets existing instance or creates new one and cache it.
25+
/// </summary>
26+
/// <param name="throwOnCorrectionFault">if set to <see langword="true"/>
27+
/// then <see cref="InvalidOperationException"/> will be thrown in case of
28+
/// the correction's fault; otherwise the origin <see cref="CompilableProvider"/>
29+
/// will be returned.</param>
30+
public static ApplyProviderCorrector GetOrCreate(bool throwOnCorrectionFault) =>
31+
(throwOnCorrectionFault)
32+
? exceptionThrowingCorrector.Value
33+
: silentCorrector.Value;
34+
35+
2036
/// <inheritdoc/>
2137
public CompilableProvider Process(CompilableProvider rootProvider)
2238
{
@@ -33,7 +49,7 @@ public CompilableProvider Process(CompilableProvider rootProvider)
3349
/// then <see cref="InvalidOperationException"/> will be thrown in case of
3450
/// the correction's fault; otherwise the origin <see cref="CompilableProvider"/>
3551
/// will be returned.</param>
36-
public ApplyProviderCorrector(bool throwOnCorrectionFault)
52+
private ApplyProviderCorrector(bool throwOnCorrectionFault)
3753
{
3854
this.throwOnCorrectionFault = throwOnCorrectionFault;
3955
}

Orm/Xtensive.Orm/Orm/Rse/Transformation/OrderingCorrector.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ namespace Xtensive.Orm.Rse.Transformation
1818
[Serializable]
1919
public sealed class OrderingCorrector : IPreCompiler
2020
{
21+
public static OrderingCorrector DefaultResolverInstance { get; } = new OrderingCorrector();
22+
2123
private readonly Func<CompilableProvider, ProviderOrderingDescriptor> orderingDescriptorResolver;
2224

2325
/// <inheritdoc/>
@@ -26,6 +28,28 @@ CompilableProvider IPreCompiler.Process(CompilableProvider rootProvider)
2628
return OrderingRewriter.Rewrite(rootProvider, orderingDescriptorResolver);
2729
}
2830

31+
private static ProviderOrderingDescriptor ResolveOrderingDescriptor(CompilableProvider provider)
32+
{
33+
var isOrderSensitive = provider.Type is ProviderType.Skip
34+
or ProviderType.Take
35+
or ProviderType.Seek
36+
or ProviderType.Paging
37+
or ProviderType.RowNumber;
38+
var preservesOrder = provider.Type is ProviderType.Skip
39+
or ProviderType.Take
40+
or ProviderType.Seek
41+
or ProviderType.Paging
42+
or ProviderType.RowNumber
43+
or ProviderType.Distinct
44+
or ProviderType.Alias;
45+
var isOrderBreaker = provider.Type is ProviderType.Except
46+
or ProviderType.Intersect
47+
or ProviderType.Union
48+
or ProviderType.Concat
49+
or ProviderType.Existence;
50+
var isSorter = provider.Type is ProviderType.Sort or ProviderType.Index;
51+
return new ProviderOrderingDescriptor(isOrderSensitive, preservesOrder, isOrderBreaker, isSorter);
52+
}
2953

3054
// Constructors
3155

@@ -39,5 +63,13 @@ public OrderingCorrector(Func<CompilableProvider, ProviderOrderingDescriptor> or
3963
ArgumentValidator.EnsureArgumentNotNull(orderingDescriptorResolver, "orderingDescriptorResolver");
4064
this.orderingDescriptorResolver = orderingDescriptorResolver;
4165
}
66+
67+
/// <summary>
68+
/// Initializes a new instance of this class with default resolver
69+
/// </summary>
70+
public OrderingCorrector()
71+
{
72+
this.orderingDescriptorResolver = ResolveOrderingDescriptor;
73+
}
4274
}
4375
}

Orm/Xtensive.Orm/Orm/Rse/Transformation/SkipTakeCorrector.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,31 @@ namespace Xtensive.Orm.Rse.Transformation
1616
[Serializable]
1717
public sealed class SkipTakeCorrector : IPreCompiler
1818
{
19+
private static readonly Lazy<SkipTakeCorrector> fullPagingSupport = new(() => new SkipTakeCorrector(true, true));
20+
private static readonly Lazy<SkipTakeCorrector> takeOnlySupport = new(() => new SkipTakeCorrector(true, false));
21+
private static readonly Lazy<SkipTakeCorrector> skipOnlySupport = new(() => new SkipTakeCorrector(false, true));
22+
private static readonly Lazy<SkipTakeCorrector> noPagingSupport = new(() => new SkipTakeCorrector(false, false));
23+
1924
private readonly bool takeSupported;
2025
private readonly bool skipSupported;
2126

27+
28+
/// <summary>
29+
/// Gets cached instance of create and cache new one
30+
/// </summary>
31+
/// <param name="takeSupported">Take operation is supported.</param>
32+
/// <param name="skipSupported">Skip operation is supported.</param>
33+
/// <returns>Cached instance of corrector.</returns>
34+
public static SkipTakeCorrector GetOrCreate(bool takeSupported, bool skipSupported)
35+
{
36+
return (takeSupported, skipSupported) switch {
37+
(true, true) => fullPagingSupport.Value,
38+
(false, true) => skipOnlySupport.Value,
39+
(true, false) => takeOnlySupport.Value,
40+
(false, false) => noPagingSupport.Value
41+
};
42+
}
43+
2244
/// <inheritdoc/>
2345
CompilableProvider IPreCompiler.Process(CompilableProvider rootProvider)
2446
{
@@ -28,7 +50,7 @@ CompilableProvider IPreCompiler.Process(CompilableProvider rootProvider)
2850

2951
// Constructors
3052

31-
public SkipTakeCorrector(bool takeSupported, bool skipSupported)
53+
private SkipTakeCorrector(bool takeSupported, bool skipSupported)
3254
{
3355
this.takeSupported = takeSupported;
3456
this.skipSupported = skipSupported;

0 commit comments

Comments
 (0)