From 8f6c3de78f22aefa2bfa97545cc4ec2724105583 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Mon, 18 Jan 2021 14:25:57 +0500 Subject: [PATCH 1/4] Created test for the issue --- ...umnRemoverRemovesPartOfTempTableColumns.cs | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 Orm/Xtensive.Orm.Tests/Issues/IssueJira0801_ReduntandColumnRemoverRemovesPartOfTempTableColumns.cs diff --git a/Orm/Xtensive.Orm.Tests/Issues/IssueJira0801_ReduntandColumnRemoverRemovesPartOfTempTableColumns.cs b/Orm/Xtensive.Orm.Tests/Issues/IssueJira0801_ReduntandColumnRemoverRemovesPartOfTempTableColumns.cs new file mode 100644 index 0000000000..252612b43e --- /dev/null +++ b/Orm/Xtensive.Orm.Tests/Issues/IssueJira0801_ReduntandColumnRemoverRemovesPartOfTempTableColumns.cs @@ -0,0 +1,148 @@ +// Copyright (C) 2020 Xtensive LLC. +// This code is distributed under MIT license terms. +// See the License.txt file in the project root for more information. +// Created by: Alexey Kulakov +// Created: 2020.11.16 + +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using Xtensive.Orm.Configuration; +using Xtensive.Orm.Tests.Issues.IssueJira0801_ReduntandColumnRemoverRemovesPartOfTempTableColumnsModel; + +namespace Xtensive.Orm.Tests.Issues.IssueJira0801_ReduntandColumnRemoverRemovesPartOfTempTableColumnsModel +{ + [HierarchyRoot] + public class EquipmentStateRecord : Entity + { + [Field, Key] + public long Id { get; private set; } + + [Field] + public DateTime StartDate { get; set; } + + [Field] + public DateTime? EndDate { get; set; } + + [Field] + public Equipment Equipment { get; set; } + + [Field] + public MachineStateType Type { get; set; } + } + + [HierarchyRoot] + public class Equipment : Entity + { + [Field, Key] + public long Id { get; private set; } + } + + public enum MachineStateType + { + Undefined = 0, + Production = 1, + EmergencyStop = 2, + Adjustment = 3, + SwitchedOn = 4, + SwitchedOff = 5 + } + + public class Segment + { + public long EquipmentId { get; set; } + + public DateTime StartDate { get; set; } + + public DateTime EndDate { get; set; } + } +} + +namespace Xtensive.Orm.Tests.Issues +{ + public class IssueJira0801_ReduntandColumnRemoverRemovesPartOfTempTableColumns : AutoBuildTest + { + private long equipmentId; + + protected override void CheckRequirements() => + Require.AllFeaturesSupported(Providers.ProviderFeatures.TemporaryTables); + + protected override DomainConfiguration BuildConfiguration() + { + var config = base.BuildConfiguration(); + config.Types.Register(typeof(EquipmentStateRecord).Assembly, typeof(EquipmentStateRecord).Namespace); + return config; + } + + protected override void PopulateData() + { + using (var session = Domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var equipment = new Equipment(); + equipmentId = equipment.Id; + + foreach (var item in Enum.GetValues(typeof(MachineStateType)).Cast()) { + _ = new EquipmentStateRecord() { + Equipment = equipment, + Type = item, + StartDate = DateTime.Now.AddDays(-1), + EndDate = DateTime.Now.AddHours(-1) + }; + + _ = new EquipmentStateRecord() { + Equipment = equipment, + Type = item, + StartDate = DateTime.Now.AddDays(-2), + EndDate = DateTime.Now.AddHours(-2) + }; + + _ = new EquipmentStateRecord() { + Equipment = equipment, + Type = item, + StartDate = DateTime.Now.AddDays(-3), + EndDate = DateTime.Now.AddHours(-3) + }; + } + + tx.Complete(); + } + } + + [Test] + public void MainTest() + { + using (var session = Domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var segments = GetSegments().Select(x => new { x.EquipmentId, x.StartDate, x.EndDate }).ToArray(); + var remoteSegments = session.Query.Store(segments); + + var testQuery = session.Query.All() + .Where(x => x.EndDate.HasValue) + .Join(remoteSegments, + record => record.Equipment.Id, + segment => segment.EquipmentId, + (record, segment) => new { + EquipmentId = record.Equipment.Id, + Type = record.Type, + StateStartDate = record.StartDate, + StateEndDate = record.EndDate.Value, + SegmentStartDate = segment.StartDate, + SegmentEndDate = segment.EndDate, + StartTime = record.StartDate < segment.StartDate ? segment.StartDate : record.StartDate, + EndTime = record.EndDate.Value > segment.EndDate ? segment.EndDate : record.EndDate.Value + }) + .Where(x => x.StateStartDate < x.SegmentEndDate) + .GroupBy(x => new { x.EquipmentId, x.Type }, x => x.EndTime - x.StartTime) + .ToArray(); + } + } + + private IEnumerable GetSegments() + { + yield return new Segment { EquipmentId = equipmentId, StartDate = DateTime.Now.AddDays(-1), EndDate = DateTime.Now }; + yield return new Segment { EquipmentId = equipmentId, StartDate = DateTime.Now.AddDays(-2), EndDate = DateTime.Now }; + yield return new Segment { EquipmentId = equipmentId, StartDate = DateTime.Now.AddDays(-3), EndDate = DateTime.Now }; + } + } +} From 3ff662f5f3e7f3b7a18ff31f18eda2206839e7cf Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Mon, 18 Jan 2021 14:32:35 +0500 Subject: [PATCH 2/4] Prevents StoreProvider columns from optimization when grouping --- .../Transformation/ColumnMappingInspector.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs b/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs index 6d307b261a..3fada3f87c 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs @@ -18,6 +18,8 @@ internal abstract class ColumnMappingInspector : CompilableProviderVisitor private readonly CompilableProviderVisitor outerColumnUsageVisitor; private readonly CompilableProvider rootProvider; + private bool hasGrouping; + public virtual CompilableProvider RemoveRedundantColumns() { mappings.Add(rootProvider, Enumerable.Range(0, rootProvider.Header.Length).ToList()); @@ -224,7 +226,13 @@ protected override Provider VisitAggregate(AggregateProvider provider) .Select(c => c.SourceIndex) .Union(provider.GroupColumnIndexes); mappings[provider.Source] = Merge(mappings[provider], map); + + if (provider.GroupColumnIndexes.Length > 0) { + hasGrouping = true; + } + var source = VisitCompilable(provider.Source); + hasGrouping = false; var sourceMap = mappings[provider.Source]; var currentMap = mappings[provider]; @@ -292,6 +300,28 @@ protected override Provider VisitRowNumber(RowNumberProvider provider) return new RowNumberProvider(newSource, rowNumberColumn.Name); } + protected override Provider VisitStore(StoreProvider provider) + { + var compilableSource = provider.Source as CompilableProvider; + if (compilableSource == null) + return provider; + + if (hasGrouping) { + mappings.Add(provider.Sources[0], + Merge(mappings[provider], provider.Header.Columns.Select((c, i) => i))); + } + else { + OnRecursionEntrance(provider); + } + + var source = VisitCompilable(compilableSource); + + _ = OnRecursionExit(provider); + if (source == compilableSource) + return provider; + return new StoreProvider(source, provider.Name); + } + protected override Provider VisitConcat(ConcatProvider provider) { return VisitSetOperationProvider(provider); From 2c95fe3dec780ca9134179eaec7ead987a35227a Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Mon, 18 Jan 2021 17:29:22 +0500 Subject: [PATCH 3/4] ColumnMappingInspector: Formatting + ToList/ToArray improvements --- .../Transformation/ColumnMappingInspector.cs | 300 +++++++++--------- 1 file changed, 153 insertions(+), 147 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs b/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs index 3fada3f87c..3446f2bc74 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs @@ -1,3 +1,7 @@ +// Copyright (C) 2010-2020 Xtensive LLC. +// This code is distributed under MIT license terms. +// See the License.txt file in the project root for more information. + using System; using System.Collections.Generic; using System.Linq; @@ -22,9 +26,9 @@ internal abstract class ColumnMappingInspector : CompilableProviderVisitor public virtual CompilableProvider RemoveRedundantColumns() { - mappings.Add(rootProvider, Enumerable.Range(0, rootProvider.Header.Length).ToList()); + mappings.Add(rootProvider, CollectionUtils.RangeToList(0, rootProvider.Header.Length)); var visitedProvider = VisitCompilable(rootProvider); - return visitedProvider!=rootProvider + return visitedProvider != rootProvider ? visitedProvider : rootProvider; } @@ -33,13 +37,16 @@ public virtual CompilableProvider RemoveRedundantColumns() protected override Provider VisitInclude(IncludeProvider provider) { - int sourceLength = provider.Source.Header.Length; + var sourceLength = provider.Source.Header.Length; mappings[provider.Source] = Merge(mappings[provider].Where(i => i < sourceLength), provider.FilteredColumns); var source = VisitCompilable(provider.Source); mappings[provider] = Merge(mappings[provider], mappings[provider.Source]); - if (source==provider.Source) + if (source == provider.Source) { return provider; - var filteredColumns = provider.FilteredColumns.Select(el => mappings[provider].IndexOf(el)).ToArray(); + } + var filteredColumns = provider.FilteredColumns + .Select(el => mappings[provider].IndexOf(el)) + .ToArray(provider.FilteredColumns.Count); return new IncludeProvider(source, provider.Algorithm, provider.IsInlined, provider.FilterDataSource, provider.ResultColumnName, filteredColumns); } @@ -47,43 +54,55 @@ protected override Provider VisitInclude(IncludeProvider provider) protected override Provider VisitSelect(SelectProvider provider) { var requiredColumns = mappings[provider]; - var remappedColumns = requiredColumns.Select(c => provider.ColumnIndexes[c]).ToList(); + var remappedColumns = requiredColumns + .Select(c => provider.ColumnIndexes[c]) + .ToList(requiredColumns.Count); + mappings[provider.Source] = remappedColumns; var source = VisitCompilable(provider.Source); var sourceMap = mappings[provider.Source]; - var columns = provider.ColumnIndexes - .Select((i, j) => new Pair(sourceMap.IndexOf(i), j)) - .Where(i => i.First >= 0) - .ToList(); - mappings[provider] = columns.Select(c => c.Second).ToList(); - var indexColumns = columns.Select(c => c.First).ToList(); - if (source==provider.Source) - return provider; - return new SelectProvider(source, indexColumns.ToArray()); + + var indexColumns = new List(); + var newMappings = new List(); + + var currentItemIndex = 0; + foreach(var item in provider.ColumnIndexes) { + var indexInMap = sourceMap.IndexOf(item); + if (indexInMap >= 0) { + indexColumns.Add(indexInMap); + newMappings.Add(currentItemIndex); + } + currentItemIndex++; + } + + mappings[provider] = newMappings; + return source == provider.Source + ? provider + : new SelectProvider(source, indexColumns.ToArray()); } /// protected override Provider VisitFreeText(FreeTextProvider provider) { - mappings[provider] = Enumerable.Range(0, provider.Header.Length).ToList(); + mappings[provider] = CollectionUtils.RangeToList(0, provider.Header.Length); return provider; } protected override Provider VisitContainsTable(ContainsTableProvider provider) { - mappings[provider] = Enumerable.Range(0, provider.Header.Length).ToList(); + mappings[provider] = CollectionUtils.RangeToList(0, provider.Header.Length); return provider; } protected override Provider VisitIndex(IndexProvider provider) { - mappings[provider] = Enumerable.Range(0, provider.Header.Length).ToList(); + mappings[provider] = CollectionUtils.RangeToList(0, provider.Header.Length); return provider; } protected override Provider VisitSeek(SeekProvider provider) { - mappings[provider] = Enumerable.Range(0, provider.Header.Length).ToList(); + mappings[provider] = CollectionUtils.RangeToList(0, provider.Header.Length); return provider; } @@ -94,19 +113,16 @@ protected override Provider VisitFilter(FilterProvider provider) mappings[provider] = mappings[provider.Source]; var predicate = TranslateLambda(provider, provider.Predicate); - if (newSourceProvider==provider.Source && predicate==provider.Predicate) - return provider; - return new FilterProvider(newSourceProvider, (Expression>) predicate); + return newSourceProvider == provider.Source && predicate == provider.Predicate + ? provider + : new FilterProvider(newSourceProvider, (Expression>) predicate); } protected override Provider VisitJoin(JoinProvider provider) { // split - List leftMapping; - List rightMapping; - - SplitMappings(provider, out leftMapping, out rightMapping); + SplitMappings(provider, out var leftMapping, out var rightMapping); leftMapping = Merge(leftMapping, provider.EqualIndexes.Select(p => p.First)); rightMapping = Merge(rightMapping, provider.EqualIndexes.Select(p => p.Second)); @@ -117,10 +133,11 @@ protected override Provider VisitJoin(JoinProvider provider) mappings[provider] = MergeMappings(provider.Left, leftMapping, rightMapping); - if (newLeftProvider==provider.Left && newRightProvider==provider.Right) + if (newLeftProvider == provider.Left && newRightProvider == provider.Right) { return provider; + } - var newIndexes = new List>(); + var newIndexes = new List>(provider.EqualIndexes.Length); foreach (var pair in provider.EqualIndexes) { var newLeftIndex = leftMapping.IndexOf(pair.First); var newRightIndex = rightMapping.IndexOf(pair.Second); @@ -131,10 +148,7 @@ protected override Provider VisitJoin(JoinProvider provider) protected override Provider VisitPredicateJoin(PredicateJoinProvider provider) { - List leftMapping; - List rightMapping; - - SplitMappings(provider, out leftMapping, out rightMapping); + SplitMappings(provider, out var leftMapping, out var rightMapping); leftMapping.AddRange(mappingsGatherer.Gather(provider.Predicate, provider.Predicate.Parameters[0])); @@ -146,10 +160,11 @@ protected override Provider VisitPredicateJoin(PredicateJoinProvider provider) VisitJoin(ref leftMapping, ref newLeftProvider, ref rightMapping, ref newRightProvider); mappings[provider] = MergeMappings(provider.Left, leftMapping, rightMapping); var predicate = TranslateJoinPredicate(leftMapping, rightMapping, provider.Predicate); - if (newLeftProvider==provider.Left && newRightProvider==provider.Right - && provider.Predicate==predicate) - return provider; - return new PredicateJoinProvider(newLeftProvider, newRightProvider, (Expression>) predicate, provider.JoinType); + + return newLeftProvider == provider.Left && newRightProvider == provider.Right + && provider.Predicate == predicate + ? provider + : new PredicateJoinProvider(newLeftProvider, newRightProvider, (Expression>) predicate, provider.JoinType); } protected override Provider VisitSort(SortProvider provider) @@ -161,52 +176,50 @@ protected override Provider VisitSort(SortProvider provider) var order = new DirectionCollection(); foreach (var pair in provider.Order) { var index = sourceMap.IndexOf(pair.Key); - if (index < 0) + if (index < 0) { throw Exceptions.InternalError(Strings.ExOrderKeyNotFoundInMapping, OrmLog.Instance); + } order.Add(index, pair.Value); } mappings[provider] = sourceMap; - if (source==provider.Source) - return provider; - return new SortProvider(source, order); + return source == provider.Source ? provider : new SortProvider(source, order); } protected override Provider VisitApply(ApplyProvider provider) { // split - List leftMapping; - List rightMapping; - - SplitMappings(provider, out leftMapping, out rightMapping); + SplitMappings(provider, out var leftMapping, out var rightMapping); - ApplyParameter applyParameter = provider.ApplyParameter; + var applyParameter = provider.ApplyParameter; var currentOuterUsages = new List(); outerColumnUsages.Add(applyParameter, currentOuterUsages); - outerColumnUsageVisitor.VisitCompilable(provider.Right); - outerColumnUsages.Remove(applyParameter); + _ = outerColumnUsageVisitor.VisitCompilable(provider.Right); + _ = outerColumnUsages.Remove(applyParameter); leftMapping = Merge(leftMapping, currentOuterUsages); - if (leftMapping.Count==0) + if (leftMapping.Count == 0) { leftMapping.Add(0); + } // visit var oldMappings = ReplaceMappings(provider.Left, leftMapping); - CompilableProvider newLeftProvider = VisitCompilable(provider.Left); + var newLeftProvider = VisitCompilable(provider.Left); leftMapping = mappings[provider.Left]; - ReplaceMappings(provider.Right, rightMapping); + _ = ReplaceMappings(provider.Right, rightMapping); outerColumnUsages.Add(applyParameter, leftMapping); - CompilableProvider newRightProvider = VisitCompilable(provider.Right); - outerColumnUsages.Remove(applyParameter); + var newRightProvider = VisitCompilable(provider.Right); + _ = outerColumnUsages.Remove(applyParameter); var pair = OverrideRightApplySource(provider, newRightProvider, rightMapping); - if (pair.First==null) + if (pair.First == null) { rightMapping = mappings[provider.Right]; + } else { newRightProvider = pair.First; rightMapping = pair.Second; @@ -215,9 +228,9 @@ protected override Provider VisitApply(ApplyProvider provider) mappings[provider] = Merge(leftMapping, rightMapping.Select(map => map + provider.Left.Header.Length)); - if (newLeftProvider==provider.Left && newRightProvider==provider.Right) - return provider; - return new ApplyProvider(applyParameter, newLeftProvider, newRightProvider, provider.IsInlined, provider.SequenceType, provider.ApplyType); + return newLeftProvider == provider.Left && newRightProvider == provider.Right + ? provider + : new ApplyProvider(applyParameter, newLeftProvider, newRightProvider, provider.IsInlined, provider.SequenceType, provider.ApplyType); } protected override Provider VisitAggregate(AggregateProvider provider) @@ -237,74 +250,83 @@ protected override Provider VisitAggregate(AggregateProvider provider) var sourceMap = mappings[provider.Source]; var currentMap = mappings[provider]; - var columns = new List(); - for (int i = 0; i < provider.AggregateColumns.Length; i++) { - int columnIndex = i + provider.GroupColumnIndexes.Length; + mappings[provider] = provider.Header.Columns.Select(c => c.Index).ToList(provider.Header.Columns.Count); + + if (source == provider.Source) { + return provider; + } + + var columns = new List(provider.AggregateColumns.Length); + for (var i = 0; i < provider.AggregateColumns.Length; i++) { + var columnIndex = i + provider.GroupColumnIndexes.Length; if (currentMap.BinarySearch(columnIndex) >= 0) { var column = provider.AggregateColumns[i]; columns.Add(new AggregateColumnDescriptor(column.Name, sourceMap.IndexOf(column.SourceIndex), column.AggregateType)); } } - mappings[provider] = provider.Header.Columns.Select(c => c.Index).ToList(); - var groupColumnIndexes = provider.GroupColumnIndexes.Select(index => sourceMap.IndexOf(index)); - if (source==provider.Source) - return provider; - return new AggregateProvider(source, groupColumnIndexes.ToArray(), columns.ToArray()); + var groupColumnIndexes = provider.GroupColumnIndexes + .Select(index => sourceMap.IndexOf(index)) + .ToArray(provider.GroupColumnIndexes.Length); + + return new AggregateProvider(source, groupColumnIndexes, columns.ToArray()); } protected override Provider VisitCalculate(CalculateProvider provider) { - int sourceLength = provider.Source.Header.Length; + var sourceLength = provider.Source.Header.Length; var usedColumns = mappings[provider]; var sourceMapping = Merge( mappings[provider].Where(i => i < sourceLength), - provider.CalculatedColumns.SelectMany(c => mappingsGatherer.Gather(c.Expression)) - ); + provider.CalculatedColumns.SelectMany(c => mappingsGatherer.Gather(c.Expression))); + mappings[provider.Source] = sourceMapping; var newSourceProvider = VisitCompilable(provider.Source); mappings[provider] = mappings[provider.Source]; - bool translated = false; - var descriptors = new List(provider.CalculatedColumns.Length); + var translated = false; + var descriptors = new List(usedColumns.Count); var currentMapping = mappings[provider]; - for (int calculatedColumnIndex = 0; calculatedColumnIndex < provider.CalculatedColumns.Length; calculatedColumnIndex++) { + for (var calculatedColumnIndex = 0; calculatedColumnIndex < provider.CalculatedColumns.Length; calculatedColumnIndex++) { if (usedColumns.Contains(provider.CalculatedColumns[calculatedColumnIndex].Index)) { currentMapping.Add(provider.Source.Header.Length + calculatedColumnIndex); var column = provider.CalculatedColumns[calculatedColumnIndex]; var expression = TranslateLambda(provider, column.Expression); - if (expression!=column.Expression) + if (expression != column.Expression) { translated = true; + } var ccd = new CalculatedColumnDescriptor(column.Name, column.Type, (Expression>) expression); descriptors.Add(ccd); } } mappings[provider] = currentMapping; - if (descriptors.Count==0) + if (descriptors.Count == 0) { return newSourceProvider; - if (!translated && newSourceProvider==provider.Source && descriptors.Count==provider.CalculatedColumns.Length) - return provider; - return new CalculateProvider(newSourceProvider, descriptors.ToArray()); + } + + return !translated && newSourceProvider == provider.Source && descriptors.Count == provider.CalculatedColumns.Length + ? provider + : new CalculateProvider(newSourceProvider, descriptors.ToArray()); } protected override Provider VisitRowNumber(RowNumberProvider provider) { - int sourceLength = provider.Source.Header.Length; + var sourceLength = provider.Source.Header.Length; mappings[provider.Source] = mappings[provider].Where(i => i < sourceLength).ToList(); var newSource = VisitCompilable(provider.Source); var currentMapping = mappings[provider.Source]; var rowNumberColumn = provider.Header.Columns.Last(); mappings[provider] = Merge(currentMapping, EnumerableUtils.One(rowNumberColumn.Index)); - if (newSource==provider.Source) - return provider; - return new RowNumberProvider(newSource, rowNumberColumn.Name); + return newSource == provider.Source + ? provider + : new RowNumberProvider(newSource, rowNumberColumn.Name); } protected override Provider VisitStore(StoreProvider provider) { - var compilableSource = provider.Source as CompilableProvider; - if (compilableSource == null) + if (!(provider.Source is CompilableProvider compilableSource)) { return provider; + } if (hasGrouping) { mappings.Add(provider.Sources[0], @@ -317,30 +339,18 @@ protected override Provider VisitStore(StoreProvider provider) var source = VisitCompilable(compilableSource); _ = OnRecursionExit(provider); - if (source == compilableSource) - return provider; - return new StoreProvider(source, provider.Name); + return source == compilableSource + ? provider + : new StoreProvider(source, provider.Name); } - protected override Provider VisitConcat(ConcatProvider provider) - { - return VisitSetOperationProvider(provider); - } + protected override Provider VisitConcat(ConcatProvider provider) => VisitSetOperationProvider(provider); - protected override Provider VisitExcept(ExceptProvider provider) - { - return VisitSetOperationProvider(provider); - } + protected override Provider VisitExcept(ExceptProvider provider) => VisitSetOperationProvider(provider); - protected override Provider VisitIntersect(IntersectProvider provider) - { - return VisitSetOperationProvider(provider); - } + protected override Provider VisitIntersect(IntersectProvider provider) => VisitSetOperationProvider(provider); - protected override Provider VisitUnion(UnionProvider provider) - { - return VisitSetOperationProvider(provider); - } + protected override Provider VisitUnion(UnionProvider provider) => VisitSetOperationProvider(provider); private Provider VisitSetOperationProvider(BinaryProvider provider) { @@ -351,47 +361,48 @@ private Provider VisitSetOperationProvider(BinaryProvider provider) var newLeftProvider = VisitCompilable(provider.Left); leftMapping = mappings[provider.Left]; - ReplaceMappings(provider.Right, rightMapping); + _ = ReplaceMappings(provider.Right, rightMapping); var newRightProvider = VisitCompilable(provider.Right); rightMapping = mappings[provider.Right]; RestoreMappings(oldMappings); var expectedColumns = mappings[provider]; mappings[provider] = Merge(leftMapping, rightMapping); - if (newLeftProvider==provider.Left && newRightProvider==provider.Right) + if (newLeftProvider == provider.Left && newRightProvider == provider.Right) { return provider; - + } newLeftProvider = BuildSetOperationSource(newLeftProvider, expectedColumns, leftMapping); newRightProvider = BuildSetOperationSource(newRightProvider, expectedColumns, rightMapping); switch (provider.Type) { - case ProviderType.Concat: - return new ConcatProvider(newLeftProvider, newRightProvider); - case ProviderType.Intersect: - return new IntersectProvider(newLeftProvider, newRightProvider); - case ProviderType.Except: - return new ExceptProvider(newLeftProvider, newRightProvider); - case ProviderType.Union: - return new UnionProvider(newLeftProvider, newRightProvider); - default: - throw new ArgumentOutOfRangeException(); + case ProviderType.Concat: + return new ConcatProvider(newLeftProvider, newRightProvider); + case ProviderType.Intersect: + return new IntersectProvider(newLeftProvider, newRightProvider); + case ProviderType.Except: + return new ExceptProvider(newLeftProvider, newRightProvider); + case ProviderType.Union: + return new UnionProvider(newLeftProvider, newRightProvider); + default: + throw new ArgumentOutOfRangeException(); } } - private static CompilableProvider BuildSetOperationSource(CompilableProvider provider, IEnumerable expectedColumns, IList returningColumns) + private static CompilableProvider BuildSetOperationSource(CompilableProvider provider, ICollection expectedColumns, IList returningColumns) { - if (provider.Type==ProviderType.Select) + if (provider.Type == ProviderType.Select) { return provider; + } + var columns = expectedColumns - .Select(originalIndex => new {OriginalIndex = originalIndex, NewIndex = returningColumns.IndexOf(originalIndex)}) - .Select(x => x.NewIndex < 0 ? x.OriginalIndex : x.NewIndex).ToArray(); + .Select(originalIndex => new { OriginalIndex = originalIndex, NewIndex = returningColumns.IndexOf(originalIndex) }) + .Select(x => x.NewIndex < 0 ? x.OriginalIndex : x.NewIndex).ToArray(expectedColumns.Count); return new SelectProvider(provider, columns); } - protected virtual Pair> OverrideRightApplySource(ApplyProvider applyProvider, CompilableProvider provider, List requestedMapping) - { - return new Pair>(provider, requestedMapping); - } + protected virtual Pair> OverrideRightApplySource(ApplyProvider applyProvider, + CompilableProvider provider, List requestedMapping) => + new Pair>(provider, requestedMapping); #endregion @@ -423,42 +434,40 @@ private static List Merge(IEnumerable left, IEnumerable right) private static List MergeMappings(Provider originalLeft, List leftMap, List rightMap) { - int leftCount = originalLeft.Header.Length; - List result = leftMap + var leftCount = originalLeft.Header.Length; + var result = leftMap .Concat(rightMap.Select(i => i + leftCount)) - .ToList(); + .ToList(leftMap.Count + rightMap.Count); return result; } private void SplitMappings(BinaryProvider provider, out List leftMapping, out List rightMapping) { - List binaryMapping = mappings[provider]; - leftMapping = new List(); - rightMapping = new List(); - int leftCount = provider.Left.Header.Length; - int index = 0; + var binaryMapping = mappings[provider]; + leftMapping = new List(binaryMapping.Count); + var leftCount = provider.Left.Header.Length; + var index = 0; while (index < binaryMapping.Count && binaryMapping[index] < leftCount) { leftMapping.Add(binaryMapping[index]); index++; } - for (int i = index; i < binaryMapping.Count; i++) + rightMapping = new List(binaryMapping.Count - index); + for (var i = index; i < binaryMapping.Count; i++) { rightMapping.Add(binaryMapping[i] - leftCount); + } } private void RegisterOuterMapping(ApplyParameter parameter, int value) { - List map; - if (outerColumnUsages.TryGetValue(parameter, out map)) - if (!map.Contains(value)) - map.Add(value); + if (outerColumnUsages.TryGetValue(parameter, out var map) && !map.Contains(value)) { + map.Add(value); + } } private int ResolveOuterMapping(ApplyParameter parameter, int value) { - int result = outerColumnUsages[parameter].IndexOf(value); - if (result < 0) - return value; - return result; + var result = outerColumnUsages[parameter].IndexOf(value); + return result < 0 ? value : result; } private Expression TranslateLambda(Provider originalProvider, LambdaExpression expression) @@ -485,11 +494,11 @@ private void VisitJoin(ref List leftMapping, ref CompilableProvider left, r // visit var oldMapping = ReplaceMappings(left, leftMapping); - CompilableProvider newLeftProvider = VisitCompilable(left); + var newLeftProvider = VisitCompilable(left); leftMapping = mappings[left]; - ReplaceMappings(right, rightMapping); - CompilableProvider newRightProvider = VisitCompilable(right); + _ = ReplaceMappings(right, rightMapping); + var newRightProvider = VisitCompilable(right); rightMapping = mappings[right]; RestoreMappings(oldMapping); left = newLeftProvider; @@ -503,10 +512,7 @@ private Dictionary> ReplaceMappings(Provider firstNewKey, Li return oldMappings; } - private void RestoreMappings(Dictionary> savedMappings) - { - mappings = savedMappings; - } + private void RestoreMappings(Dictionary> savedMappings) => mappings = savedMappings; #endregion @@ -521,8 +527,8 @@ protected ColumnMappingInspector(CompilableProvider originalProvider) mappingsGatherer = new TupleAccessGatherer((a, b) => { }); var outerMappingsGatherer = new TupleAccessGatherer(RegisterOuterMapping); - outerColumnUsageVisitor = new CompilableProviderVisitor((_, e) => { - outerMappingsGatherer.Gather(e); + outerColumnUsageVisitor = new CompilableProviderVisitor((p, e) => { + _ = outerMappingsGatherer.Gather(e); return e; }); } From d0fea39592f05fcfef0c5d6280b69a73d74629b4 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 29 Jan 2021 15:29:45 +0500 Subject: [PATCH 4/4] One more list capacity improvement --- .../Orm/Rse/Transformation/ColumnMappingInspector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs b/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs index 3446f2bc74..36bf64c3c9 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs @@ -62,8 +62,8 @@ protected override Provider VisitSelect(SelectProvider provider) var source = VisitCompilable(provider.Source); var sourceMap = mappings[provider.Source]; - var indexColumns = new List(); - var newMappings = new List(); + var indexColumns = new List(provider.ColumnIndexes.Count); + var newMappings = new List(provider.ColumnIndexes.Count); var currentItemIndex = 0; foreach(var item in provider.ColumnIndexes) {