Skip to content

Commit d6fd1dc

Browse files
authored
Enable Not node handling in HqlParser.NegateNode (nhibernate#3390)
1 parent d32a9d9 commit d6fd1dc

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

src/NHibernate.Test/Async/NHSpecificTest/GH3327/Fixture.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,21 @@ WHERE NOT (
5959
)");
6060
Assert.That((await (q.ListAsync()))[0], Is.EqualTo(0));
6161
}
62+
63+
[Test]
64+
public async Task NotNotExistsNegatedAsync()
65+
{
66+
using var log = new SqlLogSpy();
67+
using var session = OpenSession();
68+
var results = await (session.CreateQuery(
69+
@"SELECT COUNT(ROOT.Id)
70+
FROM Entity AS ROOT
71+
WHERE NOT (
72+
NOT EXISTS (FROM ChildEntity AS CHILD WHERE CHILD.Parent = ROOT)
73+
AND NOT ROOT.Name = 'Parent'
74+
)").ListAsync());
75+
Assert.That(log.GetWholeLog(), Does.Not.Contains(" NOT ").IgnoreCase);
76+
Assert.That(results.Count, Is.EqualTo(1));
77+
}
6278
}
6379
}

src/NHibernate.Test/NHSpecificTest/GH3327/Fixture.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,21 @@ WHERE NOT (
4848
)");
4949
Assert.That(q.List()[0], Is.EqualTo(0));
5050
}
51+
52+
[Test]
53+
public void NotNotExistsNegated()
54+
{
55+
using var log = new SqlLogSpy();
56+
using var session = OpenSession();
57+
var results = session.CreateQuery(
58+
@"SELECT COUNT(ROOT.Id)
59+
FROM Entity AS ROOT
60+
WHERE NOT (
61+
NOT EXISTS (FROM ChildEntity AS CHILD WHERE CHILD.Parent = ROOT)
62+
AND NOT ROOT.Name = 'Parent'
63+
)").List();
64+
Assert.That(log.GetWholeLog(), Does.Not.Contains(" NOT ").IgnoreCase);
65+
Assert.That(results.Count, Is.EqualTo(1));
66+
}
5167
}
5268
}

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,8 @@ public IASTNode NegateNode(IASTNode node)
300300
node.Type = BETWEEN;
301301
node.Text = "{not}" + node.Text;
302302
return node; // (NOT (NOT_BETWEEN a b) ) => (BETWEEN a b)
303-
/* This can never happen because this rule will always eliminate the child NOT.
304-
case NOT:
305-
return x.getFirstChild(); // (NOT (NOT x) ) => (x)
306-
*/
303+
case NOT:
304+
return node.GetChild(0); // (NOT (NOT x) ) => (x)
307305
default:
308306
IASTNode not = (IASTNode) TreeAdaptor.Create(NOT, "not");
309307
not.AddChild(node);

0 commit comments

Comments
 (0)