Skip to content

Commit 2f66408

Browse files
committed
Attempt to optimize restriction search logic
1 parent de8caf0 commit 2f66408

File tree

2 files changed

+31
-33
lines changed

2 files changed

+31
-33
lines changed

src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -292,17 +292,14 @@ public bool CanAddFetchedCollectionToCache
292292
{
293293
get
294294
{
295-
foreach (var collectionFetch in CollectionFetches)
295+
foreach (FromElement fromElement in CollectionFetches)
296296
{
297-
var fromElement = collectionFetch as FromElement;
298-
var hasCache =
299-
fromElement?.QueryableCollection != null &&
300-
fromElement.QueryableCollection.HasCache;
297+
var hasCache = fromElement.QueryableCollection.HasCache;
301298

302299
if (!hasCache)
303300
continue;
304301

305-
if (ContainsRestrictionOnTable(fromElement.TableAlias))
302+
if (ContainsRestrictionOnTable(fromElement))
306303
return false;
307304
}
308305

@@ -452,34 +449,12 @@ private void ErrorIfDML()
452449
}
453450
}
454451

455-
private bool ContainsRestrictionOnTable(string tableAlias)
452+
private bool ContainsRestrictionOnTable(FromElement fromElement)
456453
{
457454
var whereClause = ((QueryNode) _sqlAst).WhereClause;
458-
if (whereClause == null)
459-
return false;
460-
461-
var tableAliasWithDot = tableAlias + ".";
462-
var stack = new Stack<IASTNode>();
463-
for (var i = 0; i < whereClause.ChildCount; i++)
464-
{
465-
stack.Push(whereClause.GetChild(i));
466-
while (stack.Count != 0)
467-
{
468-
var child = stack.Pop();
469-
if (child.ChildCount > 0)
470-
{
471-
//We're iterating from count to 0 because it is more common to put restricting column as a left operand.
472-
//e.g WHERE fetchedCollectionAlias.Column = 1. Now we put on stack first '1' and then 'fetchedCollectionAlias.Column'
473-
//so 'fetchedCollectionAlias.Column' will be on top.
474-
for (var j = child.ChildCount - 1; j >= 0; j--)
475-
stack.Push(child.GetChild(j));
476-
}
477-
else if (child.Text.StartsWith(tableAliasWithDot, StringComparison.Ordinal))
478-
return true;
479-
}
480-
}
481-
482-
return false;
455+
//Iterate over all nodes of type FromReferenceNode (but don't go inside FromReferenceNode with defined FromElement)
456+
return ASTUtil.IterateChildrenOfType<FromReferenceNode>(whereClause, skipSearchInChildrenWhen: node => node.FromElement != null)
457+
.Any(rn => rn.FromElement == fromElement);
483458
}
484459

485460
private IList<IASTNode> CollectionFetches

src/NHibernate/Hql/Ast/ANTLR/Util/ASTUtil.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,28 @@ public static IList<IASTNode> CollectChildren(IASTNode root, FilterPredicate pre
103103
{
104104
return new CollectingNodeVisitor(predicate).Collect(root);
105105
}
106+
107+
/// <summary>
108+
/// Iterates over all children and sub-children and finds elements of required type.
109+
/// </summary>
110+
internal static IEnumerable<TRequiredType> IterateChildrenOfType<TRequiredType>(IASTNode root, Func<TRequiredType, bool> skipSearchInChildrenWhen)
111+
{
112+
foreach(var child in root)
113+
{
114+
bool searchInChildren = true;
115+
if (child is TRequiredType typedChild)
116+
{
117+
searchInChildren = !skipSearchInChildrenWhen(typedChild);
118+
yield return typedChild;
119+
}
120+
if(searchInChildren)
121+
{
122+
foreach (var subChild in IterateChildrenOfType(child, skipSearchInChildrenWhen))
123+
{
124+
yield return subChild;
125+
}
126+
}
127+
}
128+
}
106129
}
107-
}
130+
}

0 commit comments

Comments
 (0)