Skip to content

Commit cdeb20d

Browse files
author
mika
committed
fixes the generation of Collection-Filters on a JoinedSubclass
1 parent 4a21b51 commit cdeb20d

File tree

8 files changed

+73
-16
lines changed

8 files changed

+73
-16
lines changed

src/NHibernate.DomainModel/Async/CustomPersister.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
using System;
1212
using System.Collections;
13+
using System.Collections.Generic;
1314
using NHibernate.Cache;
1415
using NHibernate.Cache.Entry;
1516
using NHibernate.Engine;

src/NHibernate.DomainModel/CustomPersister.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections;
3+
using System.Collections.Generic;
34
using NHibernate.Cache;
45
using NHibernate.Cache.Entry;
56
using NHibernate.Engine;
@@ -519,6 +520,14 @@ public IComparer VersionComparator
519520

520521
public IEntityTuplizer EntityTuplizer => null;
521522

523+
524+
public FilterHelper FilterHelper => throw new NotSupportedException();
525+
526+
public string FilterFragment(string alias, IDictionary<string, IFilter> enabledFilters)
527+
{
528+
throw new NotSupportedException();
529+
}
530+
522531
#endregion
523532
}
524533
}

src/NHibernate/Async/Persister/Entity/IEntityPersister.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace NHibernate.Persister.Entity
2626
using System.Threading.Tasks;
2727
using System.Threading;
2828

29-
public partial interface IEntityPersister : IOptimisticCacheSource
29+
public partial interface IEntityPersister : IFilterable, IOptimisticCacheSource
3030
{
3131

3232
#region stuff that is persister-centric and/or EntityInfo-centric

src/NHibernate/Persister/Collection/AbstractCollectionPersister.cs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public abstract partial class AbstractCollectionPersister : ICollectionMetadata,
131131
private readonly ICacheEntryStructure cacheEntryStructure;
132132

133133
// dynamic filters for the collection
134-
private readonly FilterHelper filterHelper;
134+
public FilterHelper FilterHelper { get; }
135135

136136
#region Dynamic filters specifically for many-to-many inside the collection
137137

@@ -513,7 +513,7 @@ public AbstractCollectionPersister(Mapping.Collection collection, ICacheConcurre
513513
}
514514

515515
// Handle any filters applied to this collection
516-
filterHelper = new FilterHelper(collection.FilterMap, dialect, factory.SQLFunctionRegistry);
516+
FilterHelper = new FilterHelper(collection.FilterMap, dialect, factory.SQLFunctionRegistry);
517517

518518
// Handle any filters applied to this collection for many-to-many
519519
manyToManyFilterHelper = new FilterHelper(collection.ManyToManyFilterMap, dialect, factory.SQLFunctionRegistry);
@@ -1471,10 +1471,41 @@ protected virtual string FilterFragment(string alias)
14711471
return HasWhere ? " and " + GetSQLWhereString(alias) : "";
14721472
}
14731473

1474+
/// <summary>
1475+
/// Get the where clause filter, given a query alias and considering enabled session filters.
1476+
///
1477+
/// When an <see cref="IEntityPersister"/> is set, the filter generated by the persister is returned. This ensures
1478+
/// that a proper filter is also generated for subclass hierarchy relations.
1479+
/// </summary>
1480+
/// <param name="alias"></param>
1481+
/// <param name="enabledFilters"></param>
1482+
/// <returns></returns>
14741483
public virtual string FilterFragment(string alias, IDictionary<string, IFilter> enabledFilters)
14751484
{
1485+
if(!enabledFilters.Any())
1486+
{
1487+
// no filters enabled
1488+
// but a potential where condition needs to be handled properly
1489+
return FilterFragment(alias);
1490+
}
1491+
1492+
if(!FilterHelper.IsAffectedBy(enabledFilters))
1493+
{
1494+
// the collection filters don't match with the enabled filters
1495+
// but a potential where condition needs to be handled properly
1496+
return FilterFragment(alias);
1497+
}
1498+
1499+
if(ElementPersister != null &&
1500+
ElementPersister.FilterHelper.IsAffectedBy(enabledFilters))
1501+
{
1502+
// forward filter generation to persister when it is affected by the filter
1503+
return ElementPersister.FilterFragment(alias, enabledFilters);
1504+
}
1505+
1506+
// default handling
14761507
StringBuilder sessionFilterFragment = new StringBuilder();
1477-
filterHelper.Render(sessionFilterFragment, alias, enabledFilters);
1508+
FilterHelper.Render(sessionFilterFragment, alias, enabledFilters);
14781509

14791510
return sessionFilterFragment.Append(FilterFragment(alias)).ToString();
14801511
}
@@ -1494,7 +1525,7 @@ public override string ToString()
14941525
public bool IsAffectedByEnabledFilters(ISessionImplementor session)
14951526
{
14961527
return
1497-
filterHelper.IsAffectedBy(session.EnabledFilters)
1528+
FilterHelper.IsAffectedBy(session.EnabledFilters)
14981529
|| (IsManyToMany && manyToManyFilterHelper.IsAffectedBy(session.EnabledFilters));
14991530
}
15001531

src/NHibernate/Persister/Entity/AbstractEntityPersister.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ public virtual void BindValues(DbCommand ps)
199199

200200
#region Dynamic filters attached to the class-level
201201

202-
private readonly FilterHelper filterHelper;
202+
public FilterHelper FilterHelper { get; }
203203

204204
#endregion
205205

@@ -516,7 +516,7 @@ protected AbstractEntityPersister(PersistentClass persistentClass, ICacheConcurr
516516
#endregion
517517

518518
// Handle any filters applied to the class level
519-
filterHelper = new FilterHelper(persistentClass.FilterMap, factory.Dialect, factory.SQLFunctionRegistry);
519+
FilterHelper = new FilterHelper(persistentClass.FilterMap, factory.Dialect, factory.SQLFunctionRegistry);
520520

521521
temporaryIdTableName = persistentClass.TemporaryIdTableName;
522522
temporaryIdTableDDL = persistentClass.TemporaryIdTableDDL;
@@ -3666,11 +3666,11 @@ protected void LogStaticSQL()
36663666
public virtual string FilterFragment(string alias, IDictionary<string, IFilter> enabledFilters)
36673667
{
36683668
var filterFragment = FilterFragment(alias);
3669-
if (!filterHelper.IsAffectedBy(enabledFilters))
3669+
if (!FilterHelper.IsAffectedBy(enabledFilters))
36703670
return filterFragment;
36713671

36723672
var sessionFilterFragment = new StringBuilder();
3673-
filterHelper.Render(sessionFilterFragment, GenerateFilterConditionAlias(alias), GetColumnsToTableAliasMap(alias), enabledFilters);
3673+
FilterHelper.Render(sessionFilterFragment, GenerateFilterConditionAlias(alias), GetColumnsToTableAliasMap(alias), enabledFilters);
36743674
return sessionFilterFragment.Append(filterFragment).ToString();
36753675
}
36763676

src/NHibernate/Persister/Entity/IEntityPersister.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public struct EntityPersister
2626
/// Implementors must be threadsafe (preferably immutable) and must provide a constructor of type
2727
/// matching the signature of: (PersistentClass, SessionFactoryImplementor)
2828
/// </remarks>
29-
public partial interface IEntityPersister : IOptimisticCacheSource
29+
public partial interface IEntityPersister : IFilterable, IOptimisticCacheSource
3030
{
3131
/// <summary>
3232
/// The ISessionFactory to which this persister "belongs".
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Collections.Generic;
2+
using NHibernate.Util;
3+
4+
namespace NHibernate.Persister.Entity
5+
{
6+
/// <summary>
7+
/// Defines a contract for filtering entities implemented by persisters.
8+
/// </summary>
9+
public interface IFilterable
10+
{
11+
FilterHelper FilterHelper { get; }
12+
13+
/// <summary>
14+
/// Get the where clause filter, given a query alias and considering enabled session filters.
15+
/// </summary>
16+
/// <param name="alias"></param>
17+
/// <param name="enabledFilters"></param>
18+
/// <returns></returns>
19+
string FilterFragment(string alias, IDictionary<string, IFilter> enabledFilters);
20+
}
21+
}

src/NHibernate/Persister/Entity/IJoinable.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace NHibernate.Persister.Entity
77
/// <summary>
88
/// Anything that can be loaded by outer join - namely persisters for classes or collections.
99
/// </summary>
10-
public interface IJoinable
10+
public interface IJoinable: IFilterable
1111
{
1212
// Should this interface extend PropertyMapping?
1313

@@ -65,11 +65,6 @@ string SelectFragment(IJoinable rhs, string rhsAlias, string lhsAlias, string cu
6565
/// <returns></returns>
6666
SqlString FromJoinFragment(string alias, bool innerJoin, bool includeSubclasses);
6767

68-
/// <summary>
69-
/// Get the where clause filter, given a query alias and considering enabled session filters
70-
/// </summary>
71-
string FilterFragment(string alias, IDictionary<string, IFilter> enabledFilters);
72-
7368
string OneToManyFilterFragment(string alias);
7469

7570
/// <summary>

0 commit comments

Comments
 (0)