Skip to content

Commit 93d55c6

Browse files
committed
AND/OR below NOT must use result of subsequent NegateNode calls to create a new result node instead of partially mutating the existing node to consider functional signature of the NegateNode method
1 parent cd6362f commit 93d55c6

File tree

4 files changed

+106
-10
lines changed

4 files changed

+106
-10
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
3+
namespace NHibernate.Test.NHSpecificTest.GH3327
4+
{
5+
public class Entity
6+
{
7+
public virtual int Id { get; set; }
8+
public virtual string Name { get; set; }
9+
}
10+
11+
public class ChildEntity
12+
{
13+
public virtual int Id { get; set; }
14+
public virtual Entity Parent { get; set; }
15+
public virtual string Name { get; set; }
16+
}
17+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System;
2+
using NUnit.Framework;
3+
4+
namespace NHibernate.Test.NHSpecificTest.GH3327
5+
{
6+
[TestFixture]
7+
public class Fixture : BugTestCase
8+
{
9+
protected override void OnSetUp()
10+
{
11+
Sfi.Statistics.IsStatisticsEnabled = true;
12+
}
13+
14+
protected override void OnTearDown()
15+
{
16+
Sfi.Statistics.IsStatisticsEnabled = false;
17+
using (var session = OpenSession())
18+
using (var transaction = session.BeginTransaction())
19+
{
20+
session.CreateQuery("delete from ChildEntity").ExecuteUpdate();
21+
session.CreateQuery("delete from Entity").ExecuteUpdate();
22+
23+
transaction.Commit();
24+
}
25+
}
26+
27+
[Test]
28+
public void NotIsCorrectlyHandled()
29+
{
30+
using (var session = OpenSession())
31+
using (var t = session.BeginTransaction())
32+
{
33+
var parent = new Entity { Name = "Parent" };
34+
var child = new ChildEntity { Name = "Child", Parent = parent };
35+
session.Save(parent);
36+
session.Save(child);
37+
t.Commit();
38+
}
39+
40+
using (var session = OpenSession())
41+
using (var _ = session.BeginTransaction())
42+
{
43+
var q = session.CreateQuery(
44+
@"SELECT COUNT(ROOT.Id)
45+
FROM Entity AS ROOT
46+
WHERE (
47+
EXISTS (FROM ChildEntity AS CHILD WHERE CHILD.Parent = ROOT)
48+
AND ROOT.Name = 'Parent'
49+
)");
50+
Assert.That(q.List()[0], Is.EqualTo(1));
51+
52+
q = session.CreateQuery(
53+
@"SELECT COUNT(ROOT.Id)
54+
FROM Entity AS ROOT
55+
WHERE NOT (
56+
EXISTS (FROM ChildEntity AS CHILD WHERE CHILD.Parent = ROOT)
57+
AND ROOT.Name = 'Parent'
58+
)");
59+
Assert.That(q.List()[0], Is.EqualTo(0));
60+
}
61+
}
62+
}
63+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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.GH3327">
4+
5+
<class name="Entity">
6+
<id name="Id" generator="identity" />
7+
<property name="Name"/>
8+
</class>
9+
10+
<class name="ChildEntity">
11+
<id name="Id" generator="identity" />
12+
<one-to-one name="Parent" class="Entity" constrained="true" />
13+
<property name="Name"/>
14+
</class>
15+
16+
</hibernate-mapping>

src/NHibernate/Hql/Ast/ANTLR/HqlParser.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -212,17 +212,17 @@ public IASTNode NegateNode(IASTNode node)
212212
switch (node.Type)
213213
{
214214
case OR:
215-
node.Type = AND;
216-
node.Text = "{and}";
217-
NegateNode(node.GetChild(0));
218-
NegateNode(node.GetChild(1));
219-
return node;
215+
IASTNode newNode = (IASTNode) TreeAdaptor.Create(AND, "{and}");
216+
newNode.AddChildren(
217+
NegateNode(node.GetChild(0)),
218+
NegateNode(node.GetChild(1)));
219+
return newNode;
220220
case AND:
221-
node.Type = OR;
222-
node.Text = "{or}";
223-
NegateNode(node.GetChild(0));
224-
NegateNode(node.GetChild(1));
225-
return node;
221+
newNode = (IASTNode) TreeAdaptor.Create(OR, "{or}");
222+
newNode.AddChildren(
223+
NegateNode(node.GetChild(0)),
224+
NegateNode(node.GetChild(1)));
225+
return newNode;
226226
case EQ:
227227
node.Type = NE;
228228
node.Text = "{not}" + node.Text;

0 commit comments

Comments
 (0)