Skip to content

Commit 0fdb589

Browse files
Fix AND/OR negation logic in hql (#3328)
* Fixes #3327 Co-authored-by: Roman Artiukhin <bahusdrive@gmail.com>
1 parent 8a8180a commit 0fdb589

File tree

5 files changed

+152
-4
lines changed

5 files changed

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

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,14 +214,14 @@ public IASTNode NegateNode(IASTNode node)
214214
case OR:
215215
node.Type = AND;
216216
node.Text = "{and}";
217-
NegateNode(node.GetChild(0));
218-
NegateNode(node.GetChild(1));
217+
node.SetChild(0, NegateNode(node.GetChild(0)));
218+
node.SetChild(1, NegateNode(node.GetChild(1)));
219219
return node;
220220
case AND:
221221
node.Type = OR;
222222
node.Text = "{or}";
223-
NegateNode(node.GetChild(0));
224-
NegateNode(node.GetChild(1));
223+
node.SetChild(0, NegateNode(node.GetChild(0)));
224+
node.SetChild(1, NegateNode(node.GetChild(1)));
225225
return node;
226226
case EQ:
227227
node.Type = NE;

0 commit comments

Comments
 (0)