Skip to content

Commit bad8b20

Browse files
authored
Merge pull request #556 from fredericDelaporte/NH-3951
NH-3951 - support of .All as query result. Test cases, fix and refactoring
2 parents 909af9e + 9a5f3c0 commit bad8b20

File tree

7 files changed

+191
-37
lines changed

7 files changed

+191
-37
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace NHibernate.Test.NHSpecificTest.NH3951
5+
{
6+
class Entity
7+
{
8+
public virtual Guid Id { get; set; }
9+
public virtual string Name { get; set; }
10+
public virtual Guid? RelatedId { get; set; }
11+
12+
public virtual ISet<Entity> Related { get; set; }
13+
}
14+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System.Linq;
2+
using NHibernate.Linq;
3+
using NUnit.Framework;
4+
5+
namespace NHibernate.Test.NHSpecificTest.NH3951
6+
{
7+
[TestFixture]
8+
public class Fixture : BugTestCase
9+
{
10+
protected override void OnSetUp()
11+
{
12+
using (ISession session = OpenSession())
13+
using (ITransaction transaction = session.BeginTransaction())
14+
{
15+
var e1 = new Entity {Name = "Bob"};
16+
session.Save(e1);
17+
18+
var e2 = new Entity {Name = "Sally"};
19+
session.Save(e2);
20+
21+
session.Flush();
22+
transaction.Commit();
23+
}
24+
}
25+
26+
protected override void OnTearDown()
27+
{
28+
using (ISession session = OpenSession())
29+
using (ITransaction transaction = session.BeginTransaction())
30+
{
31+
session.Delete("from System.Object");
32+
33+
session.Flush();
34+
transaction.Commit();
35+
}
36+
}
37+
38+
[Test]
39+
public void AllNamedBob()
40+
{
41+
using (ISession session = OpenSession())
42+
using (session.BeginTransaction())
43+
{
44+
var result = session.Query<Entity>()
45+
.All(e => e.Name == "Bob");
46+
47+
Assert.AreEqual(false, result);
48+
}
49+
}
50+
51+
[Test]
52+
public void AllNamedWithAtLeast3Char()
53+
{
54+
using (ISession session = OpenSession())
55+
using (session.BeginTransaction())
56+
{
57+
var result = session.Query<Entity>()
58+
.All(e => e.Name.Length > 2);
59+
60+
Assert.AreEqual(true, result);
61+
}
62+
}
63+
64+
[Test]
65+
public void AllNamedBobWorkaround()
66+
{
67+
using (ISession session = OpenSession())
68+
using (session.BeginTransaction())
69+
{
70+
var result = !session.Query<Entity>()
71+
.Any(e => e.Name != "Bob");
72+
73+
Assert.AreEqual(false, result);
74+
}
75+
}
76+
77+
[Test]
78+
public void AllNamedWithAtLeast3CharWorkaround()
79+
{
80+
using (ISession session = OpenSession())
81+
using (session.BeginTransaction())
82+
{
83+
var result = !session.Query<Entity>()
84+
.Any(e => e.Name.Length < 3);
85+
86+
Assert.AreEqual(true, result);
87+
}
88+
}
89+
90+
[Test]
91+
public void AnyAndAllInSubQueries()
92+
{
93+
using (ISession session = OpenSession())
94+
using (session.BeginTransaction())
95+
{
96+
var result = session.Query<Entity>()
97+
.Select(e => new { e.Id, hasRelated = e.Related.Any(), allBobRelated = e.Related.All(r => r.Name == "Bob") })
98+
.ToList();
99+
100+
Assert.AreEqual(false, result[0].hasRelated);
101+
Assert.AreEqual(true, result[0].allBobRelated);
102+
}
103+
}
104+
}
105+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" namespace="NHibernate.Test.NHSpecificTest.NH3951">
3+
4+
<class name="Entity">
5+
<id name="Id" generator="guid.comb" />
6+
<property name="Name" />
7+
<property name="RelatedId" />
8+
<set name="Related">
9+
<key column="RelatedId"/>
10+
<one-to-many class="Entity" />
11+
</set>
12+
</class>
13+
14+
</hibernate-mapping>

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,8 @@
749749
<Compile Include="NHSpecificTest\NH3950\Fixture.cs" />
750750
<Compile Include="NHSpecificTest\NH3952\Entity.cs" />
751751
<Compile Include="NHSpecificTest\NH3952\Fixture.cs" />
752+
<Compile Include="NHSpecificTest\NH3951\Entity.cs" />
753+
<Compile Include="NHSpecificTest\NH3951\Fixture.cs" />
752754
<Compile Include="NHSpecificTest\NH2204\Model.cs" />
753755
<Compile Include="NHSpecificTest\NH2204\Fixture.cs" />
754756
<Compile Include="NHSpecificTest\NH3912\BatcherLovingEntity.cs" />
@@ -3227,6 +3229,7 @@
32273229
<EmbeddedResource Include="NHSpecificTest\NH3963\Mappings.hbm.xml" />
32283230
<EmbeddedResource Include="NHSpecificTest\NH3950\Mappings.hbm.xml" />
32293231
<EmbeddedResource Include="NHSpecificTest\NH3952\Mappings.hbm.xml" />
3232+
<EmbeddedResource Include="NHSpecificTest\NH3951\Mappings.hbm.xml" />
32303233
<EmbeddedResource Include="NHSpecificTest\NH2204\Mappings.hbm.xml" />
32313234
<EmbeddedResource Include="NHSpecificTest\NH3874\Mappings.hbm.xml" />
32323235
<EmbeddedResource Include="NHSpecificTest\EntityWithUserTypeCanHaveLinqGenerators\Mappings.hbm.xml" />

src/NHibernate/Linq/IntermediateHqlTree.cs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ public class IntermediateHqlTree
3030
private HqlTreeNode _root;
3131
private HqlOrderBy _orderBy;
3232

33+
public bool IsRoot
34+
{
35+
get
36+
{
37+
return _isRoot;
38+
}
39+
}
40+
3341
public HqlTreeNode Root
3442
{
3543
get
@@ -53,11 +61,6 @@ public IntermediateHqlTree(bool root)
5361

5462
public ExpressionToHqlTranslationResults GetTranslation()
5563
{
56-
if (_isRoot)
57-
{
58-
DetectOuterExists();
59-
}
60-
6164
return new ExpressionToHqlTranslationResults(Root,
6265
_itemTransformers,
6366
_listTransformers,
@@ -201,19 +204,6 @@ public void AddHavingClause(HqlBooleanExpression where)
201204
}
202205
}
203206

204-
private void DetectOuterExists()
205-
{
206-
if (_root is HqlExists)
207-
{
208-
_takeCount = TreeBuilder.Constant(1);
209-
_root = Root.Children.First();
210-
211-
Expression<Func<IEnumerable<object>, bool>> x = l => l.Any();
212-
213-
_listTransformers.Add(x);
214-
}
215-
}
216-
217207
public void AddAdditionalCriteria(Action<IQuery, IDictionary<string, Tuple<object, IType>>> criteria)
218208
{
219209
_additionalCriteria.Add(criteria);
Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
1-
using NHibernate.Hql.Ast;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Linq.Expressions;
5+
using NHibernate.Hql.Ast;
26
using Remotion.Linq.Clauses.ResultOperators;
37

48
namespace NHibernate.Linq.Visitors.ResultOperatorProcessors
59
{
6-
public class ProcessAll : IResultOperatorProcessor<AllResultOperator>
7-
{
8-
public void Process(AllResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree)
9-
{
10-
tree.AddWhereClause(tree.TreeBuilder.BooleanNot(
11-
HqlGeneratorExpressionTreeVisitor.Visit(resultOperator.Predicate, queryModelVisitor.VisitorParameters).
12-
ToBooleanExpression()));
10+
public class ProcessAll : IResultOperatorProcessor<AllResultOperator>
11+
{
12+
public void Process(AllResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree)
13+
{
14+
tree.AddWhereClause(tree.TreeBuilder.BooleanNot(
15+
HqlGeneratorExpressionTreeVisitor.Visit(resultOperator.Predicate, queryModelVisitor.VisitorParameters).
16+
ToBooleanExpression()));
1317

14-
tree.SetRoot(tree.TreeBuilder.BooleanNot(tree.TreeBuilder.Exists((HqlQuery) tree.Root)));
15-
}
16-
}
18+
if (tree.IsRoot)
19+
{
20+
tree.AddTakeClause(tree.TreeBuilder.Constant(1));
21+
22+
Expression<Func<IEnumerable<object>, bool>> x = l => !l.Any();
23+
tree.AddListTransformer(x);
24+
}
25+
else
26+
{
27+
tree.SetRoot(tree.TreeBuilder.BooleanNot(tree.TreeBuilder.Exists((HqlQuery)tree.Root)));
28+
}
29+
}
30+
}
1731
}
Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
1-
using NHibernate.Hql.Ast;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Linq.Expressions;
5+
using NHibernate.Hql.Ast;
26
using Remotion.Linq.Clauses.ResultOperators;
37

48
namespace NHibernate.Linq.Visitors.ResultOperatorProcessors
59
{
6-
public class ProcessAny : IResultOperatorProcessor<AnyResultOperator>
7-
{
8-
public void Process(AnyResultOperator anyOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree)
9-
{
10-
tree.SetRoot(tree.TreeBuilder.Exists((HqlQuery) tree.Root));
11-
}
12-
}
10+
public class ProcessAny : IResultOperatorProcessor<AnyResultOperator>
11+
{
12+
public void Process(AnyResultOperator anyOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree)
13+
{
14+
if (tree.IsRoot)
15+
{
16+
tree.AddTakeClause(tree.TreeBuilder.Constant(1));
17+
18+
Expression<Func<IEnumerable<object>, bool>> x = l => l.Any();
19+
tree.AddListTransformer(x);
20+
}
21+
else
22+
{
23+
tree.SetRoot(tree.TreeBuilder.Exists((HqlQuery)tree.Root));
24+
}
25+
}
26+
}
1327
}

0 commit comments

Comments
 (0)