diff --git a/Orm/Xtensive.Orm/Orm/Providers/Expressions/ExpressionProcessor.cs b/Orm/Xtensive.Orm/Orm/Providers/Expressions/ExpressionProcessor.cs index ae10b97d18..a003318926 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/Expressions/ExpressionProcessor.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/Expressions/ExpressionProcessor.cs @@ -28,13 +28,13 @@ internal sealed partial class ExpressionProcessor : ExpressionVisitor memberCompilerProvider; - private readonly List[] sourceColumns; + private readonly IReadOnlyList[] sourceColumns; private readonly ExpressionEvaluator evaluator; private readonly ParameterExtractor parameterExtractor; private readonly LambdaExpression lambda; private readonly HashSet bindings; private readonly List activeParameters; - private readonly Dictionary> sourceMapping; + private readonly Dictionary> sourceMapping; private readonly SqlCompiler compiler; private readonly Dictionary bindingsWithIdentity @@ -448,7 +448,7 @@ private SqlExpression TryUnwrapEnum(SqlContainer container) // Constructors public ExpressionProcessor( - LambdaExpression lambda, HandlerAccessor handlers, SqlCompiler compiler, params List[] sourceColumns) + LambdaExpression lambda, HandlerAccessor handlers, SqlCompiler compiler, params IReadOnlyList[] sourceColumns) { ArgumentValidator.EnsureArgumentNotNull(lambda, "lambda"); ArgumentValidator.EnsureArgumentNotNull(handlers, "handlers"); @@ -478,7 +478,7 @@ public ExpressionProcessor( throw Exceptions.InternalError(Strings.ExParametersCountIsNotSameAsSourceColumnListsCount, OrmLog.Instance); if (sourceColumns.Any(list => list.Any(c => c.IsNullReference()))) throw Exceptions.InternalError(Strings.ExSourceColumnListContainsNullValues, OrmLog.Instance); - sourceMapping = new Dictionary>(); + sourceMapping = new Dictionary>(); } } } diff --git a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Apply.cs b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Apply.cs index 5405a0e1f0..ccaff33c69 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Apply.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Apply.cs @@ -92,10 +92,11 @@ private SqlSelect ProcessApplyViaSubqueries(ApplyProvider provider, SqlProvider if (shouldUseQueryReference) { var leftTable = left.PermanentReference; query = SqlDml.Select(leftTable); - query.Columns.AddRange(leftTable.Columns.Cast()); + query.Columns.AddRange(leftTable.Columns); } - else + else { query = left.Request.Statement.ShallowClone(); + } var isApplyExistence = provider.Right.Type==ProviderType.Existence || @@ -166,7 +167,7 @@ private SqlSelect ProcessApplyViaCrossApply(ApplyProvider provider, SqlProvider ? left.PermanentReference : left.Request.Statement.From; var leftColumns = leftShouldUseReference - ? leftTable.Columns.Cast() + ? (IReadOnlyList) leftTable.Columns : left.Request.Statement.Columns; var rightShouldUseReference = ShouldUseQueryReference(provider, right); @@ -174,7 +175,7 @@ private SqlSelect ProcessApplyViaCrossApply(ApplyProvider provider, SqlProvider ? right.PermanentReference : right.Request.Statement.From; var rightColumns = rightShouldUseReference - ? rightTable.Columns.Cast() + ? (IReadOnlyList) rightTable.Columns : right.Request.Statement.Columns; var joinType = provider.ApplyType==JoinType.LeftOuter @@ -185,8 +186,8 @@ private SqlSelect ProcessApplyViaCrossApply(ApplyProvider provider, SqlProvider joinType, leftTable, rightTable, - leftColumns.ToList(), - rightColumns.ToList()); + leftColumns, + rightColumns); var query = SqlDml.Select(joinedTable); if (!leftShouldUseReference) diff --git a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs index 8517876a2d..acac4f16b3 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs @@ -67,7 +67,7 @@ protected virtual string ProcessAliasedName(string name) } protected Pair> ProcessExpression(LambdaExpression le, - params List[] sourceColumns) + params IReadOnlyList[] sourceColumns) { var processor = new ExpressionProcessor(le, Handlers, this, sourceColumns); var result = new Pair>( @@ -81,7 +81,7 @@ protected static SqlSelect ExtractSqlSelect(CompilableProvider origin, SqlProvid if (ShouldUseQueryReference(origin, compiledSource)) { var queryRef = compiledSource.PermanentReference; var query = SqlDml.Select(queryRef); - query.Columns.AddRange(queryRef.Columns.Cast()); + query.Columns.AddRange(queryRef.Columns); return query; } return sourceSelect.ShallowClone(); diff --git a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Index.cs b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Index.cs index 3931d89cc5..87ed0f2282 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Index.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Index.cs @@ -94,7 +94,7 @@ private SqlSelect BuildUnionQuery(IndexInfo index) var unionRef = SqlDml.QueryRef(result); var query = SqlDml.Select(unionRef); - query.Columns.AddRange(unionRef.Columns.Cast()); + query.Columns.AddRange(unionRef.Columns); return query; } diff --git a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Paging.cs b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Paging.cs index b8ecaa6316..96263dcaa8 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Paging.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Paging.cs @@ -88,7 +88,7 @@ private SqlProvider VisitSkipRowNumber(SkipProvider provider) var source = compiledSource.Request.Statement; var queryRef = SqlDml.QueryRef(source); var query = SqlDml.Select(queryRef); - query.Columns.AddRange(queryRef.Columns.Cast()); + query.Columns.AddRange(queryRef.Columns); query.Where = queryRef.Columns.Last() > skipParameterBinding.ParameterReference; return CreateProvider(query, bindings, provider, compiledSource); } @@ -101,7 +101,7 @@ private SqlProvider VisitTakeRowNumber(TakeProvider provider) var source = compiledSource.Request.Statement; var queryRef = SqlDml.QueryRef(source); var query = SqlDml.Select(queryRef); - query.Columns.AddRange(queryRef.Columns.Cast()); + query.Columns.AddRange(queryRef.Columns); query.Where = queryRef.Columns.Last() <= takeParameterBinding.ParameterReference; return CreateProvider(query, bindings, provider, compiledSource); } @@ -116,7 +116,7 @@ private SqlProvider VisitPagingRowNumber(PagingProvider provider) var queryRef = SqlDml.QueryRef(source); var query = SqlDml.Select(queryRef); var rowNumberColumn = queryRef.Columns.Last(); - query.Columns.AddRange(queryRef.Columns.Cast()); + query.Columns.AddRange(queryRef.Columns); query.Where = SqlDml.Between(rowNumberColumn, fromParameterBinding.ParameterReference, toParameterBinding.ParameterReference); diff --git a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.cs b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.cs index 7fd4abeb09..5ab7e64028 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.cs @@ -129,10 +129,12 @@ protected override SqlProvider VisitDistinct(DistinctProvider provider) if (!sourceSelect.Limit.IsNullReference() || !sourceSelect.Offset.IsNullReference()) { var queryRef = SqlDml.QueryRef(sourceSelect); query = SqlDml.Select(queryRef); - query.Columns.AddRange(queryRef.Columns.Cast()); + query.Columns.AddRange(queryRef.Columns); } - else + else { query = sourceSelect.ShallowClone(); + } + query.Distinct = true; return CreateProvider(query, provider, source); } @@ -173,7 +175,7 @@ protected override SqlProvider VisitJoin(JoinProvider provider) ? left.PermanentReference : left.Request.Statement.From; var leftColumns = leftShouldUseReference - ? leftTable.Columns.Cast() + ? (IReadOnlyList) leftTable.Columns : left.Request.Statement.Columns; var leftExpressions = leftShouldUseReference ? leftTable.Columns.Cast().ToList() @@ -184,7 +186,7 @@ protected override SqlProvider VisitJoin(JoinProvider provider) ? right.PermanentReference : right.Request.Statement.From; var rightColumns = rightShouldUseReference - ? rightTable.Columns.Cast() + ? (IReadOnlyList) rightTable.Columns : right.Request.Statement.Columns; var rightExpressions = rightShouldUseReference ? rightTable.Columns.Cast().ToList() @@ -205,8 +207,8 @@ protected override SqlProvider VisitJoin(JoinProvider provider) joinType, leftTable, rightTable, - leftColumns.ToList(), - rightColumns.ToList(), + leftColumns, + rightColumns, joinExpression); var query = SqlDml.Select(joinedTable); @@ -229,10 +231,10 @@ protected override SqlProvider VisitPredicateJoin(PredicateJoinProvider provider ? left.PermanentReference : left.Request.Statement.From; var leftColumns = leftShouldUseReference - ? leftTable.Columns.Cast() + ? (IReadOnlyList) leftTable.Columns : left.Request.Statement.Columns; var leftExpressions = leftShouldUseReference - ? leftTable.Columns.Cast().ToList() + ? (IReadOnlyList) leftTable.Columns : ExtractColumnExpressions(left.Request.Statement); var rightShouldUseReference = ShouldUseQueryReference(provider, right); @@ -240,10 +242,10 @@ protected override SqlProvider VisitPredicateJoin(PredicateJoinProvider provider ? right.PermanentReference : right.Request.Statement.From; var rightColumns = rightShouldUseReference - ? rightTable.Columns.Cast() + ? (IReadOnlyList) rightTable.Columns : right.Request.Statement.Columns; var rightExpressions = rightShouldUseReference - ? rightTable.Columns.Cast().ToList() + ? (IReadOnlyList) rightTable.Columns : ExtractColumnExpressions(right.Request.Statement); @@ -257,8 +259,8 @@ protected override SqlProvider VisitPredicateJoin(PredicateJoinProvider provider joinType, leftTable, rightTable, - leftColumns.ToList(), - rightColumns.ToList(), + leftColumns, + rightColumns, joinExpression); var query = SqlDml.Select(joinedTable); @@ -308,10 +310,18 @@ protected override SqlProvider VisitSelect(SelectProvider provider) { var compiledSource = Compile(provider.Source); - SqlSelect query = ExtractSqlSelect(provider, compiledSource); - var originalColumns = query.Columns.ToList(); - query.Columns.Clear(); - query.Columns.AddRange(provider.ColumnIndexes.Select(i => originalColumns[i])); + var query = ExtractSqlSelect(provider, compiledSource); + var queryColumns = query.Columns; + var columnIndexes = provider.ColumnIndexes; + + var newIndex = 0; + var newColumns = new SqlColumn[columnIndexes.Count]; + foreach (var index in columnIndexes) { + newColumns[newIndex++] = queryColumns[index]; + } + + queryColumns.Clear(); + queryColumns.AddRange(newColumns); return CreateProvider(query, provider, compiledSource); } @@ -407,7 +417,7 @@ protected override SqlProvider VisitIntersect(IntersectProvider provider) var queryRef = SqlDml.QueryRef(result); SqlSelect query = SqlDml.Select(queryRef); - query.Columns.AddRange(queryRef.Columns.Cast()); + query.Columns.AddRange(queryRef.Columns); return CreateProvider(query, provider, left, right); } @@ -431,7 +441,7 @@ protected override SqlProvider VisitExcept(ExceptProvider provider) var result = SqlDml.Except(leftSelect, rightSelect); var queryRef = SqlDml.QueryRef(result); SqlSelect query = SqlDml.Select(queryRef); - query.Columns.AddRange(queryRef.Columns.Cast()); + query.Columns.AddRange(queryRef.Columns); return CreateProvider(query, provider, left, right); } @@ -455,7 +465,7 @@ protected override SqlProvider VisitConcat(ConcatProvider provider) var result = SqlDml.UnionAll(leftSelect, rightSelect); var queryRef = SqlDml.QueryRef(result); SqlSelect query = SqlDml.Select(queryRef); - query.Columns.AddRange(queryRef.Columns.Cast()); + query.Columns.AddRange(queryRef.Columns); return CreateProvider(query, provider, left, right); } @@ -479,7 +489,7 @@ protected override SqlProvider VisitUnion(UnionProvider provider) var result = SqlDml.Union(leftSelect, rightSelect); var queryRef = SqlDml.QueryRef(result); SqlSelect query = SqlDml.Select(queryRef); - query.Columns.AddRange(queryRef.Columns.Cast()); + query.Columns.AddRange(queryRef.Columns); return CreateProvider(query, provider, left, right); } diff --git a/Orm/Xtensive.Orm/Sql/Dml/Collections/SqlColumnCollection.cs b/Orm/Xtensive.Orm/Sql/Dml/Collections/SqlColumnCollection.cs index f5061db42b..73b1866dea 100644 --- a/Orm/Xtensive.Orm/Sql/Dml/Collections/SqlColumnCollection.cs +++ b/Orm/Xtensive.Orm/Sql/Dml/Collections/SqlColumnCollection.cs @@ -3,9 +3,8 @@ // For conditions of distribution and use, see license. using System; +using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using Xtensive.Core; @@ -15,74 +14,123 @@ namespace Xtensive.Sql.Dml /// Represents collection of s. /// [Serializable] - public class SqlColumnCollection : Collection + public class SqlColumnCollection : ICollection, IReadOnlyList { private static readonly StringComparer Comparer = StringComparer.OrdinalIgnoreCase; + private readonly List columnList; - public SqlColumn this[string name] - { - get - { - if (string.IsNullOrEmpty(name)) - return null; - return this.FirstOrDefault(column => Comparer.Equals(column.Name, name)); - } - set { throw new NotSupportedException(); } - } + /// + /// Gets the number of elements contained in the . + /// + public int Count => columnList.Count; - public bool IsReadOnly - { - get { return false; } - } + /// > + bool ICollection.IsReadOnly => false; - public void Add(SqlColumn item, string alias) - { - base.Add(SqlDml.ColumnRef(item, alias)); - } + /// > + IEnumerator IEnumerable.GetEnumerator() => columnList.GetEnumerator(); + + /// > + IEnumerator IEnumerable.GetEnumerator() => columnList.GetEnumerator(); + + /// + /// Returns a that iterates through the . + /// + public List.Enumerator GetEnumerator() => columnList.GetEnumerator(); - public void Add(SqlExpression expression) + /// + /// Gets or sets the column at the specified . + /// + public SqlColumn this[int index] { - if (expression is SqlColumn) - base.Add(expression as SqlColumn); - else - base.Add(SqlDml.ColumnRef(SqlDml.Column(expression))); + get => columnList[index]; + set => columnList[index] = value; } - public void Add(SqlExpression expression, string alias) + /// + /// Gets the column with the specified + /// or null if collection doesn't contain such a column. + /// + public SqlColumn this[string name] => + string.IsNullOrEmpty(name) ? null : columnList.Find(column => Comparer.Equals(column.Name, name)); + + /// + /// Adds a specified to the end of the . + /// + public void Add(SqlColumn column) => columnList.Add(column); + + /// + /// Builds a to the specified using + /// the provided and then adds it to the end of the . + /// + /// is null. + public void Add(SqlColumn column, string alias) { - ArgumentValidator.EnsureArgumentNotNull(alias, "alias"); - base.Add(SqlDml.ColumnRef(SqlDml.Column(expression), alias)); + ArgumentValidator.EnsureArgumentNotNull(alias, nameof(alias)); + columnList.Add(SqlDml.ColumnRef(column, alias)); } - public void Add(SqlColumnRef columnReference) + /// + /// Builds a by the specified and + /// then adds it to the end of the . + /// + public void Add(SqlExpression expression) => + columnList.Add(expression is SqlColumn column ? column : SqlDml.ColumnRef(SqlDml.Column(expression))); + + /// + /// Builds a by the specified and + /// ; then adds it to the end of the . + /// + /// is null. + public void Add(SqlExpression expression, string alias) { - ArgumentValidator.EnsureArgumentNotNull(columnReference, "columnReference"); - base.Add(columnReference); + ArgumentValidator.EnsureArgumentNotNull(alias, nameof(alias)); + columnList.Add(SqlDml.ColumnRef(SqlDml.Column(expression), alias)); } + /// + /// Builds a by the specified and + /// then inserts it into at the specified . + /// + /// is null. + /// is less than 0. + /// -or- is greater than . public void Insert(int index, SqlExpression expression, string alias) { - ArgumentValidator.EnsureArgumentNotNull(alias, "alias"); - Insert(index, SqlDml.ColumnRef(SqlDml.Column(expression), alias)); + ArgumentValidator.EnsureArgumentNotNull(alias, nameof(alias)); + columnList.Insert(index, SqlDml.ColumnRef(SqlDml.Column(expression), alias)); } + /// + /// Adds to the end of the . + /// + /// Columns to be added. public void AddRange(params SqlColumn[] columns) { - ArgumentValidator.EnsureArgumentNotNull(columns, "columns"); - foreach (SqlColumn c in columns) { - ArgumentValidator.EnsureArgumentNotNull(c, "column"); - base.Add(c); - } + ArgumentValidator.EnsureArgumentNotNull(columns, nameof(columns)); + columnList.AddRange(columns); } - public void AddRange(IEnumerable columns) - where TColumn : SqlColumn - { - ArgumentValidator.EnsureArgumentNotNull(columns, "columns"); - foreach (TColumn c in columns) - base.Add(c); - } + /// + /// Adds to the end of the . + /// + /// Columns to be added. + /// A type of the columns in the specified + /// collection; it must be or its inheritor. + public void AddRange(IEnumerable columns) where TColumn : SqlColumn => + columnList.AddRange(columns); + + /// + public bool Contains(SqlColumn item) => columnList.Contains(item); + + /// + public void CopyTo(SqlColumn[] array, int arrayIndex) => columnList.CopyTo(array, arrayIndex); + + /// + public bool Remove(SqlColumn item) => columnList.Remove(item); + /// + public void Clear() => columnList.Clear(); // Constructors @@ -91,14 +139,24 @@ public void AddRange(IEnumerable columns) /// public SqlColumnCollection() { + columnList = new List(); } /// /// Initializes new instance of this type. /// - public SqlColumnCollection(IList list) - : base(list) + public SqlColumnCollection(IEnumerable columns) + { + columnList = new List(columns); + } + + /// + /// Initializes a new instance of the class. + /// This is special version it uses provided list as is. + /// + internal SqlColumnCollection(List columns) { + columnList = columns; } } } \ No newline at end of file diff --git a/Orm/Xtensive.Orm/Sql/Dml/Collections/SqlTableColumnCollection.cs b/Orm/Xtensive.Orm/Sql/Dml/Collections/SqlTableColumnCollection.cs index a07a4105a9..e359ae0090 100644 --- a/Orm/Xtensive.Orm/Sql/Dml/Collections/SqlTableColumnCollection.cs +++ b/Orm/Xtensive.Orm/Sql/Dml/Collections/SqlTableColumnCollection.cs @@ -3,8 +3,9 @@ // For conditions of distribution and use, see license. using System; +using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; +using System.Runtime.CompilerServices; namespace Xtensive.Sql.Dml { @@ -12,36 +13,98 @@ namespace Xtensive.Sql.Dml /// Represents collection of s. /// [Serializable] - public class SqlTableColumnCollection - : ReadOnlyCollection + public class SqlTableColumnCollection : IReadOnlyList { private static readonly StringComparer Comparer = StringComparer.OrdinalIgnoreCase; + private readonly List columnList; + private Dictionary columnLookup; /// - /// An indexer that provides access to collection items by their names. - /// Returns if there is no such item. + /// Gets the number of elements contained in the . + /// + public int Count => columnList.Count; + + /// > + IEnumerator IEnumerable.GetEnumerator() => columnList.GetEnumerator(); + + /// > + IEnumerator IEnumerable.GetEnumerator() => columnList.GetEnumerator(); + + /// + /// Returns a that iterates through the . + /// + public List.Enumerator GetEnumerator() => columnList.GetEnumerator(); + + /// + /// Gets the column at the specified . + /// + public SqlTableColumn this[int index] => columnList[index]; + + /// + /// Gets the column with the specified + /// or if collection doesn't contain such a column. /// public SqlTableColumn this[string name] { - get - { - if (string.IsNullOrEmpty(name)) + get { + if (string.IsNullOrEmpty(name)) { return null; - foreach (SqlTableColumn column in this) - if (Comparer.Equals(column.Name, name)) - return column; - return null; + } + + var count = columnList.Count; + return count <= 16 ? FindColumnInList(name) : FindColumnInDictionaryLookup(name, count); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private SqlTableColumn FindColumnInList(string name) + { + foreach (var column in columnList) { + if (Comparer.Equals(column.Name, name)) { + return column; + } + } + + return null; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private SqlTableColumn FindColumnInDictionaryLookup(string name, int count) + { + if (columnLookup != null) { + return columnLookup.TryGetValue(name, out var column) ? column : null; + } + + SqlTableColumn result = null; + columnLookup = new Dictionary(count, Comparer); + for (var index = count - 1; index >= 0; index--) { + var column = columnList[index]; + var columnName = column.Name; + columnLookup[columnName] = column; + if (Comparer.Equals(columnName, name)) { + result = column; + } } + + return result; + } + + /// + /// Initializes a new instance of the class. + /// + /// A collection of s to be wrapped. + public SqlTableColumnCollection(IEnumerable columns) + { + columnList = new List(columns); } /// /// Initializes a new instance of the class. + /// This is special version it uses provided list as is. /// - /// The list to wrap. - /// list is null. - public SqlTableColumnCollection(IList list) - : base(list) + internal SqlTableColumnCollection(List columns) { + columnList = columns; } } } \ No newline at end of file diff --git a/Orm/Xtensive.Orm/Sql/Dml/SqlContainsTable.cs b/Orm/Xtensive.Orm/Sql/Dml/SqlContainsTable.cs index 97bc7db3f6..4c377d939f 100644 --- a/Orm/Xtensive.Orm/Sql/Dml/SqlContainsTable.cs +++ b/Orm/Xtensive.Orm/Sql/Dml/SqlContainsTable.cs @@ -66,35 +66,40 @@ public SqlQueryExpression UnionAll(ISqlQueryExpression operand) // Constructors - internal SqlContainsTable(DataTable dataTable, SqlExpression freeText, IEnumerable columnNames) + internal SqlContainsTable(DataTable dataTable, SqlExpression freeText, ICollection columnNames) : this(dataTable, freeText, columnNames, ArrayUtils.EmptyArray, null) { } - internal SqlContainsTable(DataTable dataTable, SqlExpression freeText, IEnumerable columnNames, ICollection targetColumnNames) + internal SqlContainsTable(DataTable dataTable, SqlExpression freeText, ICollection columnNames, ICollection targetColumnNames) : this(dataTable, freeText, columnNames, targetColumnNames, null) { } - internal SqlContainsTable(DataTable dataTable, SqlExpression freeText, IEnumerable columNames, SqlExpression topN) - : this(dataTable, freeText, columNames, ArrayUtils.EmptyArray, topN) + internal SqlContainsTable(DataTable dataTable, SqlExpression freeText, ICollection columnNames, SqlExpression topN) + : this(dataTable, freeText, columnNames, ArrayUtils.EmptyArray, topN) { } - internal SqlContainsTable(DataTable dataTable, SqlExpression searchCondition, IEnumerable columnNames, ICollection targetColumnNames, SqlExpression topNByRank) + internal SqlContainsTable(DataTable dataTable, SqlExpression searchCondition, ICollection columnNames, ICollection targetColumnNames, SqlExpression topNByRank) : base(string.Empty) { TargetTable = SqlDml.TableRef(dataTable); SearchCondition = searchCondition; TopNByRank = topNByRank; - var targetColumns = new List(); - if (targetColumnNames.Count == 0) - targetColumns.Add(Asterisk); - else - targetColumns = targetColumnNames.Select(cn => SqlDml.TableColumn(this, cn)).ToList(); - TargetColumns = new SqlTableColumnCollection(targetColumns); - - columns = new SqlTableColumnCollection(columnNames.Select(column=>SqlDml.TableColumn(this, column)).ToList()); + var targetColumnCount = targetColumnNames.Count; + if (targetColumnCount == 0) { + TargetColumns = new SqlTableColumnCollection(new List(1) {Asterisk}); + } + else { + var targetColumns = new List(targetColumnCount); + targetColumns.AddRange(targetColumnNames.Select(columnName => SqlDml.TableColumn(this, columnName))); + TargetColumns = new SqlTableColumnCollection(targetColumns); + } + + var columnList = new List(columnNames.Count); + columnList.AddRange(columnNames.Select(columnName => SqlDml.TableColumn(this, columnName))); + columns = new SqlTableColumnCollection(columnList); } } } diff --git a/Orm/Xtensive.Orm/Sql/Dml/SqlFreeTextTable.cs b/Orm/Xtensive.Orm/Sql/Dml/SqlFreeTextTable.cs index 8bf1535cad..b0f0274ef5 100644 --- a/Orm/Xtensive.Orm/Sql/Dml/SqlFreeTextTable.cs +++ b/Orm/Xtensive.Orm/Sql/Dml/SqlFreeTextTable.cs @@ -71,35 +71,40 @@ public SqlQueryExpression UnionAll(ISqlQueryExpression operand) // Constructors - internal SqlFreeTextTable(DataTable dataTable, SqlExpression freeText, IEnumerable columnNames) + internal SqlFreeTextTable(DataTable dataTable, SqlExpression freeText, ICollection columnNames) : this(dataTable, freeText, columnNames, ArrayUtils.EmptyArray, null) { } - internal SqlFreeTextTable(DataTable dataTable, SqlExpression freeText, IEnumerable columnNames, ICollection targetColumnNames) + internal SqlFreeTextTable(DataTable dataTable, SqlExpression freeText, ICollection columnNames, ICollection targetColumnNames) : this(dataTable, freeText, columnNames, targetColumnNames, null) { } - internal SqlFreeTextTable(DataTable dataTable, SqlExpression freeText, IEnumerable columNames, SqlExpression topN) - : this(dataTable, freeText, columNames, ArrayUtils.EmptyArray, topN) + internal SqlFreeTextTable(DataTable dataTable, SqlExpression freeText, ICollection columnNames, SqlExpression topN) + : this(dataTable, freeText, columnNames, ArrayUtils.EmptyArray, topN) { } - internal SqlFreeTextTable(DataTable dataTable, SqlExpression freeText, IEnumerable columnNames, ICollection targetColumnNames, SqlExpression topNByRank) + internal SqlFreeTextTable(DataTable dataTable, SqlExpression freeText, ICollection columnNames, ICollection targetColumnNames, SqlExpression topNByRank) : base(string.Empty) { TargetTable = SqlDml.TableRef(dataTable); FreeText = freeText; TopNByRank = topNByRank; - var targetColumns = new List(); - if (targetColumnNames.Count == 0) - targetColumns.Add(Asterisk); - else - targetColumns = targetColumnNames.Select(cn => SqlDml.TableColumn(this, cn)).ToList(); - TargetColumns = new SqlTableColumnCollection(targetColumns); - - columns = new SqlTableColumnCollection(columnNames.Select(column=>SqlDml.TableColumn(this, column)).ToList()); + var targetColumnCount = targetColumnNames.Count; + if (targetColumnCount == 0) { + TargetColumns = new SqlTableColumnCollection(new List(1) {Asterisk}); + } + else { + var targetColumns = new List(targetColumnCount); + targetColumns.AddRange(targetColumnNames.Select(columnName => SqlDml.TableColumn(this, columnName))); + TargetColumns = new SqlTableColumnCollection(targetColumns); + } + + var columnList = new List(columnNames.Count); + columnList.AddRange(columnNames.Select(columnName => SqlDml.TableColumn(this, columnName))); + columns = new SqlTableColumnCollection(columnList); } } } \ No newline at end of file diff --git a/Orm/Xtensive.Orm/Sql/Dml/SqlJoinedTable.cs b/Orm/Xtensive.Orm/Sql/Dml/SqlJoinedTable.cs index 4d19e98647..36de650ecb 100644 --- a/Orm/Xtensive.Orm/Sql/Dml/SqlJoinedTable.cs +++ b/Orm/Xtensive.Orm/Sql/Dml/SqlJoinedTable.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.Linq; namespace Xtensive.Sql.Dml { @@ -30,11 +29,13 @@ public SqlJoinExpression JoinExpression internal override object Clone(SqlNodeCloneContext context) { - if (context.NodeMapping.ContainsKey(this)) + if (context.NodeMapping.ContainsKey(this)) { return context.NodeMapping[this]; + } - var clone = new SqlJoinedTable((SqlJoinExpression)joinExpression.Clone(context)); - clone.AliasedColumns = new SqlColumnCollection(AliasedColumns); + var clone = new SqlJoinedTable((SqlJoinExpression) joinExpression.Clone(context)) { + AliasedColumns = new SqlColumnCollection(new List(AliasedColumns)) + }; context.NodeMapping[this] = clone; return clone; } @@ -54,17 +55,25 @@ public override IEnumerator GetEnumerator() // Constructor internal SqlJoinedTable(SqlJoinExpression joinExpression) + : this(joinExpression, joinExpression.Left.Columns, joinExpression.Right.Columns) { - this.joinExpression = joinExpression; - var joinedColumns = joinExpression.Left.Columns.Concat(joinExpression.Right.Columns).ToList(); - columns = new SqlTableColumnCollection(joinedColumns); - AliasedColumns = new SqlColumnCollection(columns.Cast().ToList()); } - internal SqlJoinedTable(SqlJoinExpression joinExpression, IEnumerable leftColumns, IEnumerable rightColumns) - : this (joinExpression) + internal SqlJoinedTable(SqlJoinExpression joinExpression, IReadOnlyList leftColumns, IReadOnlyList rightColumns) { - AliasedColumns = new SqlColumnCollection(leftColumns.Concat(rightColumns).ToList()); + this.joinExpression = joinExpression; + var allLeftColumns = joinExpression.Left.Columns; + var allRightColumns = joinExpression.Right.Columns; + + var joinedColumns = new List(allLeftColumns.Count + allRightColumns.Count); + joinedColumns.AddRange(allLeftColumns); + joinedColumns.AddRange(allRightColumns); + columns = new SqlTableColumnCollection(joinedColumns); + + var aliasedColumns = new List(leftColumns.Count + rightColumns.Count); + aliasedColumns.AddRange(leftColumns); + aliasedColumns.AddRange(rightColumns); + AliasedColumns = new SqlColumnCollection(aliasedColumns); } } } diff --git a/Orm/Xtensive.Orm/Sql/Dml/SqlQueryRef.cs b/Orm/Xtensive.Orm/Sql/Dml/SqlQueryRef.cs index 68fe18299e..ae110c9514 100644 --- a/Orm/Xtensive.Orm/Sql/Dml/SqlQueryRef.cs +++ b/Orm/Xtensive.Orm/Sql/Dml/SqlQueryRef.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Linq; namespace Xtensive.Sql.Dml @@ -57,36 +56,36 @@ internal SqlQueryRef(ISqlQueryExpression query, string name) this.query = query; var queryColumns = new List(); foreach (var queryExpression in query) { - - var select = queryExpression as SqlSelect; - if (select!=null) { - var selectColumns = select.Columns.ToList(); - select.Columns.Clear(); - foreach (var originalColumn in selectColumns) { + if (queryExpression is SqlSelect sqlSelect) { + var selectColumns = sqlSelect.Columns; + for (int index = 0, count = selectColumns.Count; index < count; index++) { + var originalColumn = selectColumns[index]; var column = originalColumn; - var stubColumn = column as SqlColumnStub; - if (!ReferenceEquals(null, stubColumn)) + if (column is SqlColumnStub stubColumn) { column = stubColumn.Column; - var columnRef = column as SqlColumnRef; - if (!ReferenceEquals(null, columnRef)) { + } + + if (column is SqlColumnRef columnRef) { stubColumn = columnRef.SqlColumn as SqlColumnStub; - if (!ReferenceEquals(null, stubColumn)) + if (!ReferenceEquals(null, stubColumn)) { column = stubColumn.Column; + } } - select.Columns.Add(column); + + selectColumns[index] = column; queryColumns.Add(SqlDml.TableColumn(this, originalColumn.Name)); } } - var freeTextTable = queryExpression as SqlFreeTextTable; - if (freeTextTable!=null ) - foreach (var originalColumn in freeTextTable.Columns) - queryColumns.Add(SqlDml.TableColumn(this, originalColumn.Name)); + if (queryExpression is SqlFreeTextTable freeTextTable) { + queryColumns.AddRange( + freeTextTable.Columns.Select(originalColumn => SqlDml.TableColumn(this, originalColumn.Name))); + } - var containsTable = queryExpression as SqlContainsTable; - if (containsTable!=null ) - foreach (var originalColumn in containsTable.Columns) - queryColumns.Add(SqlDml.TableColumn(this, originalColumn.Name)); + if (queryExpression is SqlContainsTable containsTable) { + queryColumns.AddRange( + containsTable.Columns.Select(originalColumn => SqlDml.TableColumn(this, originalColumn.Name))); + } break; } diff --git a/Orm/Xtensive.Orm/Sql/Dml/SqlTableRef.cs b/Orm/Xtensive.Orm/Sql/Dml/SqlTableRef.cs index c3fba85062..f5930a3b35 100644 --- a/Orm/Xtensive.Orm/Sql/Dml/SqlTableRef.cs +++ b/Orm/Xtensive.Orm/Sql/Dml/SqlTableRef.cs @@ -17,75 +17,67 @@ namespace Xtensive.Sql.Dml [Serializable] public class SqlTableRef : SqlTable { - private DataTable dataTable; - /// /// Gets the name of the instance. /// /// The name. - public override string Name - { - get { return string.IsNullOrEmpty(base.Name) ? dataTable.DbName : base.Name; } - } + public override string Name => string.IsNullOrEmpty(base.Name) ? DataTable.DbName : base.Name; /// /// Gets the referenced table. /// /// The table. - public DataTable DataTable - { - get { return dataTable; } - } + public DataTable DataTable { get; private set; } internal override object Clone(SqlNodeCloneContext context) { - if (context.NodeMapping.ContainsKey(this)) + if (context.NodeMapping.ContainsKey(this)) { return context.NodeMapping[this]; + } - var clone = new SqlTableRef {Name = Name, dataTable = DataTable}; + return CreateClone(context); + } + + private SqlTableRef CreateClone(SqlNodeCloneContext context) + { + var clone = new SqlTableRef {Name = Name, DataTable = DataTable}; context.NodeMapping[this] = clone; - var columnClones = new Collection(); - foreach (var column in columns) - columnClones.Add((SqlTableColumn) column.Clone(context)); + var columnClones = new List(columns.Count); + columnClones.AddRange(columns.Select(column => (SqlTableColumn) column.Clone(context))); + clone.columns = new SqlTableColumnCollection(columnClones); return clone; } - public override void AcceptVisitor(ISqlVisitor visitor) - { - visitor.Visit(this); - } - + public override void AcceptVisitor(ISqlVisitor visitor) => visitor.Visit(this); // Constructors private SqlTableRef() - { - } + { } internal SqlTableRef(DataTable dataTable) - : this(dataTable, string.Empty) - { - } + : this(dataTable, string.Empty, Array.Empty()) + { } internal SqlTableRef(DataTable dataTable, string name) - : this(dataTable, name, ArrayUtils.EmptyArray) - { - this.dataTable = dataTable; - var tableColumns = new List(); - foreach (DataTableColumn c in dataTable.Columns) - tableColumns.Add(SqlDml.TableColumn(this, c.Name)); - columns = new SqlTableColumnCollection(tableColumns); - } + : this(dataTable, name, Array.Empty()) + { } internal SqlTableRef(DataTable dataTable, string name, params string[] columnNames) : base(name) { - this.dataTable = dataTable; - var tableColumns = columnNames.Length == 0 - ? dataTable.Columns.Select(c => SqlDml.TableColumn(this, c.Name)).ToList() - : columnNames.Select(cn => SqlDml.TableColumn(this, cn)).ToList(); + DataTable = dataTable; + List tableColumns; + if (columnNames.Length == 0) { + tableColumns = new List(dataTable.Columns.Count); + tableColumns.AddRange(dataTable.Columns.Select(column => SqlDml.TableColumn(this, column.Name))); + } + else { + tableColumns = new List(columnNames.Length); + tableColumns.AddRange(columnNames.Select(columnName => SqlDml.TableColumn(this, columnName))); + } columns = new SqlTableColumnCollection(tableColumns); } } diff --git a/Orm/Xtensive.Orm/Sql/SqlDml.cs b/Orm/Xtensive.Orm/Sql/SqlDml.cs index 8cab506da3..ebe100165a 100644 --- a/Orm/Xtensive.Orm/Sql/SqlDml.cs +++ b/Orm/Xtensive.Orm/Sql/SqlDml.cs @@ -840,7 +840,8 @@ public static SqlJoinedTable Join(SqlJoinType joinType, SqlTable left, SqlTable return Join(joinType, left, right, null); } - public static SqlJoinedTable Join(SqlJoinType joinType, SqlTable left, SqlTable right, IList leftColumns, IList rightColumns) + public static SqlJoinedTable Join(SqlJoinType joinType, SqlTable left, SqlTable right, + IReadOnlyList leftColumns, IReadOnlyList rightColumns) { return Join(joinType, left, right, leftColumns, rightColumns, null); } @@ -854,7 +855,8 @@ public static SqlJoinedTable Join(SqlJoinType joinType, SqlTable left, SqlTable return new SqlJoinedTable(new SqlJoinExpression(joinType, left, right, expression)); } - public static SqlJoinedTable Join(SqlJoinType joinType, SqlTable left, SqlTable right, IList leftColumns, IList rightColumns, SqlExpression expression) + public static SqlJoinedTable Join(SqlJoinType joinType, SqlTable left, SqlTable right, + IReadOnlyList leftColumns, IReadOnlyList rightColumns, SqlExpression expression) { ArgumentValidator.EnsureArgumentNotNull(left, "left"); ArgumentValidator.EnsureArgumentNotNull(right, "right");