Skip to content

Optimize filter applying logic #2295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 27, 2019
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
48 changes: 24 additions & 24 deletions src/NHibernate/Persister/Entity/AbstractEntityPersister.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2148,13 +2148,18 @@ public string GenerateTableAlias(string rootAlias, int tableNumber)
if (tableNumber == 0)
return rootAlias;

StringBuilder buf = new StringBuilder().Append(rootAlias);
if (!rootAlias.EndsWith("_"))
{
buf.Append('_');
}
string x = rootAlias.EndsWith('_')
? string.Empty
: "_";
return string.Concat(rootAlias, x, tableNumber.ToString(), "_");
}

return buf.Append(tableNumber).Append('_').ToString();
private string GetSubclassAliasedColumn(string rootAlias, int tableNumber, string columnName)
{
if (string.IsNullOrEmpty(rootAlias))
return columnName;

return GenerateTableAlias(rootAlias, tableNumber) + "." + columnName;
}

public string[] ToColumns(string name, int i)
Expand Down Expand Up @@ -3655,16 +3660,21 @@ protected void LogStaticSQL()

public virtual string FilterFragment(string alias, IDictionary<string, IFilter> enabledFilters)
{
StringBuilder sessionFilterFragment = new StringBuilder();
var filterFragment = FilterFragment(alias);
if (!filterHelper.IsAffectedBy(enabledFilters))
return filterFragment;

var sessionFilterFragment = new StringBuilder();
filterHelper.Render(sessionFilterFragment, GenerateFilterConditionAlias(alias), GetColumnsToTableAliasMap(alias), enabledFilters);

return sessionFilterFragment.Append(FilterFragment(alias)).ToString();
return sessionFilterFragment.Append(filterFragment).ToString();
}

private IDictionary<string, string> GetColumnsToTableAliasMap(string rootAlias)
{
IDictionary<PropertyKey, string> propDictionary = new Dictionary<PropertyKey, string>();
if (SubclassTableSpan < 2)
return CollectionHelper.EmptyDictionary<string, string>();

var propDictionary = new Dictionary<PropertyKey, string>();
for (int i =0; i < SubclassPropertyNameClosure.Length; i++)
{
string property = SubclassPropertyNameClosure[i];
Expand All @@ -3677,20 +3687,11 @@ private IDictionary<string, string> GetColumnsToTableAliasMap(string rootAlias)
}
}

IDictionary<string, string> dict = new Dictionary<string, string>();
var dict = new Dictionary<string, string>();
for (int i = 0; i < SubclassColumnTableNumberClosure.Length; i++ )
{
string fullColumn;
string col = SubclassColumnClosure[i];
if (!string.IsNullOrEmpty(rootAlias))
{
string alias = GenerateTableAlias(rootAlias, SubclassColumnTableNumberClosure[i]);
fullColumn = string.Format("{0}.{1}", alias, col);
}
else
{
fullColumn = col;
}
var fullColumn = GetSubclassAliasedColumn(rootAlias, SubclassColumnTableNumberClosure[i], col);

PropertyKey key = new PropertyKey(col, SubclassColumnTableNumberClosure[i]);
if (propDictionary.ContainsKey(key))
Expand All @@ -3709,8 +3710,7 @@ private IDictionary<string, string> GetColumnsToTableAliasMap(string rootAlias)
{
foreach (var key in GetSubclassTableKeyColumns(i))
{
var alias = i == 0 ? rootAlias : GenerateTableAlias(rootAlias, i);
dict[key] = $"{alias}.{key}";
dict[key] = GetSubclassAliasedColumn(rootAlias, i, key);
}
}

Expand Down Expand Up @@ -3753,7 +3753,7 @@ public virtual string OneToManyFilterFragment(string alias)
public virtual SqlString FromJoinFragment(string alias, bool innerJoin, bool includeSubclasses)
{
return SubclassTableSpan == 1
? new SqlString(string.Empty) // just a performance opt!
? SqlString.Empty // just a performance opt!
: CreateJoin(alias, innerJoin, includeSubclasses).ToFromFragmentString;
}

Expand Down
36 changes: 15 additions & 21 deletions src/NHibernate/Util/FilterHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,50 +55,44 @@ public string Render(String alias, IDictionary<string, IFilter> enabledFilters)

public void Render(StringBuilder buffer, string alias, IDictionary<string, IFilter> enabledFilters)
{
Render(buffer, alias, new Dictionary<string, string>(), enabledFilters);
Render(buffer, alias, CollectionHelper.EmptyDictionary<string, string>(), enabledFilters);
}

public void Render(StringBuilder buffer, string defaultAlias, IDictionary<string, string> propMap, IDictionary<string, IFilter> enabledFilters)
{
if (filterNames != null)
for (int i = 0; i < filterNames.Length; i++)
{
int max = filterNames.Length;
if (max > 0)
if (enabledFilters.ContainsKey(filterNames[i]))
{
for (int i = 0; i < max; i++)
string condition = filterConditions[i];
if (!string.IsNullOrEmpty(condition))
{
if (enabledFilters.ContainsKey(filterNames[i]))
{
string condition = filterConditions[i];
if (StringHelper.IsNotEmpty(condition))
{
buffer.Append(" and ");
AddFilterString(buffer, defaultAlias, propMap, condition);
}
}
buffer.Append(" and ");
AddFilterString(buffer, defaultAlias, propMap, condition);
}
}
}
}

private static void AddFilterString(StringBuilder buffer, string defaultAlias, IDictionary<string, string> propMap, string condition)
{
int i = condition.IndexOf(FilterImpl.MARKER);
int i;
int upTo = 0;
while (i > -1 && upTo < condition.Length)
while ((i = condition.IndexOf(FilterImpl.MARKER, upTo, StringComparison.Ordinal)) >= 0 && upTo < condition.Length)
{
buffer.Append(condition.Substring(upTo, i - upTo));
buffer.Append(condition, upTo, i - upTo);
int startOfProperty = i + FilterImpl.MARKER.Length + 1;

upTo = condition.IndexOf(" ", startOfProperty);
upTo = condition.IndexOf(' ', startOfProperty);
upTo = upTo >= 0 ? upTo : condition.Length;
string property = condition.Substring(startOfProperty, upTo - startOfProperty);

string fullColumn = propMap.ContainsKey(property) ? propMap[property] : string.Format("{0}.{1}", defaultAlias, property);
if (!propMap.TryGetValue(property, out var fullColumn))
fullColumn = string.IsNullOrEmpty(defaultAlias)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robustness improvement by the way, in case some caller may omit the alias some days? Or an actual bug fix?

Copy link
Member Author

@bahusoid bahusoid Dec 26, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's logic from GetColumnsToTableAliasMap

But now this part is not executed for entities without sub-classes - so I added it here just in case (and for consistency)

? property
: defaultAlias + "." + property;

buffer.Append(fullColumn);

i = condition.IndexOf(FilterImpl.MARKER, upTo);
}
buffer.Append(condition.Substring(upTo));
}
Expand Down