From 32b9918c4ac0960a49765e72069915c15c3572c9 Mon Sep 17 00:00:00 2001 From: AlexUstinov Date: Tue, 7 Apr 2020 22:32:44 -0700 Subject: [PATCH 1/4] Reorganize code in SqlCompiler.Helpers.cs --- .../Orm/Providers/SqlCompiler.Helpers.cs | 286 ++++++++++-------- 1 file changed, 159 insertions(+), 127 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs index acac4f16b3..3fb149ca05 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs @@ -24,8 +24,7 @@ partial class SqlCompiler protected SqlProvider CreateProvider(SqlSelect statement, CompilableProvider origin, params ExecutableProvider[] sources) { - var extraBindings = (IEnumerable) null; - return CreateProvider(statement, extraBindings, origin, sources); + return CreateProvider(statement, (IEnumerable) null, origin, sources); } protected SqlProvider CreateProvider(SqlSelect statement, QueryParameterBinding extraBinding, @@ -41,20 +40,23 @@ protected SqlProvider CreateProvider(SqlSelect statement, IEnumerable(); var parameterBindings = sqlSources.SelectMany(p => p.Request.ParameterBindings); - if (extraBindings!=null) + if (extraBindings!=null) { parameterBindings = parameterBindings.Concat(extraBindings); + } - bool allowBatching = sqlSources + var allowBatching = sqlSources .Aggregate(true, (current, provider) => current && provider.Request.CheckOptions(QueryRequestOptions.AllowOptimization)); var tupleDescriptor = origin.Header.TupleDescriptor; var options = QueryRequestOptions.Empty; - if (allowBatching) + if (allowBatching) { options |= QueryRequestOptions.AllowOptimization; + } - if (statement.Columns.Count < origin.Header.TupleDescriptor.Count) + if (statement.Columns.Count < origin.Header.TupleDescriptor.Count) { tupleDescriptor = origin.Header.TupleDescriptor.Head(statement.Columns.Count); + } var request = CreateQueryRequest(Driver, statement, parameterBindings, tupleDescriptor, options); @@ -121,11 +123,15 @@ protected SqlExpression ExtractColumnExpression(SqlColumn column) } } } - else + else { expression = column; + } + var columnRef = expression as SqlColumnRef; - if (!columnRef.IsNullReference()) + if (!columnRef.IsNullReference()) { expression = columnRef.SqlColumn; + } + return expression; } @@ -139,8 +145,9 @@ protected void AddInlinableColumn(IInlinableProvider provider, Column column, stubColumnMap.Add(columnStub, columnExpression); resultQuery.Columns.Add(columnStub); } - else + else { resultQuery.Columns.Add(columnRef); + } } protected SqlExpression GetBooleanColumnExpression(SqlExpression originalExpression) @@ -150,187 +157,212 @@ protected SqlExpression GetBooleanColumnExpression(SqlExpression originalExpress : booleanExpressionConverter.BooleanToInt(originalExpression); } - protected QueryRequest CreateQueryRequest(StorageDriver driver, SqlSelect statement, IEnumerable parameterBindings, + protected QueryRequest CreateQueryRequest(StorageDriver driver, SqlSelect statement, + IEnumerable parameterBindings, TupleDescriptor tupleDescriptor, QueryRequestOptions options) { - if (Handlers.Domain.Configuration.ShareStorageSchemaOverNodes) + if (Handlers.Domain.Configuration.ShareStorageSchemaOverNodes) { return new QueryRequest(driver, statement, parameterBindings, tupleDescriptor, options, NodeConfiguration); + } + return new QueryRequest(driver, statement, parameterBindings, tupleDescriptor, options); } private static bool IsCalculatedColumn(SqlColumn column) { - if (column is SqlUserColumn) + if (column is SqlUserColumn) { return true; + } var cRef = column as SqlColumnRef; - if (!ReferenceEquals(null, cRef)) - return cRef.SqlColumn is SqlUserColumn; - return false; + return cRef?.SqlColumn is SqlUserColumn; } private static bool IsColumnStub(SqlColumn column) { - if (column is SqlColumnStub) + if (column is SqlColumnStub) { return true; + } + var cRef = column as SqlColumnRef; - if (!ReferenceEquals(null, cRef)) - return cRef.SqlColumn is SqlColumnStub; - return false; + return cRef?.SqlColumn is SqlColumnStub; } private static SqlColumnStub ExtractColumnStub(SqlColumn column) { - var columnStub = column as SqlColumnStub; - if (!ReferenceEquals(null, columnStub)) - return columnStub; - var columnRef = column as SqlColumnRef; - if (!ReferenceEquals(null, columnRef)) - return (SqlColumnStub) columnRef.SqlColumn; - return (SqlColumnStub) column; + switch (column) { + case SqlColumnStub columnStub: + return columnStub; + case SqlColumnRef columnRef: + return (SqlColumnStub) columnRef.SqlColumn; + default: + return (SqlColumnStub) column; + } } private static SqlUserColumn ExtractUserColumn(SqlColumn column) { - var userColumn = column as SqlUserColumn; - if (!ReferenceEquals(null, userColumn)) - return userColumn; - var columnRef = column as SqlColumnRef; - if (!ReferenceEquals(null, columnRef)) - return (SqlUserColumn) columnRef.SqlColumn; - return (SqlUserColumn) column; + switch (column) { + case SqlUserColumn userColumn: + return userColumn; + case SqlColumnRef columnRef: + return (SqlUserColumn) columnRef.SqlColumn; + default: + return (SqlUserColumn) column; + } } private static bool ShouldUseQueryReference(CompilableProvider origin, SqlProvider compiledSource) { var sourceSelect = compiledSource.Request.Statement; - if (sourceSelect.From==null) + if (sourceSelect.From==null) { return false; + } - var calculatedColumnIndexes = sourceSelect.Columns - .Select((c, i) => IsCalculatedColumn(c) ? i : -1) - .Where(i => i >= 0) - .ToList(); + var columnIndex = 0; + var rowNumberIsUsed = false; + var calculatedColumnIndexes = new List(8); + foreach (var column in sourceSelect.Columns) { + if (IsCalculatedColumn(column)) { + calculatedColumnIndexes.Add(columnIndex); + rowNumberIsUsed = rowNumberIsUsed || ExtractUserColumn(column).Expression is SqlRowNumber; + } + columnIndex++; + } var containsCalculatedColumns = calculatedColumnIndexes.Count > 0; - var rowNumberIsUsed = calculatedColumnIndexes.Count > 0 && sourceSelect.Columns - .Select((c, i) => new { c, i }) - .Any(a => calculatedColumnIndexes.Contains(a.i) && ExtractUserColumn(a.c).Expression is SqlRowNumber); - var pagingIsUsed = !sourceSelect.Limit.IsNullReference() || !sourceSelect.Offset.IsNullReference() || rowNumberIsUsed; + var pagingIsUsed = rowNumberIsUsed + || !sourceSelect.Limit.IsNullReference() || !sourceSelect.Offset.IsNullReference(); var groupByIsUsed = sourceSelect.GroupBy.Count > 0; var distinctIsUsed = sourceSelect.Distinct; var filterIsUsed = !sourceSelect.Where.IsNullReference(); - if (origin.Type==ProviderType.Filter) { - var filterProvider = (FilterProvider) origin; - var usedColumnIndexes = new TupleAccessGatherer().Gather(filterProvider.Predicate.Body); - return pagingIsUsed || usedColumnIndexes.Any(calculatedColumnIndexes.Contains); - } - - if (origin.Type==ProviderType.Select) - return distinctIsUsed; - - if (origin.Type==ProviderType.RowNumber) { - var usedColumnIndexes = origin.Header.Order.Select(o => o.Key); - return pagingIsUsed || groupByIsUsed || distinctIsUsed || usedColumnIndexes.Any(calculatedColumnIndexes.Contains); - } - - if (origin.Type==ProviderType.Calculate) { - var calculateProvider = (CalculateProvider) origin; - var columnGatherer = new TupleAccessGatherer(); - var usedColumnIndexes = new List(); - foreach (var column in calculateProvider.CalculatedColumns) - usedColumnIndexes.AddRange( - columnGatherer.Gather(column.Expression.Body, column.Expression.Parameters[0])); - - return usedColumnIndexes.Any(calculatedColumnIndexes.Contains); - } + switch (origin.Type) { + case ProviderType.Filter: { + var filterProvider = (FilterProvider) origin; + var usedColumnIndexes = new TupleAccessGatherer().Gather(filterProvider.Predicate.Body); + return pagingIsUsed || usedColumnIndexes.Any(calculatedColumnIndexes.Contains); + } + case ProviderType.Select: + return distinctIsUsed; + case ProviderType.RowNumber: { + var usedColumnIndexes = origin.Header.Order.Select(o => o.Key); + return pagingIsUsed || groupByIsUsed || distinctIsUsed + || usedColumnIndexes.Any(calculatedColumnIndexes.Contains); + } + case ProviderType.Calculate: { + var calculateProvider = (CalculateProvider) origin; + var columnGatherer = new TupleAccessGatherer(); + var usedColumnIndexes = new List(); + foreach (var column in calculateProvider.CalculatedColumns) { + usedColumnIndexes.AddRange( + columnGatherer.Gather(column.Expression.Body, column.Expression.Parameters[0])); + } - if (origin.Type == ProviderType.Aggregate) { - var aggregateProvider = (AggregateProvider)origin; - var columnGatherer = new TupleAccessGatherer(); - var usedColumnIndexes = (aggregateProvider.AggregateColumns ?? Enumerable.Empty()) - .Select(ac => ac.SourceIndex) - .Concat(aggregateProvider.GroupColumnIndexes) - .ToList(); + return usedColumnIndexes.Any(calculatedColumnIndexes.Contains); + } + case ProviderType.Aggregate: { + var aggregateProvider = (AggregateProvider)origin; + var usedColumnIndexes = (aggregateProvider.AggregateColumns ?? Enumerable.Empty()) + .Select(ac => ac.SourceIndex) + .Concat(aggregateProvider.GroupColumnIndexes); + + return pagingIsUsed || distinctIsUsed || groupByIsUsed + || usedColumnIndexes.Any(calculatedColumnIndexes.Contains); + } + case ProviderType.Take: + case ProviderType.Skip: + case ProviderType.Paging: { + return distinctIsUsed || pagingIsUsed || groupByIsUsed + || (origin.Sources[0] is SortProvider sortProvider && + sortProvider.Header.Order.Select(order => order.Key).Any(calculatedColumnIndexes.Contains)); + } + case ProviderType.Apply: + return containsCalculatedColumns || distinctIsUsed || pagingIsUsed || groupByIsUsed; + case ProviderType.Join: { + var shouldUseQueryReference = distinctIsUsed || pagingIsUsed || groupByIsUsed; + if (shouldUseQueryReference) { + return true; + } - return usedColumnIndexes.Any(calculatedColumnIndexes.Contains) || pagingIsUsed || distinctIsUsed || groupByIsUsed; - } + var joinProvider = (JoinProvider) origin; + var isRight = joinProvider.Right == compiledSource.Origin; + var indexes = joinProvider.EqualIndexes.Select(p => isRight ? p.Second : p.First); + return (joinProvider.JoinType == JoinType.LeftOuter && filterIsUsed && isRight) + || (containsCalculatedColumns && indexes.Any(calculatedColumnIndexes.Contains)); + } + case ProviderType.PredicateJoin: { + var shouldUseQueryReference = distinctIsUsed || pagingIsUsed || groupByIsUsed; + if (shouldUseQueryReference) { + return true; + } - if (origin.Type.In(ProviderType.Take,ProviderType.Skip,ProviderType.Paging)) { - var sortProvider = origin.Sources[0] as SortProvider; - var orderingOverCalculatedColumn = sortProvider!=null && - sortProvider.Header.Order + var joinProvider = (PredicateJoinProvider) origin; + var isRight = joinProvider.Right == compiledSource.Origin; + var indexes = new TupleAccessGatherer() + .Gather(joinProvider.Predicate.Body, joinProvider.Predicate.Parameters[isRight ? 1 : 0]); + return (joinProvider.JoinType == JoinType.LeftOuter && filterIsUsed && isRight) + || (containsCalculatedColumns && indexes.Any(calculatedColumnIndexes.Contains)); + } + case ProviderType.Sort when distinctIsUsed: + return true; + case ProviderType.Sort: { + var orderingOverCalculatedColumn = origin.Header.Order .Select(order => order.Key) .Any(calculatedColumnIndexes.Contains); - return distinctIsUsed || pagingIsUsed || groupByIsUsed || orderingOverCalculatedColumn; - } - - if (origin.Type == ProviderType.Apply) - return containsCalculatedColumns || distinctIsUsed || pagingIsUsed || groupByIsUsed; - - if (origin.Type == ProviderType.Join) { - var shouldUseQueryReference = distinctIsUsed || pagingIsUsed || groupByIsUsed; - if (shouldUseQueryReference) - return true; - var joinProvider = (JoinProvider) origin; - var isRight = joinProvider.Right == compiledSource.Origin; - var indexes = joinProvider.EqualIndexes.Select(p => isRight ? p.Second : p.First); - return (joinProvider.JoinType == JoinType.LeftOuter && filterIsUsed && isRight) - || (containsCalculatedColumns && indexes.Any(calculatedColumnIndexes.Contains)); - } - - if (origin.Type == ProviderType.PredicateJoin) { - var shouldUseQueryReference = distinctIsUsed || pagingIsUsed || groupByIsUsed; - if (shouldUseQueryReference) - return true; - var joinProvider = (PredicateJoinProvider) origin; - var isRight = joinProvider.Right == compiledSource.Origin; - var indexes = new TupleAccessGatherer().Gather(joinProvider.Predicate.Body, joinProvider.Predicate.Parameters[isRight ? 1 : 0]); - return (joinProvider.JoinType == JoinType.LeftOuter && filterIsUsed && isRight) - || (containsCalculatedColumns && indexes.Any(calculatedColumnIndexes.Contains)); - } - - if (origin.Type == ProviderType.Sort) { - if (distinctIsUsed) - return true; - var orderingOverCalculatedColumn = origin.Header.Order - .Select(order => order.Key) - .Any(calculatedColumnIndexes.Contains); - return orderingOverCalculatedColumn; + return orderingOverCalculatedColumn; + } + default: + return containsCalculatedColumns || distinctIsUsed || pagingIsUsed || groupByIsUsed; } - - return containsCalculatedColumns || distinctIsUsed || pagingIsUsed || groupByIsUsed; } private SqlExpression GetOrderByExpression(SqlExpression expression, SortProvider provider, int index) { - if (provider.Header.Columns.Count <= index) + var columns = provider.Header.Columns; + if (columns.Count <= index) { return expression; + } - if (providerInfo.Supports(ProviderFeatures.DateTimeEmulation) && provider.Header.Columns[index].Type == typeof(DateTime)) + var columnType = columns[index].Type; + if (providerInfo.Supports(ProviderFeatures.DateTimeEmulation) && columnType == typeof(DateTime)) { return SqlDml.Cast(expression, SqlType.DateTime); - if (providerInfo.Supports(ProviderFeatures.DateTimeOffsetEmulation) && provider.Header.Columns[index].Type == typeof(DateTimeOffset)) + } + + if (providerInfo.Supports(ProviderFeatures.DateTimeOffsetEmulation) && columnType == typeof(DateTimeOffset)) { return SqlDml.Cast(expression, SqlType.DateTimeOffset); + } + return expression; } - private SqlExpression GetJoinExpression(SqlExpression leftExpression, SqlExpression rightExpression, JoinProvider provider, int index) + private SqlExpression GetJoinExpression(SqlExpression leftExpression, SqlExpression rightExpression, + JoinProvider provider, int index) { if (provider.EqualColumns.Length > index) { - if (providerInfo.Supports(ProviderFeatures.DateTimeEmulation)) - { - if (provider.EqualColumns[index].First.Type==typeof (DateTime)) + Pair columnPair; + if (providerInfo.Supports(ProviderFeatures.DateTimeEmulation)) { + columnPair = provider.EqualColumns[index]; + if (columnPair.First.Type == typeof(DateTime)) { leftExpression = SqlDml.Cast(leftExpression, SqlType.DateTime); - if (provider.EqualColumns[index].Second.Type==typeof (DateTime)) + } + + if (columnPair.Second.Type == typeof(DateTime)) { rightExpression = SqlDml.Cast(rightExpression, SqlType.DateTime); + } } + if (providerInfo.Supports(ProviderFeatures.DateTimeOffsetEmulation)) { - if (provider.EqualColumns[index].First.Type==typeof (DateTimeOffset)) + columnPair = provider.EqualColumns[index]; + if (columnPair.First.Type == typeof(DateTimeOffset)) { leftExpression = SqlDml.Cast(leftExpression, SqlType.DateTimeOffset); - if (provider.EqualColumns[index].Second.Type==typeof (DateTimeOffset)) + } + + if (columnPair.Second.Type == typeof(DateTimeOffset)) { rightExpression = SqlDml.Cast(rightExpression, SqlType.DateTimeOffset); + } } } - return leftExpression==rightExpression; + + return leftExpression == rightExpression; } public SqlExpression GetOuterExpression(ApplyParameter parameter, int columnIndex) From 21847756de654726be20405cb62b662b95ecd3f4 Mon Sep 17 00:00:00 2001 From: AlexUstinov Date: Thu, 6 Aug 2020 13:07:00 -0700 Subject: [PATCH 2/4] Fix formatting and copyright comments + Use new language features --- .../Orm/Providers/SqlCompiler.Helpers.cs | 111 +++++++----------- 1 file changed, 42 insertions(+), 69 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs index 3fb149ca05..0be8f6f062 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs @@ -1,6 +1,6 @@ -// Copyright (C) 2003-2010 Xtensive LLC. -// All rights reserved. -// For conditions of distribution and use, see license. +// Copyright (C) 2009-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: Denis Krjuchkov // Created: 2009.11.13 @@ -8,7 +8,6 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Xtensive.Collections; using Xtensive.Core; using Xtensive.Orm.Rse; using Xtensive.Orm.Rse.Transformation; @@ -22,31 +21,31 @@ namespace Xtensive.Orm.Providers partial class SqlCompiler { protected SqlProvider CreateProvider(SqlSelect statement, - CompilableProvider origin, params ExecutableProvider[] sources) - { - return CreateProvider(statement, (IEnumerable) null, origin, sources); - } + CompilableProvider origin, params ExecutableProvider[] sources) => + CreateProvider(statement, (IEnumerable) null, origin, sources); protected SqlProvider CreateProvider(SqlSelect statement, QueryParameterBinding extraBinding, CompilableProvider origin, params ExecutableProvider[] sources) { - var extraBindings = extraBinding!=null ? EnumerableUtils.One(extraBinding) : null; + var extraBindings = extraBinding!=null ? Enumerable.Repeat(extraBinding, 1) : null; return CreateProvider(statement, extraBindings, origin, sources); } protected SqlProvider CreateProvider(SqlSelect statement, IEnumerable extraBindings, CompilableProvider origin, params ExecutableProvider[] sources) { - var sqlSources = sources.OfType(); + var allowBatching = true; + var parameterBindings = Enumerable.Empty(); + foreach (var provider in sources.OfType()) { + var queryRequest = provider.Request; + allowBatching &= queryRequest.CheckOptions(QueryRequestOptions.AllowOptimization); + parameterBindings = parameterBindings.Concat(queryRequest.ParameterBindings); + } - var parameterBindings = sqlSources.SelectMany(p => p.Request.ParameterBindings); - if (extraBindings!=null) { + if (extraBindings != null) { parameterBindings = parameterBindings.Concat(extraBindings); } - var allowBatching = sqlSources - .Aggregate(true, (current, provider) => - current && provider.Request.CheckOptions(QueryRequestOptions.AllowOptimization)); var tupleDescriptor = origin.Header.TupleDescriptor; var options = QueryRequestOptions.Empty; @@ -63,10 +62,7 @@ protected SqlProvider CreateProvider(SqlSelect statement, IEnumerable name; protected Pair> ProcessExpression(LambdaExpression le, params IReadOnlyList[] sourceColumns) @@ -101,22 +97,13 @@ protected SqlExpression ExtractColumnExpression(SqlColumn column) SqlExpression expression; if (IsColumnStub(column)) { expression = stubColumnMap[ExtractColumnStub(column)]; - var subQuery = expression as SqlSubQuery; - if (!subQuery.IsNullReference()) { - var subSelect = subQuery.Query as SqlSelect; - if (subSelect!=null) { - if (subSelect.Columns.Count==1 && subSelect.From==null) { - var userColumn = subSelect.Columns[0] as SqlUserColumn; - if (!userColumn.IsNullReference()) { - var cast = userColumn.Expression as SqlCast; - if (!cast.IsNullReference() && cast.Type.Type==SqlType.Boolean) { - var sqlCase = cast.Operand as SqlCase; - if (!sqlCase.IsNullReference() && sqlCase.Count==1) { - var pair = sqlCase.First(); - var key = pair.Key as SqlUnary; - if (!key.IsNullReference() && pair.Value is SqlLiteral) - expression = cast; - } + if (expression is SqlSubQuery subQuery && subQuery.Query is SqlSelect subSelect && subSelect.From == null) { + if (subSelect.Columns.Count == 1 && subSelect.Columns[0] is SqlUserColumn userColumn) { + if (userColumn.Expression is SqlCast cast && cast.Type.Type == SqlType.Boolean) { + if (cast.Operand is SqlCase sqlCase && sqlCase.Count == 1) { + var pair = sqlCase.First(); + if (pair.Key is SqlUnary && pair.Value is SqlLiteral) { + expression = cast; } } } @@ -127,8 +114,7 @@ protected SqlExpression ExtractColumnExpression(SqlColumn column) expression = column; } - var columnRef = expression as SqlColumnRef; - if (!columnRef.IsNullReference()) { + if (expression is SqlColumnRef columnRef) { expression = columnRef.SqlColumn; } @@ -150,12 +136,10 @@ protected void AddInlinableColumn(IInlinableProvider provider, Column column, } } - protected SqlExpression GetBooleanColumnExpression(SqlExpression originalExpression) - { - return providerInfo.Supports(ProviderFeatures.FullFeaturedBooleanExpressions) + protected SqlExpression GetBooleanColumnExpression(SqlExpression originalExpression) => + providerInfo.Supports(ProviderFeatures.FullFeaturedBooleanExpressions) ? originalExpression : booleanExpressionConverter.BooleanToInt(originalExpression); - } protected QueryRequest CreateQueryRequest(StorageDriver driver, SqlSelect statement, IEnumerable parameterBindings, @@ -173,8 +157,8 @@ private static bool IsCalculatedColumn(SqlColumn column) if (column is SqlUserColumn) { return true; } - var cRef = column as SqlColumnRef; - return cRef?.SqlColumn is SqlUserColumn; + + return column is SqlColumnRef columnRef && columnRef.SqlColumn is SqlUserColumn; } private static bool IsColumnStub(SqlColumn column) @@ -183,38 +167,25 @@ private static bool IsColumnStub(SqlColumn column) return true; } - var cRef = column as SqlColumnRef; - return cRef?.SqlColumn is SqlColumnStub; + return column is SqlColumnRef columnRef && columnRef.SqlColumn is SqlColumnStub; } - private static SqlColumnStub ExtractColumnStub(SqlColumn column) - { - switch (column) { - case SqlColumnStub columnStub: - return columnStub; - case SqlColumnRef columnRef: - return (SqlColumnStub) columnRef.SqlColumn; - default: - return (SqlColumnStub) column; - } - } + private static SqlColumnStub ExtractColumnStub(SqlColumn column) => + column switch { + SqlColumnRef columnRef => (SqlColumnStub) columnRef.SqlColumn, + _ => (SqlColumnStub) column + }; - private static SqlUserColumn ExtractUserColumn(SqlColumn column) - { - switch (column) { - case SqlUserColumn userColumn: - return userColumn; - case SqlColumnRef columnRef: - return (SqlUserColumn) columnRef.SqlColumn; - default: - return (SqlUserColumn) column; - } - } + private static SqlUserColumn ExtractUserColumn(SqlColumn column) => + column switch { + SqlColumnRef columnRef => (SqlUserColumn) columnRef.SqlColumn, + _ => (SqlUserColumn) column + }; private static bool ShouldUseQueryReference(CompilableProvider origin, SqlProvider compiledSource) { var sourceSelect = compiledSource.Request.Statement; - if (sourceSelect.From==null) { + if (sourceSelect.From == null) { return false; } @@ -226,8 +197,10 @@ private static bool ShouldUseQueryReference(CompilableProvider origin, SqlProvid calculatedColumnIndexes.Add(columnIndex); rowNumberIsUsed = rowNumberIsUsed || ExtractUserColumn(column).Expression is SqlRowNumber; } + columnIndex++; } + var containsCalculatedColumns = calculatedColumnIndexes.Count > 0; var pagingIsUsed = rowNumberIsUsed || !sourceSelect.Limit.IsNullReference() || !sourceSelect.Offset.IsNullReference(); @@ -260,7 +233,7 @@ private static bool ShouldUseQueryReference(CompilableProvider origin, SqlProvid return usedColumnIndexes.Any(calculatedColumnIndexes.Contains); } case ProviderType.Aggregate: { - var aggregateProvider = (AggregateProvider)origin; + var aggregateProvider = (AggregateProvider) origin; var usedColumnIndexes = (aggregateProvider.AggregateColumns ?? Enumerable.Empty()) .Select(ac => ac.SourceIndex) .Concat(aggregateProvider.GroupColumnIndexes); From c461f6cc50b28ae476e9b33fa2d662e26547b3aa Mon Sep 17 00:00:00 2001 From: AlexUstinov Date: Thu, 6 Aug 2020 14:13:53 -0700 Subject: [PATCH 3/4] Simplify CreateProvider method code --- Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs index 0be8f6f062..13ed394eec 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs @@ -35,17 +35,13 @@ protected SqlProvider CreateProvider(SqlSelect statement, IEnumerable(); + var parameterBindings = extraBindings ?? Enumerable.Empty(); foreach (var provider in sources.OfType()) { var queryRequest = provider.Request; allowBatching &= queryRequest.CheckOptions(QueryRequestOptions.AllowOptimization); parameterBindings = parameterBindings.Concat(queryRequest.ParameterBindings); } - if (extraBindings != null) { - parameterBindings = parameterBindings.Concat(extraBindings); - } - var tupleDescriptor = origin.Header.TupleDescriptor; var options = QueryRequestOptions.Empty; From 1d75a49e79c19a4d86974a97edc655840ec515ae Mon Sep 17 00:00:00 2001 From: AlexUstinov Date: Fri, 7 Aug 2020 11:18:17 -0700 Subject: [PATCH 4/4] Use switch expression in IsTypeIdColumn method --- .../Orm/Providers/SqlCompiler.Helpers.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs index e2051ed391..b93f26b448 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs @@ -166,15 +166,12 @@ private static bool IsColumnStub(SqlColumn column) return column is SqlColumnRef columnRef && columnRef.SqlColumn is SqlColumnStub; } - private static bool IsTypeIdColumn(SqlColumn column) - { - if (column is SqlUserColumn) - return string.Equals(column.Name, "TypeId", StringComparison.OrdinalIgnoreCase); - var cRef = column as SqlColumnRef; - if (!ReferenceEquals(null, cRef)) - return string.Equals(cRef.Name, "TypeId", StringComparison.OrdinalIgnoreCase); - return false; - } + private static bool IsTypeIdColumn(SqlColumn column) => + column switch { + SqlUserColumn _ => string.Equals(column.Name, "TypeId", StringComparison.OrdinalIgnoreCase), + SqlColumnRef cRef => string.Equals(cRef.Name, "TypeId", StringComparison.OrdinalIgnoreCase), + _ => false + }; private static SqlColumnStub ExtractColumnStub(SqlColumn column) => column switch { @@ -290,7 +287,7 @@ private static bool ShouldUseQueryReference(CompilableProvider origin, SqlProvid return orderingOverCalculatedColumn; } default: - var typeIdIsOnlyCalculatedColumn = containsCalculatedColumns && (calculatedColumnIndexes.Count == 1) + var typeIdIsOnlyCalculatedColumn = containsCalculatedColumns && calculatedColumnIndexes.Count == 1 && IsTypeIdColumn(sourceSelect.Columns[calculatedColumnIndexes[0]]); return (containsCalculatedColumns && !typeIdIsOnlyCalculatedColumn) || distinctIsUsed || pagingIsUsed || groupByIsUsed; }