Skip to content

Commit f633248

Browse files
bahusoidhazzik
authored andcommitted
Skip Topological sorting if not required (#2006)
* Move dependent alias calculation to sort method Co-authored-by: Alexander Zaytsev <hazzik@gmail.com>
1 parent 6cb478f commit f633248

File tree

1 file changed

+73
-39
lines changed

1 file changed

+73
-39
lines changed

src/NHibernate/Loader/JoinWalker.cs

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,14 @@ protected virtual bool IsTooManyCollections
115115
get { return false; }
116116
}
117117

118+
//Since v5.3
119+
[Obsolete("This class is not used and will be removed in a future version.")]
118120
public class DependentAlias
119121
{
120122
public string Alias { get; set; }
121123
public string[] DependsOn { get; set; }
122124
}
123125

124-
readonly List<DependentAlias> _dependentAliases = new List<DependentAlias>();
125-
126126
protected JoinWalker(ISessionFactoryImplementor factory, IDictionary<string, IFilter> enabledFilters)
127127
{
128128
this.factory = factory;
@@ -181,7 +181,7 @@ private void AddAssociationToJoinTree(IAssociationType type, string[] aliasedLhs
181181
enabledFilters,
182182
GetSelectMode(path));
183183
assoc.ValidateJoin(path);
184-
AddAssociation(subalias, assoc);
184+
AddAssociation(assoc);
185185

186186
int nextDepth = currentDepth + 1;
187187

@@ -204,10 +204,25 @@ protected virtual SelectMode GetSelectMode(string path)
204204
return SelectMode.Undefined;
205205
}
206206

207-
private static int[] GetTopologicalSortOrder(List<DependentAlias> fields)
207+
private struct DependentAlias2
208+
{
209+
public DependentAlias2(string alias, ICollection<string> dependsOn)
210+
{
211+
Alias = alias;
212+
DependsOn = dependsOn;
213+
}
214+
215+
public string Alias { get; }
216+
public ICollection<string> DependsOn { get; }
217+
}
218+
219+
/// <summary>
220+
/// Returns list of indexes in sorted order
221+
/// </summary>
222+
private static int[] GetTopologicalSortOrder(IList<DependentAlias2> fields)
208223
{
209224
TopologicalSorter g = new TopologicalSorter(fields.Count);
210-
Dictionary<string, int> indexes = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
225+
Dictionary<string, int> indexes = new Dictionary<string, int>(fields.Count, StringComparer.OrdinalIgnoreCase);
211226

212227
// add vertices
213228
for (int i = 0; i < fields.Count; i++)
@@ -218,14 +233,12 @@ private static int[] GetTopologicalSortOrder(List<DependentAlias> fields)
218233
// add edges
219234
for (int i = 0; i < fields.Count; i++)
220235
{
221-
var dependentAlias = fields[i];
222-
if (dependentAlias.DependsOn != null)
236+
var dependentFields = fields[i].DependsOn;
237+
if (dependentFields != null)
223238
{
224-
for (int j = 0; j < dependentAlias.DependsOn.Length; j++)
239+
foreach (var dependentField in dependentFields)
225240
{
226-
var dependentField = dependentAlias.DependsOn[j];
227-
int end;
228-
if (indexes.TryGetValue(dependentField, out end))
241+
if (indexes.TryGetValue(dependentField, out var end))
229242
{
230243
g.AddEdge(i, end);
231244
}
@@ -236,31 +249,40 @@ private static int[] GetTopologicalSortOrder(List<DependentAlias> fields)
236249
return g.Sort();
237250
}
238251

239-
/// <summary>
240-
/// Adds an association and extracts the aliases the association's 'with clause' is dependent on
241-
/// </summary>
242-
private void AddAssociation(string subalias, OuterJoinableAssociation association)
252+
private static List<DependentAlias2> GetDependentAliases(IList<OuterJoinableAssociation> associations)
243253
{
244-
var dependentAlias = new DependentAlias
254+
var dependentAliases = new List<DependentAlias2>(associations.Count);
255+
foreach (var association in associations)
245256
{
246-
Alias = subalias,
247-
};
248-
_dependentAliases.Add(dependentAlias);
257+
dependentAliases.Add(new DependentAlias2(association.RHSAlias, GetDependsOn(association)));
258+
}
249259

250-
var on = association.On.ToString();
251-
if (!string.IsNullOrEmpty(on))
260+
return dependentAliases;
261+
}
262+
263+
private static HashSet<string> GetDependsOn(OuterJoinableAssociation association)
264+
{
265+
if (SqlStringHelper.IsEmpty(association.On))
266+
return null;
267+
268+
var dependencies = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
269+
foreach (Match match in aliasRegex.Matches(association.On.ToString()))
252270
{
253-
var dependencies = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
254-
foreach (Match match in aliasRegex.Matches(on))
255-
{
256-
string alias = match.Value;
257-
if (string.Equals(alias, subalias, StringComparison.OrdinalIgnoreCase))
258-
continue;
259-
dependencies.Add(alias);
260-
}
261-
dependentAlias.DependsOn = dependencies.ToArray();
271+
string alias = match.Value;
272+
if (string.Equals(alias, association.RHSAlias, StringComparison.OrdinalIgnoreCase))
273+
continue;
274+
275+
dependencies.Add(alias);
262276
}
263277

278+
return dependencies;
279+
}
280+
281+
/// <summary>
282+
/// Adds an association
283+
/// </summary>
284+
private void AddAssociation(OuterJoinableAssociation association)
285+
{
264286
associations.Add(association);
265287
}
266288

@@ -360,7 +382,7 @@ internal void AddExplicitEntityJoinAssociation(
360382
Factory,
361383
enabledFilters,
362384
GetSelectMode(path));
363-
AddAssociation(tableAlias, assoc);
385+
AddAssociation(assoc);
364386
}
365387

366388
private void WalkEntityAssociationTree(IAssociationType associationType, IOuterJoinLoadable persister,
@@ -799,16 +821,9 @@ protected SqlString MergeOrderings(string ass, string orderBy) {
799821
/// </summary>
800822
protected JoinFragment MergeOuterJoins(IList<OuterJoinableAssociation> associations)
801823
{
802-
IList<OuterJoinableAssociation> sortedAssociations = new List<OuterJoinableAssociation>();
803-
804-
var indices = GetTopologicalSortOrder(_dependentAliases);
805-
for (int index = indices.Length - 1; index >= 0; index--)
806-
{
807-
sortedAssociations.Add(associations[indices[index]]);
808-
}
809-
810824
JoinFragment outerjoin = Dialect.CreateOuterJoinFragment();
811825

826+
var sortedAssociations = GetSortedAssociations(associations);
812827
OuterJoinableAssociation last = null;
813828
foreach (OuterJoinableAssociation oj in sortedAssociations)
814829
{
@@ -840,6 +855,25 @@ protected JoinFragment MergeOuterJoins(IList<OuterJoinableAssociation> associati
840855
return outerjoin;
841856
}
842857

858+
private static IList<OuterJoinableAssociation> GetSortedAssociations(IList<OuterJoinableAssociation> associations)
859+
{
860+
if (associations.Count < 2)
861+
return associations;
862+
863+
var fields = GetDependentAliases(associations);
864+
if (!fields.Exists(a => a.DependsOn?.Count > 0))
865+
return associations;
866+
867+
var indexes = GetTopologicalSortOrder(fields);
868+
var sortedAssociations = new List<OuterJoinableAssociation>(associations.Count);
869+
for (int index = indexes.Length - 1; index >= 0; index--)
870+
{
871+
sortedAssociations.Add(associations[indexes[index]]);
872+
}
873+
874+
return sortedAssociations;
875+
}
876+
843877
/// <summary>
844878
/// Count the number of instances of IJoinable which are actually
845879
/// also instances of ILoadable, or are one-to-many associations

0 commit comments

Comments
 (0)