Skip to content

Commit c88d146

Browse files
authored
Fix null check for component with 4+ properties in hql (#2823)
Fixes #2822
1 parent 204b33b commit c88d146

File tree

5 files changed

+145
-14
lines changed

5 files changed

+145
-14
lines changed

src/NHibernate.Test/Async/NHSpecificTest/NH3634/FixtureByCode.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
//------------------------------------------------------------------------------
99

1010

11+
using System.Linq;
1112
using NHibernate.Cfg.MappingSchema;
1213
using NHibernate.Criterion;
1314
using NHibernate.Mapping.ByCode;
1415
using NUnit.Framework;
16+
using NHibernate.Linq;
1517

1618
namespace NHibernate.Test.NHSpecificTest.NH3634
1719
{
@@ -316,6 +318,66 @@ public async Task CachedQueryAgainstComponentWithANullPropertyUsingCriteriaAsync
316318
}
317319
}
318320

321+
[Test]
322+
public async Task QueryOverComponentIsNullAsync()
323+
{
324+
using (ISession session = OpenSession())
325+
using (session.BeginTransaction())
326+
{
327+
var person = await (session.QueryOver<Person>()
328+
.Where(p => p.Connection == null)
329+
.SingleOrDefaultAsync<Person>());
330+
Assert.That(person, Is.Null);
331+
}
332+
}
333+
334+
[Test(Description = "GH-2822")]
335+
public async Task LinqComponentIsNullAsync()
336+
{
337+
using (ISession session = OpenSession())
338+
{
339+
var person = await (session.Query<Person>()
340+
.Where(p => p.Name != null && p.Connection == null && p.Name != null)
341+
.FirstOrDefaultAsync<Person>());
342+
Assert.That(person, Is.Null);
343+
}
344+
}
345+
346+
[Test]
347+
public async Task LinqComponentIsNotNullAsync()
348+
{
349+
using (ISession session = OpenSession())
350+
{
351+
var person = await (session.Query<Person>()
352+
.Where(p => p.Name != null && p.Connection != null && p.Name != null)
353+
.FirstOrDefaultAsync<Person>());
354+
Assert.That(person, Is.Not.Null);
355+
}
356+
}
357+
358+
[Test]
359+
public async Task HqlComponentIsNullAsync()
360+
{
361+
using(new SqlLogSpy())
362+
using (ISession session = OpenSession())
363+
{
364+
var p = await (session.CreateQuery("from Person where Connection is null").UniqueResultAsync<Person>());
365+
366+
Assert.That(p, Is.Null);
367+
}
368+
}
369+
370+
[Test]
371+
public async Task HqlComponentIsNotNullAsync()
372+
{
373+
using (ISession session = OpenSession())
374+
{
375+
var p = await (session.CreateQuery("from Person where Connection is not null").SetMaxResults(1).UniqueResultAsync<Person>());
376+
377+
Assert.That(p, Is.Not.Null);
378+
}
379+
}
380+
319381
[Test]
320382
public async Task QueryOverANullComponentPropertyAsync()
321383
{

src/NHibernate.Test/NHSpecificTest/NH3634/Connection.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ class Connection
55
public virtual string ConnectionType { get; set; }
66
public virtual string Address { get; set; }
77
public virtual string PortName { get; set; }
8+
public virtual string PortName2 { get; set; }
89
}
9-
}
10+
}

src/NHibernate.Test/NHSpecificTest/NH3634/FixtureByCode.cs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using NHibernate.Cfg.MappingSchema;
1+
using System.Linq;
2+
using NHibernate.Cfg.MappingSchema;
23
using NHibernate.Criterion;
34
using NHibernate.Mapping.ByCode;
45
using NUnit.Framework;
@@ -305,6 +306,66 @@ public void CachedQueryAgainstComponentWithANullPropertyUsingCriteria()
305306
}
306307
}
307308

309+
[Test]
310+
public void QueryOverComponentIsNull()
311+
{
312+
using (ISession session = OpenSession())
313+
using (session.BeginTransaction())
314+
{
315+
var person = session.QueryOver<Person>()
316+
.Where(p => p.Connection == null)
317+
.SingleOrDefault<Person>();
318+
Assert.That(person, Is.Null);
319+
}
320+
}
321+
322+
[Test(Description = "GH-2822")]
323+
public void LinqComponentIsNull()
324+
{
325+
using (ISession session = OpenSession())
326+
{
327+
var person = session.Query<Person>()
328+
.Where(p => p.Name != null && p.Connection == null && p.Name != null)
329+
.FirstOrDefault<Person>();
330+
Assert.That(person, Is.Null);
331+
}
332+
}
333+
334+
[Test]
335+
public void LinqComponentIsNotNull()
336+
{
337+
using (ISession session = OpenSession())
338+
{
339+
var person = session.Query<Person>()
340+
.Where(p => p.Name != null && p.Connection != null && p.Name != null)
341+
.FirstOrDefault<Person>();
342+
Assert.That(person, Is.Not.Null);
343+
}
344+
}
345+
346+
[Test]
347+
public void HqlComponentIsNull()
348+
{
349+
using(new SqlLogSpy())
350+
using (ISession session = OpenSession())
351+
{
352+
var p = session.CreateQuery("from Person where Connection is null").UniqueResult<Person>();
353+
354+
Assert.That(p, Is.Null);
355+
}
356+
}
357+
358+
[Test]
359+
public void HqlComponentIsNotNull()
360+
{
361+
using (ISession session = OpenSession())
362+
{
363+
var p = session.CreateQuery("from Person where Connection is not null").SetMaxResults(1).UniqueResult<Person>();
364+
365+
Assert.That(p, Is.Not.Null);
366+
}
367+
}
368+
308369
[Test]
309370
public void QueryOverANullComponentProperty()
310371
{

src/NHibernate.Test/NHSpecificTest/NH3634/PersonMapper.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public PersonMapper()
1919
m.Property(c => c.ConnectionType, mapper => mapper.NotNullable(true));
2020
m.Property(c => c.Address, mapper => mapper.NotNullable(false));
2121
m.Property(c => c.PortName, mapper => mapper.NotNullable(false));
22+
m.Property(c => c.PortName2, mapper => mapper.NotNullable(false));
2223
});
2324
}
2425
}
25-
}
26+
}

src/NHibernate/Hql/Ast/ANTLR/Tree/AbstractNullnessCheckNode.cs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,20 +75,26 @@ private void MutateRowValueConstructorSyntax(int operandColumnSpan)
7575
{
7676
if ( i == 1 )
7777
{
78-
container.AddChildren(
79-
ASTFactory.CreateNode(comparisonType, comparisonText,
80-
ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[0])),
81-
ASTFactory.CreateNode(comparisonType, comparisonText,
82-
ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[1])));
78+
var op1 = ASTFactory.CreateNode(comparisonType, comparisonText);
79+
var operand1 = ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[0]);
80+
op1.SetFirstChild(operand1);
81+
container.SetFirstChild(op1);
82+
83+
var op2 = ASTFactory.CreateNode(comparisonType, comparisonText);
84+
var operand2 = ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[1]);
85+
op2.SetFirstChild(operand2);
86+
op1.AddSibling(op2);
8387
}
8488
else
8589
{
86-
container.AddChildren(
87-
ASTFactory.CreateNode(expansionConnectorType, expansionConnectorText),
88-
ASTFactory.CreateNode(comparisonType, comparisonText,
89-
ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[i])));
90-
91-
container = GetChild(0);
90+
var operand = ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[i]);
91+
var op = ASTFactory.CreateNode(comparisonType, comparisonText);
92+
op.SetFirstChild(operand);
93+
94+
var newContainer = ASTFactory.CreateNode(expansionConnectorType, expansionConnectorText);
95+
container.SetFirstChild(newContainer);
96+
newContainer.AddSibling(op);
97+
container = newContainer;
9298
}
9399
}
94100
}

0 commit comments

Comments
 (0)