Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ protected override SqlProvider VisitFreeText(FreeTextProvider provider)

var index = provider.PrimaryIndex.Resolve(Handlers.Domain.Model);
var table = Mapping[index.ReflectedType];
var columns = provider.Header.Columns.Select(column => column.Name).ToList();
var columns = provider.Header.Columns.Columns.Select(column => column.Name).ToList();

if (provider.TopN == null) {
fromTable = SqlDml.FreeTextTable(table, criteriaBinding.ParameterReference, columns);
Expand Down Expand Up @@ -66,7 +66,7 @@ protected override SqlProvider VisitContainsTable(ContainsTableProvider provider

var index = provider.PrimaryIndex.Resolve(Handlers.Domain.Model);
var table = Mapping[index.ReflectedType];
var columns = provider.Header.Columns.Select(column => column.Name).ToList();
var columns = provider.Header.Columns.Columns.Select(column => column.Name).ToList();

var targetColumnNames = provider.TargetColumns.Select(c => c.Name).ToArray();
if (provider.TopN == null) {
Expand Down
6 changes: 3 additions & 3 deletions Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ internal protected override SqlProvider VisitStore(StoreProvider provider)
var source = provider.Source is RawProvider rawProvider
? (ExecutableProvider) (new Rse.Providers.ExecutableRawProvider(rawProvider))
: Compile(provider.Source);
var columnNames = provider.Header.Columns.Select(column => column.Name).ToArray();
var columnNames = provider.Header.Columns.Columns.Select(column => column.Name).ToArray();
var descriptor = DomainHandler.TemporaryTableManager
.BuildDescriptor(Mapping, provider.Name, provider.Header.TupleDescriptor, columnNames);
var request = CreateQueryRequest(Driver, descriptor.QueryStatement, null, descriptor.TupleDescriptor, QueryRequestOptions.Empty);
Expand Down Expand Up @@ -553,7 +553,7 @@ internal protected override SqlProvider VisitRowNumber(RowNumberProvider provide

var query = ExtractSqlSelect(provider, source);
var rowNumber = SqlDml.RowNumber();
query.Columns.Add(rowNumber, header.Columns.Last().Name);
query.Columns.Add(rowNumber, header.Columns.Columns.Last().Name);
var columns = ExtractColumnExpressions(query);
foreach (var order in directionCollection)
rowNumber.OrderBy.Add(columns[order.Key], order.Value==Direction.Positive);
Expand Down Expand Up @@ -592,7 +592,7 @@ internal protected override SqlProvider VisitLock(LockProvider provider)

protected override void Initialize()
{
foreach (var column in RootProvider.Header.Columns)
foreach (var column in RootProvider.Header.Columns.Columns)
rootColumns.Add(column.Origin);
}

Expand Down
205 changes: 71 additions & 134 deletions Orm/Xtensive.Orm/Orm/Rse/ColumnCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,154 +4,91 @@
// Created by: Alexey Kochetov
// Created: 2007.09.24

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Xtensive.Core;

namespace Xtensive.Orm.Rse;

namespace Xtensive.Orm.Rse
/// <summary>
/// Collection of <see cref="Column"/> items.
/// </summary>
[Serializable]
public readonly struct ColumnCollection
{
/// <summary>
/// Collection of <see cref="Column"/> items.
/// </summary>
[Serializable]
public sealed class ColumnCollection : IReadOnlyList<Column>
{
public struct Enumerator : IEnumerator<Column>, IEnumerator
{
private readonly IReadOnlyList<Column> list;
private int index;
public Column Current { get; private set; }

object IEnumerator.Current =>
index == 0 || index == list.Count + 1
? throw new InvalidOperationException("Enumeration cannot happen")
: Current;

public void Dispose()
{
}

public bool MoveNext()
{
if (index < list.Count) {
Current = list[index++];
return true;
}
index = list.Count + 1;
Current = default;
return false;
}

void IEnumerator.Reset()
{
index = 0;
Current = default;
}

internal Enumerator(IReadOnlyList<Column> list)
{
this.list = list;
index = 0;
Current = default;
}
}
private readonly Dictionary<string, int> nameIndex;

private readonly Dictionary<string, int> nameIndex;
private readonly IReadOnlyList<Column> columns;
public IReadOnlyList<Column> Columns { get; }

/// <summary>
/// Gets the number of <see href="Column"/>s in the collection.
/// </summary>
public ColNum Count => (ColNum)columns.Count;

int IReadOnlyCollection<Column>.Count => columns.Count;

/// <summary>
/// Gets a <see href="Column"/> instance by its index.
/// </summary>
public Column this[int index] => columns[index];

/// <summary>
/// Gets <see cref="Column"/> by provided <paramref name="fullName"/>.
/// </summary>
/// <remarks>
/// Returns <see cref="Column"/> if it was found; otherwise <see langword="null"/>.
/// </remarks>
/// <param name="fullName">Full name of the <see cref="Column"/> to find.</param>
public Column this[string fullName] =>
nameIndex.TryGetValue(fullName, out var index) ? columns[index] : null;
/// <summary>
/// Gets the number of <see href="Column"/>s in the collection.
/// </summary>
public ColNum Count => (ColNum)Columns.Count;

/// <summary>
/// Determines whether the collecton contains specified column
/// </summary>
/// <param name="column"></param>
/// <returns></returns>
public bool Contains(Column column)
{
if (columns is ICollection<Column> colColumns)
return colColumns.Contains(column);
return columns.Contains(column);
}

/// <summary>
/// Joins this collection with specified the column collection.
/// </summary>
/// <param name="joined">The joined.</param>
/// <returns>The joined collection.</returns>
public ColumnCollection Join(IEnumerable<Column> joined)
{
return new ColumnCollection(this.Concat(joined).ToList());
}
/// <summary>
/// Gets a <see href="Column"/> instance by its index.
/// </summary>
public Column this[int index] => Columns[index];

/// <summary>
/// Aliases the specified <see cref="Column"/> collection.
/// </summary>
/// <param name="alias">The alias to add.</param>
/// <returns>Aliased collection of columns.</returns>
public ColumnCollection Alias(string alias)
{
ArgumentException.ThrowIfNullOrEmpty(alias);
return new ColumnCollection(this.Select(column => column.Clone(alias + "." + column.Name)).ToArray(Count));
}
/// <summary>
/// Gets <see cref="Column"/> by provided <paramref name="fullName"/>.
/// </summary>
/// <remarks>
/// Returns <see cref="Column"/> if it was found; otherwise <see langword="null"/>.
/// </remarks>
/// <param name="fullName">Full name of the <see cref="Column"/> to find.</param>
public Column this[string fullName] =>
nameIndex.TryGetValue(fullName, out var index) ? Columns[index] : null;

/// <summary>
/// Returns an enumerator that iterates through the <see href="ColumnCollection"/>.
/// </summary>
public Enumerator GetEnumerator() => new Enumerator(this);
/// <summary>
/// Determines whether the collecton contains specified column
/// </summary>
/// <param name="column"></param>
/// <returns></returns>
public bool Contains(Column column) =>
Columns is ICollection<Column> colColumns ? colColumns.Contains(column) : Columns.Contains(column);

/// <summary>
/// Returns an enumerator that iterates through the <see href="ColumnCollection"/>.
/// </summary>
IEnumerator<Column> IEnumerable<Column>.GetEnumerator() => GetEnumerator();
/// <summary>
/// Joins this collection with specified the column collection.
/// </summary>
/// <param name="joined">The joined.</param>
/// <returns>The joined collection.</returns>
public ColumnCollection Join(IEnumerable<Column> joined)
{
return new ColumnCollection(Columns.Concat(joined).ToList());
}

/// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <summary>
/// Aliases the specified <see cref="Column"/> collection.
/// </summary>
/// <param name="alias">The alias to add.</param>
/// <returns>Aliased collection of columns.</returns>
public ColumnCollection Alias(string alias)
{
ArgumentException.ThrowIfNullOrEmpty(alias);
return new ColumnCollection(Columns.Select(column => column.Clone(alias + "." + column.Name)).ToArray(Count));
}

// Constructors
// Constructors

/// <summary>
/// Initializes a new instance of this class.
/// </summary>
/// <param name="columns">Collection of items to add.</param>
/// <remarks>
/// <paramref name="columns"/> is used to initialize inner field directly
/// to save time on avoiding collection copy. If you pass an <see cref="IReadOnlyList{Column}"/>
/// implementor that, in fact, can be changed, make sure the passed collection doesn't change afterwards.
/// Ideally, use arrays instead of <see cref="List{T}"/> or similar collections.
/// Changing the passed collection afterwards will lead to unpredictable results.
/// </remarks>
public ColumnCollection(IReadOnlyList<Column> columns)
{
//!!! Direct initialization by parameter is unsafe performance optimization: See remarks in ctor summary!
this.columns = columns;
var count = this.columns.Count;
nameIndex = new Dictionary<string, int>(count);
for (var index = count; index-- > 0;) {
nameIndex.Add(this.columns[index].Name, index);
}
/// <summary>
/// Initializes a new instance of this class.
/// </summary>
/// <param name="columns">Collection of items to add.</param>
/// <remarks>
/// <paramref name="columns"/> is used to initialize inner field directly
/// to save time on avoiding collection copy. If you pass an <see cref="IReadOnlyList{Column}"/>
/// implementor that, in fact, can be changed, make sure the passed collection doesn't change afterwards.
/// Ideally, use arrays instead of <see cref="List{T}"/> or similar collections.
/// Changing the passed collection afterwards will lead to unpredictable results.
/// </remarks>
public ColumnCollection(IReadOnlyList<Column> columns)
{
//!!! Direct initialization by parameter is unsafe performance optimization: See remarks in ctor summary!
Columns = columns;
var count = Columns.Count;
nameIndex = new Dictionary<string, int>(count);
for (var index = count; index-- > 0;) {
nameIndex.Add(Columns[index].Name, index);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected override RecordSetHeader BuildHeader()
/// <inheritdoc/>
protected override string ParametersToString()
{
return Header.Columns.Select(c => c.Name).ToCommaDelimitedString();
return Header.Columns.Columns.Select(c => c.Name).ToCommaDelimitedString();
}

internal override Provider Visit(ProviderVisitor visitor) => visitor.VisitSelect(this);
Expand All @@ -50,4 +50,4 @@ public SelectProvider(CompilableProvider provider, IReadOnlyList<ColNum> columnI
Initialize();
}
}
}
}
14 changes: 7 additions & 7 deletions Orm/Xtensive.Orm/Orm/Rse/RecordSetHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public RecordSetHeader Alias(string alias)
ColumnCollection resultColumns = Columns.Alias(alias);

return new RecordSetHeader(
TupleDescriptor, resultColumns, ColumnGroups, OrderTupleDescriptor, Order);
TupleDescriptor, resultColumns.Columns, ColumnGroups, OrderTupleDescriptor, Order);
}

/// <summary>
Expand All @@ -75,7 +75,7 @@ public RecordSetHeader Alias(string alias)
public RecordSetHeader Add(Column column)
{
var newColumns = new List<Column>(Columns.Count + 1);
newColumns.AddRange(Columns);
newColumns.AddRange(Columns.Columns);
newColumns.Add(column);

var newTupleDescriptor = CreateTupleDescriptor(newColumns);
Expand All @@ -96,7 +96,7 @@ public RecordSetHeader Add(Column column)
public RecordSetHeader Add(IReadOnlyList<Column> columns)
{
var n = Columns.Count + columns.Count;
var newColumns = Columns.Concat(columns).ToArray(n);
var newColumns = Columns.Columns.Concat(columns).ToArray(n);

var newTupleDescriptor = CreateTupleDescriptor(newColumns);

Expand All @@ -118,10 +118,10 @@ public RecordSetHeader Join(RecordSetHeader joined)
var columnCount = Columns.Count;
var newColumns = new Column[columnCount + joined.Columns.Count];
int j = 0;
foreach (var c in Columns) {
foreach (var c in Columns.Columns) {
newColumns[j++] = c;
}
foreach (var c in joined.Columns) {
foreach (var c in joined.Columns.Columns) {
newColumns[j++] = c.Clone((ColNum) (columnCount + c.Index));
}

Expand Down Expand Up @@ -201,7 +201,7 @@ public RecordSetHeader Sort(DirectionCollection<ColNum> sortOrder)
{
return new RecordSetHeader(
TupleDescriptor,
Columns,
Columns.Columns,
ColumnGroups,
TupleDescriptor,
sortOrder);
Expand Down Expand Up @@ -269,7 +269,7 @@ private static TupleDescriptor CreateTupleDescriptor(IReadOnlyList<Column> newCo
/// <inheritdoc/>
public override string ToString()
{
return Columns.Select(c => c.ToString()).ToCommaDelimitedString();
return Columns.Columns.Select(c => c.ToString()).ToCommaDelimitedString();
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ internal protected override IncludeProvider VisitInclude(IncludeProvider provide
var source = VisitCompilable(provider.Source);

var currentMapping = mappings[provider.Source];
var calulatedColumn = provider.Header.Columns.Last();
var calulatedColumn = provider.Header.Columns.Columns.Last();
mappings[provider] = Merge(currentMapping, [calulatedColumn.Index]);
if (source == provider.Source) {
return provider;
Expand Down Expand Up @@ -260,7 +260,7 @@ internal protected override AggregateProvider VisitAggregate(AggregateProvider p
using ColumnMap sourceMap = new(mappings[provider.Source]);
var currentMap = mappings[provider];

mappings[provider] = provider.Header.Columns.Select(c => c.Index).ToList(provider.Header.Columns.Count);
mappings[provider] = provider.Header.Columns.Columns.Select(c => c.Index).ToList(provider.Header.Columns.Count);

if (source == provider.Source) {
return provider;
Expand Down Expand Up @@ -325,7 +325,7 @@ internal protected override RowNumberProvider VisitRowNumber(RowNumberProvider p
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();
var rowNumberColumn = provider.Header.Columns.Columns.Last();
mappings[provider] = Merge(currentMapping, [rowNumberColumn.Index]);
return newSource == provider.Source
? provider
Expand All @@ -340,7 +340,7 @@ internal protected override CompilableProvider VisitStore(StoreProvider provider

if (hasGrouping) {
mappings.Add(provider.Sources[0],
Merge(mappings[provider], provider.Header.Columns.Select((c, i) => (ColNum)i)));
Merge(mappings[provider], provider.Header.Columns.Columns.Select((c, i) => (ColNum)i)));
}
else {
OnRecursionEntrance(provider);
Expand Down
Loading