Skip to content

Commit c79489c

Browse files
committed
Apply filters for entity joins
1 parent 7530a25 commit c79489c

File tree

7 files changed

+293
-39
lines changed

7 files changed

+293
-39
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System.Linq;
12+
using NHibernate.Cfg.MappingSchema;
13+
using NHibernate.Criterion;
14+
using NHibernate.Mapping.ByCode;
15+
using NUnit.Framework;
16+
17+
namespace NHibernate.Test.NHSpecificTest.GH2330
18+
{
19+
using System.Threading.Tasks;
20+
[TestFixture]
21+
public class JoinedSubclassWithClauseFixtureAsync : TestCaseMappingByCode
22+
{
23+
private object _visit1Id;
24+
private object _visit2Id;
25+
26+
protected override HbmMapping GetMappings()
27+
{
28+
var mapper = new ModelMapper();
29+
30+
mapper.Class<Node>(ca =>
31+
{
32+
ca.Id(x => x.Id, map => map.Generator(Generators.Identity));
33+
ca.Property(x => x.Deleted);
34+
ca.Property(x => x.FamilyName);
35+
ca.Table("Node");
36+
ca.Abstract(true);
37+
});
38+
39+
mapper.JoinedSubclass<PersonBase>(
40+
ca =>
41+
{
42+
ca.Key(x => x.Column("FK_Node_ID"));
43+
ca.Extends(typeof(Node));
44+
ca.Property(x => x.Deleted);
45+
ca.Property(x => x.Login);
46+
});
47+
48+
mapper.Class<UserEntityVisit>(
49+
ca =>
50+
{
51+
ca.Id(x => x.Id, map => map.Generator(Generators.Identity));
52+
ca.Property(x => x.Deleted);
53+
ca.ManyToOne(x => x.PersonBase);
54+
});
55+
56+
return mapper.CompileMappingForAllExplicitlyAddedEntities();
57+
}
58+
59+
protected override void OnSetUp()
60+
{
61+
using (var arrangeSession = OpenSession())
62+
using (var tx = arrangeSession.BeginTransaction())
63+
{
64+
var person = new PersonBase {Login = "dave", FamilyName = "grohl"};
65+
arrangeSession.Save(person);
66+
_visit1Id = arrangeSession.Save(new UserEntityVisit {PersonBase = person});
67+
_visit2Id = arrangeSession.Save(new UserEntityVisit {PersonBase = person});
68+
arrangeSession.Flush();
69+
70+
tx.Commit();
71+
}
72+
}
73+
74+
protected override void OnTearDown()
75+
{
76+
using (var session = OpenSession())
77+
using (var transaction = session.BeginTransaction())
78+
{
79+
session.Delete("from System.Object");
80+
81+
transaction.Commit();
82+
}
83+
}
84+
85+
[Test]
86+
public async Task Join_InheritanceAsync()
87+
{
88+
using(new SqlLogSpy())
89+
using (var session = OpenSession())
90+
using (session.BeginTransaction())
91+
{
92+
var results = (await (session
93+
.CreateCriteria<UserEntityVisit>()
94+
.CreateCriteria(
95+
$"{nameof(UserEntityVisit.PersonBase)}",
96+
"f",
97+
SqlCommand.JoinType.LeftOuterJoin,
98+
Restrictions.Eq("Deleted", false))
99+
.ListAsync<UserEntityVisit>()))
100+
.Select(x => x.Id);
101+
102+
Assert.That(results, Is.EquivalentTo(new[] {_visit1Id, _visit2Id,}));
103+
}
104+
}
105+
106+
[Test]
107+
public async Task Join_Inheritance_QueryOverAsync()
108+
{
109+
using (var session = OpenSession())
110+
using (session.BeginTransaction())
111+
{
112+
PersonBase f = null;
113+
var results = (await (session.QueryOver<UserEntityVisit>()
114+
.JoinAlias(
115+
x => x.PersonBase,
116+
() => f,
117+
SqlCommand.JoinType.LeftOuterJoin,
118+
Restrictions.Where(() => f.Deleted == false))
119+
.ListAsync()))
120+
.Select(x => x.Id);
121+
122+
Assert.That(results, Is.EquivalentTo(new[] {_visit1Id, _visit2Id,}));
123+
}
124+
}
125+
}
126+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System.Linq;
12+
using NUnit.Framework;
13+
using NHibernate.Linq;
14+
15+
namespace NHibernate.Test.NHSpecificTest.GH2549
16+
{
17+
using System.Threading.Tasks;
18+
[TestFixture]
19+
public class FixtureAsync : BugTestCase
20+
{
21+
protected override void OnSetUp()
22+
{
23+
base.OnSetUp();
24+
using (var session = OpenSession())
25+
using (var tx = session.BeginTransaction())
26+
{
27+
var p = new Person {Id = 1, Name = "Name"};
28+
session.Save(p);
29+
var ic = new Customer {Deleted = false, Name = "Name", Id = 1};
30+
session.Save(ic);
31+
var dc = new Customer {Deleted = true, Name = "Name", Id = 2};
32+
session.Save(dc);
33+
34+
tx.Commit();
35+
}
36+
}
37+
38+
protected override void OnTearDown()
39+
{
40+
base.OnTearDown();
41+
using (var session = OpenSession())
42+
{
43+
session.Delete("from System.Object");
44+
session.Flush();
45+
}
46+
}
47+
48+
[Test]
49+
public async Task EntityJoinFilterAsync()
50+
{
51+
using (var s = OpenSession())
52+
{
53+
var list = await ((from p in s.Query<Person>()
54+
join c in s.Query<Customer>() on p.Name equals c.Name
55+
select p).ToListAsync());
56+
57+
s.EnableFilter("DeletedCustomer").SetParameter("deleted", false);
58+
59+
var filteredList = await ((from p in s.Query<Person>()
60+
join c in s.Query<Customer>() on p.Name equals c.Name
61+
select p).ToListAsync());
62+
63+
Assert.That(list, Has.Count.EqualTo(2));
64+
Assert.That(filteredList, Has.Count.EqualTo(1));
65+
}
66+
}
67+
}
68+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System.Linq;
2+
using NUnit.Framework;
3+
4+
namespace NHibernate.Test.NHSpecificTest.GH2549
5+
{
6+
[TestFixture]
7+
public class Fixture : BugTestCase
8+
{
9+
protected override void OnSetUp()
10+
{
11+
base.OnSetUp();
12+
using (var session = OpenSession())
13+
using (var tx = session.BeginTransaction())
14+
{
15+
var p = new Person {Id = 1, Name = "Name"};
16+
session.Save(p);
17+
var ic = new Customer {Deleted = false, Name = "Name", Id = 1};
18+
session.Save(ic);
19+
var dc = new Customer {Deleted = true, Name = "Name", Id = 2};
20+
session.Save(dc);
21+
22+
tx.Commit();
23+
}
24+
}
25+
26+
protected override void OnTearDown()
27+
{
28+
base.OnTearDown();
29+
using (var session = OpenSession())
30+
{
31+
session.Delete("from System.Object");
32+
session.Flush();
33+
}
34+
}
35+
36+
[Test]
37+
public void EntityJoinFilter()
38+
{
39+
using (var s = OpenSession())
40+
{
41+
var list = (from p in s.Query<Person>()
42+
join c in s.Query<Customer>() on p.Name equals c.Name
43+
select p).ToList();
44+
45+
s.EnableFilter("DeletedCustomer").SetParameter("deleted", false);
46+
47+
var filteredList = (from p in s.Query<Person>()
48+
join c in s.Query<Customer>() on p.Name equals c.Name
49+
select p).ToList();
50+
51+
Assert.That(list, Has.Count.EqualTo(2));
52+
Assert.That(filteredList, Has.Count.EqualTo(1));
53+
}
54+
}
55+
}
56+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test"
3+
namespace="NHibernate.Test.NHSpecificTest.GH2549" >
4+
5+
<class name="Customer">
6+
<id name="Id">
7+
<generator class="assigned" />
8+
</id>
9+
<property name="Name" />
10+
<property name="Deleted" type="Boolean" not-null="true" />
11+
12+
<filter name="DeletedCustomer" condition="Deleted = :deleted" />
13+
</class>
14+
15+
<class name="Person">
16+
<id name="Id">
17+
<generator class="assigned" />
18+
</id>
19+
<property name="Name" />
20+
</class>
21+
22+
<filter-def name="DeletedCustomer">
23+
<filter-param name="deleted" type="Boolean"/>
24+
</filter-def>
25+
26+
</hibernate-mapping>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace NHibernate.Test.NHSpecificTest.GH2549
2+
{
3+
public class Customer
4+
{
5+
public virtual int Id { get; set; }
6+
public virtual bool Deleted { get; set; }
7+
public virtual string Name { get; set; }
8+
}
9+
10+
public class Person
11+
{
12+
public virtual int Id { get; set; }
13+
public virtual string Name { get; set; }
14+
}
15+
}

src/NHibernate/Hql/Ast/ANTLR/Tree/EntityJoinFromElement.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ public EntityJoinFromElement(FromClause fromClause, IQueryable entityPersister,
1818
JoinSequence = new EntityJoinJoinSequenceImpl(
1919
SessionFactoryHelper.Factory,
2020
entityType,
21-
entityPersister.TableName,
2221
tableAlias,
2322
joinType);
2423

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
32
using NHibernate.Engine;
43
using NHibernate.SqlCommand;
54
using NHibernate.Type;
@@ -8,44 +7,9 @@ namespace NHibernate.Hql.Ast.ANTLR.Tree
87
{
98
class EntityJoinJoinSequenceImpl : JoinSequence
109
{
11-
private readonly EntityType _entityType;
12-
private readonly string _tableName;
13-
private readonly string _tableAlias;
14-
private readonly JoinType _joinType;
15-
16-
public EntityJoinJoinSequenceImpl(ISessionFactoryImplementor factory, EntityType entityType, string tableName, string tableAlias, JoinType joinType):base(factory)
10+
public EntityJoinJoinSequenceImpl(ISessionFactoryImplementor factory, EntityType entityType, string tableAlias, JoinType joinType):base(factory)
1711
{
18-
_entityType = entityType;
19-
_tableName = tableName;
20-
_tableAlias = tableAlias;
21-
_joinType = joinType;
22-
}
23-
24-
internal override JoinFragment ToJoinFragment(
25-
IDictionary<string, IFilter> enabledFilters,
26-
bool includeExtraJoins,
27-
SqlString withClauseFragment,
28-
string withClauseJoinAlias,
29-
string withRootAlias)
30-
{
31-
var joinFragment = new ANSIJoinFragment();
32-
33-
var on = withClauseFragment ?? SqlString.Empty;
34-
//Note: filters logic commented due to following issues
35-
//1) Original code is non functional as SqlString is immutable and so all Append results are lost. Correct code would look like: on = on.Append(filters);
36-
//2) Also it seems GetOnCondition always returns empty string for entity join (as IsReferenceToPrimaryKey is always true).
37-
// So if filters for entity join really make sense we need to inline GetOnCondition part that retrieves filters
38-
// var filters = _entityType.GetOnCondition(_tableAlias, Factory, enabledFilters);
39-
// if (!string.IsNullOrEmpty(filters))
40-
// {
41-
// on.Append(" and ").Append(filters);
42-
// }
43-
joinFragment.AddJoin(_tableName, _tableAlias, Array.Empty<string>(), Array.Empty<string>(), _joinType, on);
44-
if (includeExtraJoins)
45-
{
46-
AddExtraJoins(joinFragment, _tableAlias, _entityType.GetAssociatedJoinable(Factory), _joinType == JoinType.InnerJoin);
47-
}
48-
return joinFragment;
12+
AddJoin(entityType, tableAlias, joinType, Array.Empty<string>());
4913
}
5014
}
5115
}

0 commit comments

Comments
 (0)