Skip to content

Commit b7c085c

Browse files
PleasantDhazzik
authored andcommitted
NH-3414 - Fixed the HqlSqlWalker grammar to correctly handle multiple ORDER clauses with queries or expressions (#473)
1 parent 1a2d126 commit b7c085c

File tree

5 files changed

+2893
-2717
lines changed

5 files changed

+2893
-2717
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
5+
namespace NHibernate.Test.NHSpecificTest.NH3414
6+
{
7+
public class Entity
8+
{
9+
public virtual Guid Id { get; set; }
10+
public virtual string Name { get; set; }
11+
public virtual int SomeValue { get; set; }
12+
13+
public virtual Entity Parent { get; set; }
14+
15+
private readonly IList<Entity> children = new List<Entity>();
16+
public virtual IEnumerable<Entity> Children { get { return children; } }
17+
18+
public virtual void AddChild(Entity child)
19+
{
20+
children.Add(child);
21+
child.Parent = this;
22+
}
23+
24+
public override string ToString()
25+
{
26+
return Name + SomeValue;
27+
}
28+
29+
public override bool Equals(object obj)
30+
{
31+
var other = obj as Entity;
32+
if (other == null)
33+
{
34+
return false;
35+
}
36+
return other.Id == Id;
37+
}
38+
39+
public override int GetHashCode()
40+
{
41+
return Id.GetHashCode();
42+
}
43+
}
44+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
using System.Linq;
2+
using System.Linq.Expressions;
3+
using Antlr.Runtime.Misc;
4+
using NHibernate.Cfg.MappingSchema;
5+
using NHibernate.Linq;
6+
using NHibernate.Mapping.ByCode;
7+
using NUnit.Framework;
8+
9+
namespace NHibernate.Test.NHSpecificTest.NH3414
10+
{
11+
public class ByCodeFixture : TestCaseMappingByCode
12+
{
13+
protected override HbmMapping GetMappings()
14+
{
15+
var mapper = new ModelMapper();
16+
mapper.Class<Entity>(rc =>
17+
{
18+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
19+
rc.Property(x => x.Name);
20+
rc.Property(x => x.SomeValue);
21+
rc.ManyToOne(x => x.Parent, map => map.Column("ParentId"));
22+
rc.Bag(x => x.Children, map =>
23+
{
24+
map.Access(Accessor.NoSetter);
25+
map.Key(km => km.Column("ParentId"));
26+
map.Cascade(Mapping.ByCode.Cascade.All.Include(Mapping.ByCode.Cascade.DeleteOrphans));
27+
}, rel => rel.OneToMany());
28+
});
29+
30+
return mapper.CompileMappingForAllExplicitlyAddedEntities();
31+
}
32+
33+
protected override void OnSetUp()
34+
{
35+
using (ISession session = OpenSession())
36+
using (ITransaction transaction = session.BeginTransaction())
37+
{
38+
var e1 = new Entity {
39+
Name = "A",
40+
SomeValue = 1,
41+
};
42+
e1.AddChild(new Entity { Name = "X", SomeValue = 3 });
43+
e1.AddChild(new Entity { Name = "Z", SomeValue = 10 });
44+
session.Save(e1);
45+
46+
var e2 = new Entity
47+
{
48+
Name = "B",
49+
SomeValue = 2,
50+
};
51+
e2.AddChild(new Entity { Name = "Y", SomeValue = 10 });
52+
e2.AddChild(new Entity { Name = "Z", SomeValue = 2 });
53+
session.Save(e2);
54+
55+
var e3 = new Entity
56+
{
57+
Name = "A",
58+
SomeValue = 3,
59+
};
60+
e3.AddChild(new Entity { Name = "X", SomeValue = 9 });
61+
e3.AddChild(new Entity { Name = "Y", SomeValue = 1 });
62+
session.Save(e3);
63+
64+
session.Flush();
65+
transaction.Commit();
66+
}
67+
}
68+
69+
protected override void OnTearDown()
70+
{
71+
using (ISession session = OpenSession())
72+
using (ITransaction transaction = session.BeginTransaction())
73+
{
74+
session.Delete("from System.Object");
75+
76+
session.Flush();
77+
transaction.Commit();
78+
}
79+
}
80+
81+
[Test]
82+
public void OrderByNoQueriesTest()
83+
{
84+
using (ISession session = OpenSession())
85+
using (session.BeginTransaction())
86+
{
87+
var query = session.Query<Entity>()
88+
.Where(x => x.Parent == null)
89+
.OrderBy(x => x.Name) // Expression
90+
.ThenBy(x => x.SomeValue); // Expression
91+
92+
var results = query.ToList();
93+
Assert.That(results.Select(x => x.ToString()), Is.EqualTo(new[] { "A1", "A3", "B2" }));
94+
}
95+
}
96+
97+
[Test]
98+
public void OrderBySingleQueryTest()
99+
{
100+
using (ISession session = OpenSession())
101+
using (session.BeginTransaction())
102+
{
103+
var query = session.Query<Entity>()
104+
.Where(x => x.Parent == null)
105+
// This could be any expression that generates a subquery
106+
.OrderBy(x => x.Children.Select(c => c.SomeValue).Min());
107+
108+
var results = query.ToList();
109+
Assert.That(results.Select(x => x.ToString()), Is.EqualTo(new[] { "A3", "B2", "A1" }));
110+
}
111+
}
112+
113+
[Test]
114+
public void OrderBySingleQueryComplex()
115+
{
116+
using (ISession session = OpenSession())
117+
using (session.BeginTransaction())
118+
{
119+
var query = session.Query<Entity>()
120+
.Where(x => x.Parent == null)
121+
.OrderBy(x => x.Name) // Expression
122+
// This could be any expression that generates a subquery
123+
.ThenBy(x => x.Children.Select(c => c.SomeValue).Min());
124+
125+
var results = query.ToList();
126+
Assert.That(results.Select(x => x.ToString()), Is.EqualTo(new[] { "A3", "A1", "B2" }));
127+
}
128+
}
129+
130+
[Test]
131+
public void OrderBySingleQueryComplexReverse()
132+
{
133+
using (ISession session = OpenSession())
134+
using (session.BeginTransaction())
135+
{
136+
var query = session.Query<Entity>()
137+
.Where(x => x.Parent == null)
138+
// This could be any expression that generates a subquery
139+
.OrderByDescending(x => x.Children.Select(c => c.SomeValue).Max())
140+
.ThenBy(x => x.Name); // Expression
141+
142+
var results = query.ToList();
143+
Assert.That(results.Select(x => x.ToString()), Is.EqualTo(new[] { "A1", "B2", "A3" }));
144+
}
145+
}
146+
147+
[Test]
148+
public void OrderByMultipleQuery()
149+
{
150+
using (ISession session = OpenSession())
151+
using (session.BeginTransaction())
152+
{
153+
var query = session.Query<Entity>()
154+
.Where(x => x.Parent == null)
155+
// These could be any expressions that generate a subqueries
156+
.OrderByDescending(x => x.Children.Select(c => c.SomeValue).Max())
157+
.ThenBy(x => x.Children.Select(c => c.SomeValue).Min());
158+
159+
var results = query.ToList();
160+
Assert.That(results.Select(x => x.ToString()), Is.EqualTo(new[] { "B2", "A1", "A3" }));
161+
}
162+
}
163+
}
164+
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,8 @@
723723
<Compile Include="NHSpecificTest\BagWithLazyExtraAndFilter\Fixture.cs" />
724724
<Compile Include="Linq\ByMethod\DistinctTests.cs" />
725725
<Compile Include="Component\Basic\ComponentWithUniqueConstraintTests.cs" />
726+
<Compile Include="NHSpecificTest\NH3414\Entity.cs" />
727+
<Compile Include="NHSpecificTest\NH3414\FixtureByCode.cs" />
726728
<Compile Include="NHSpecificTest\NH2218\Fixture.cs" />
727729
<Compile Include="NHSpecificTest\NH2931\Fixture.cs" />
728730
<Compile Include="NHSpecificTest\NH2931\Mappings.cs" />

0 commit comments

Comments
 (0)