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
1 change: 1 addition & 0 deletions ChangeLog/7.1.2_dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[main] Addressed issue when cycles in Entity dependency graph were not detected
42 changes: 37 additions & 5 deletions Orm/Xtensive.Orm/Sorting/TopologicalSorter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
using Xtensive.Collections;
using System.Linq;
using Xtensive.Core;

using DotNetNotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute;
using JBNotNullAttribute = JetBrains.Annotations.NotNullAttribute;
using JBCanBeNullAttribute = JetBrains.Annotations.CanBeNullAttribute;

namespace Xtensive.Sorting
{
Expand All @@ -29,6 +31,7 @@ public static class TopologicalSorter
/// Sorting result, if there were no loops;
/// otherwise, <see langword="null"/>.
/// </returns>
[JBCanBeNull]
public static IEnumerable<TNodeItem> Sort<TNodeItem>(IEnumerable<TNodeItem> items, Predicate<TNodeItem, TNodeItem> connector) =>
Sort(items, connector, out List<Node<TNodeItem, object>> loops);

Expand All @@ -43,6 +46,7 @@ public static IEnumerable<TNodeItem> Sort<TNodeItem>(IEnumerable<TNodeItem> item
/// Sorting result, if there were no loops;
/// otherwise, <see langword="null"/>.
/// </returns>
[JBCanBeNull]
public static IReadOnlyList<TNodeItem> SortToList<TNodeItem>(IEnumerable<TNodeItem> items, Predicate<TNodeItem, TNodeItem> connector) =>
SortToList(items, connector, out List<Node<TNodeItem, object>> loops);

Expand All @@ -59,6 +63,7 @@ public static IReadOnlyList<TNodeItem> SortToList<TNodeItem>(IEnumerable<TNodeIt
/// otherwise, <see langword="null"/>.
/// In this case <paramref name="loops"/> will contain only the loop edges.
/// </returns>
[JBCanBeNull]
public static IEnumerable<TNodeItem> Sort<TNodeItem>(
IEnumerable<TNodeItem> items,
Predicate<TNodeItem, TNodeItem> connector,
Expand All @@ -83,6 +88,7 @@ public static IEnumerable<TNodeItem> Sort<TNodeItem>(
/// otherwise, <see langword="null"/>.
/// In this case <paramref name="loops"/> will contain only the loop edges.
/// </returns>
[JBCanBeNull]
public static IReadOnlyList<TNodeItem> SortToList<TNodeItem>(
IEnumerable<TNodeItem> items,
Predicate<TNodeItem, TNodeItem> connector,
Expand All @@ -105,6 +111,8 @@ public static IReadOnlyList<TNodeItem> SortToList<TNodeItem>(
/// <returns>
/// Sorting result
/// </returns>
[return: DotNetNotNull]
[JBNotNull]
public static IEnumerable<TNodeItem> Sort<TNodeItem>(
IEnumerable<TNodeItem> items,
Predicate<TNodeItem, TNodeItem> connector,
Expand All @@ -121,6 +129,8 @@ public static IEnumerable<TNodeItem> Sort<TNodeItem>(
/// <returns>
/// Sorting result
/// </returns>
[return: DotNetNotNull]
[JBNotNull]
public static IReadOnlyList<TNodeItem> SortToList<TNodeItem>(
IEnumerable<TNodeItem> items,
Predicate<TNodeItem, TNodeItem> connector,
Expand All @@ -138,6 +148,8 @@ public static IReadOnlyList<TNodeItem> SortToList<TNodeItem>(
/// <returns>
/// Sorting result
/// </returns>
[return: DotNetNotNull]
[JBNotNull]
public static IEnumerable<TNodeItem> Sort<TNodeItem>(
IEnumerable<TNodeItem> items,
Predicate<TNodeItem, TNodeItem> connector,
Expand All @@ -161,6 +173,8 @@ public static IEnumerable<TNodeItem> Sort<TNodeItem>(
/// <returns>
/// Sorting result
/// </returns>
[return: DotNetNotNull]
[JBNotNull]
public static IReadOnlyList<TNodeItem> SortToList<TNodeItem>(
IEnumerable<TNodeItem> items,
Predicate<TNodeItem, TNodeItem> connector,
Expand All @@ -181,9 +195,16 @@ public static IReadOnlyList<TNodeItem> SortToList<TNodeItem>(
/// <returns>Sorting result, if there were no loops;
/// otherwise, <see langword="null" />.
/// In this case <paramref name="nodes"/> will contain only the loop edges.</returns>
[JBCanBeNull]
public static IEnumerable<TNodeItem> Sort<TNodeItem, TConnectionItem>(
List<Node<TNodeItem, TConnectionItem>> nodes,
out List<Node<TNodeItem, TConnectionItem>> loops) => SortInternal(nodes, out loops).sorted ?? Array.Empty<TNodeItem>();
out List<Node<TNodeItem, TConnectionItem>> loops)
{
var (sorted, count) = SortInternal(nodes, out loops) /* ?? Array.Empty<TNodeItem>()*/;
return (sorted is not null && count == 0)
? Array.Empty<TNodeItem>()
: sorted;
}

/// <summary>
/// Sorts the specified oriented graph of the nodes in their topological order
Expand All @@ -194,14 +215,17 @@ public static IEnumerable<TNodeItem> Sort<TNodeItem, TConnectionItem>(
/// <returns>Sorting result, if there were no loops;
/// otherwise, <see langword="null" />.
/// In this case <paramref name="nodes"/> will contain only the loop edges.</returns>
[JBCanBeNull]
public static IReadOnlyList<TNodeItem> SortToList<TNodeItem, TConnectionItem>(
List<Node<TNodeItem, TConnectionItem>> nodes,
out List<Node<TNodeItem, TConnectionItem>> loops)
{
var (sorted, count) = SortInternal(nodes, out loops);
return (sorted is null || count == 0)
? Array.Empty<TNodeItem>()
: sorted.ToArray(count);
return (sorted is null)
? null
: count == 0
? Array.Empty<TNodeItem>()
: sorted.ToArray(count);
}

/// <summary>
Expand All @@ -211,6 +235,8 @@ public static IReadOnlyList<TNodeItem> SortToList<TNodeItem, TConnectionItem>(
/// <param name="nodes">The nodes.</param>
/// <param name="removedEdges">Edges removed to make graph non-cyclic.</param>
/// <returns>Sorting result.</returns>
[return: DotNetNotNull]
[JBNotNull]
public static IEnumerable<TNodeItem> Sort<TNodeItem, TConnectionItem>(
IEnumerable<Node<TNodeItem, TConnectionItem>> nodes,
out List<NodeConnection<TNodeItem, TConnectionItem>> removedEdges) =>
Expand All @@ -223,6 +249,8 @@ public static IEnumerable<TNodeItem> Sort<TNodeItem, TConnectionItem>(
/// <param name="nodes">The nodes.</param>
/// <param name="removedEdges">Edges removed to make graph non-cyclic.</param>
/// <returns>Sorting result.</returns>
[return: DotNetNotNull]
[JBNotNull]
public static IReadOnlyList<TNodeItem> SortToList<TNodeItem, TConnectionItem>(
IEnumerable<Node<TNodeItem, TConnectionItem>> nodes,
out List<NodeConnection<TNodeItem, TConnectionItem>> removedEdges) =>
Expand All @@ -236,6 +264,8 @@ public static IReadOnlyList<TNodeItem> SortToList<TNodeItem, TConnectionItem>(
/// <param name="removedEdges">Edges removed to make graph non-cyclic.</param>
/// <param name="removeWholeNode">If <see langword="true"/> removes whole node in the case of loop, otherwise removes only one edge.</param>
/// <returns>Sorting result.</returns>
[return: DotNetNotNull]
[JBNotNull]
public static IEnumerable<TNodeItem> Sort<TNodeItem, TConnectionItem>(
IEnumerable<Node<TNodeItem, TConnectionItem>> nodes,
out List<NodeConnection<TNodeItem, TConnectionItem>> removedEdges,
Expand All @@ -250,6 +280,8 @@ public static IEnumerable<TNodeItem> Sort<TNodeItem, TConnectionItem>(
/// <param name="removedEdges">Edges removed to make graph non-cyclic.</param>
/// <param name="removeWholeNode">If <see langword="true"/> removes whole node in the case of loop, otherwise removes only one edge.</param>
/// <returns>Sorting result.</returns>
[return: DotNetNotNull]
[JBNotNull]
public static IReadOnlyList<TNodeItem> SortToList<TNodeItem, TConnectionItem>(
IEnumerable<Node<TNodeItem, TConnectionItem>> nodes,
out List<NodeConnection<TNodeItem, TConnectionItem>> removedEdges,
Expand Down