Skip to content

Fix null check for component with 4+ properties in hql #2823

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/NH3634/FixtureByCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
//------------------------------------------------------------------------------


using System.Linq;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Criterion;
using NHibernate.Mapping.ByCode;
using NUnit.Framework;
using NHibernate.Linq;

namespace NHibernate.Test.NHSpecificTest.NH3634
{
Expand Down Expand Up @@ -316,6 +318,66 @@ public async Task CachedQueryAgainstComponentWithANullPropertyUsingCriteriaAsync
}
}

[Test]
public async Task QueryOverComponentIsNullAsync()
{
using (ISession session = OpenSession())
using (session.BeginTransaction())
{
var person = await (session.QueryOver<Person>()
.Where(p => p.Connection == null)
.SingleOrDefaultAsync<Person>());
Assert.That(person, Is.Null);
}
}

[Test(Description = "GH-2822")]
public async Task LinqComponentIsNullAsync()
{
using (ISession session = OpenSession())
{
var person = await (session.Query<Person>()
.Where(p => p.Name != null && p.Connection == null && p.Name != null)
.FirstOrDefaultAsync<Person>());
Assert.That(person, Is.Null);
}
}

[Test]
public async Task LinqComponentIsNotNullAsync()
{
using (ISession session = OpenSession())
{
var person = await (session.Query<Person>()
.Where(p => p.Name != null && p.Connection != null && p.Name != null)
.FirstOrDefaultAsync<Person>());
Assert.That(person, Is.Not.Null);
}
}

[Test]
public async Task HqlComponentIsNullAsync()
{
using(new SqlLogSpy())
using (ISession session = OpenSession())
{
var p = await (session.CreateQuery("from Person where Connection is null").UniqueResultAsync<Person>());

Assert.That(p, Is.Null);
}
}

[Test]
public async Task HqlComponentIsNotNullAsync()
{
using (ISession session = OpenSession())
{
var p = await (session.CreateQuery("from Person where Connection is not null").SetMaxResults(1).UniqueResultAsync<Person>());

Assert.That(p, Is.Not.Null);
}
}

[Test]
public async Task QueryOverANullComponentPropertyAsync()
{
Expand Down
3 changes: 2 additions & 1 deletion src/NHibernate.Test/NHSpecificTest/NH3634/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ class Connection
public virtual string ConnectionType { get; set; }
public virtual string Address { get; set; }
public virtual string PortName { get; set; }
public virtual string PortName2 { get; set; }
}
}
}
63 changes: 62 additions & 1 deletion src/NHibernate.Test/NHSpecificTest/NH3634/FixtureByCode.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NHibernate.Cfg.MappingSchema;
using System.Linq;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Criterion;
using NHibernate.Mapping.ByCode;
using NUnit.Framework;
Expand Down Expand Up @@ -305,6 +306,66 @@ public void CachedQueryAgainstComponentWithANullPropertyUsingCriteria()
}
}

[Test]
public void QueryOverComponentIsNull()
{
using (ISession session = OpenSession())
using (session.BeginTransaction())
{
var person = session.QueryOver<Person>()
.Where(p => p.Connection == null)
.SingleOrDefault<Person>();
Assert.That(person, Is.Null);
}
}

[Test(Description = "GH-2822")]
public void LinqComponentIsNull()
{
using (ISession session = OpenSession())
{
var person = session.Query<Person>()
.Where(p => p.Name != null && p.Connection == null && p.Name != null)
.FirstOrDefault<Person>();
Assert.That(person, Is.Null);
}
}

[Test]
public void LinqComponentIsNotNull()
{
using (ISession session = OpenSession())
{
var person = session.Query<Person>()
.Where(p => p.Name != null && p.Connection != null && p.Name != null)
.FirstOrDefault<Person>();
Assert.That(person, Is.Not.Null);
}
}

[Test]
public void HqlComponentIsNull()
{
using(new SqlLogSpy())
using (ISession session = OpenSession())
{
var p = session.CreateQuery("from Person where Connection is null").UniqueResult<Person>();

Assert.That(p, Is.Null);
}
}

[Test]
public void HqlComponentIsNotNull()
{
using (ISession session = OpenSession())
{
var p = session.CreateQuery("from Person where Connection is not null").SetMaxResults(1).UniqueResult<Person>();

Assert.That(p, Is.Not.Null);
}
}

[Test]
public void QueryOverANullComponentProperty()
{
Expand Down
3 changes: 2 additions & 1 deletion src/NHibernate.Test/NHSpecificTest/NH3634/PersonMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public PersonMapper()
m.Property(c => c.ConnectionType, mapper => mapper.NotNullable(true));
m.Property(c => c.Address, mapper => mapper.NotNullable(false));
m.Property(c => c.PortName, mapper => mapper.NotNullable(false));
m.Property(c => c.PortName2, mapper => mapper.NotNullable(false));
});
}
}
}
}
28 changes: 17 additions & 11 deletions src/NHibernate/Hql/Ast/ANTLR/Tree/AbstractNullnessCheckNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,26 @@ private void MutateRowValueConstructorSyntax(int operandColumnSpan)
{
if ( i == 1 )
{
container.AddChildren(
ASTFactory.CreateNode(comparisonType, comparisonText,
ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[0])),
ASTFactory.CreateNode(comparisonType, comparisonText,
ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[1])));
var op1 = ASTFactory.CreateNode(comparisonType, comparisonText);
var operand1 = ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[0]);
op1.SetFirstChild(operand1);
container.SetFirstChild(op1);

var op2 = ASTFactory.CreateNode(comparisonType, comparisonText);
var operand2 = ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[1]);
op2.SetFirstChild(operand2);
op1.AddSibling(op2);
}
else
{
container.AddChildren(
ASTFactory.CreateNode(expansionConnectorType, expansionConnectorText),
ASTFactory.CreateNode(comparisonType, comparisonText,
ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[i])));

container = GetChild(0);
var operand = ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, mutationTexts[i]);
var op = ASTFactory.CreateNode(comparisonType, comparisonText);
op.SetFirstChild(operand);

var newContainer = ASTFactory.CreateNode(expansionConnectorType, expansionConnectorText);
container.SetFirstChild(newContainer);
newContainer.AddSibling(op);
container = newContainer;
}
}
}
Expand Down