From 4e4d60577b4f4dabc4dfaa1c943e23152549a638 Mon Sep 17 00:00:00 2001 From: csharper2010 Date: Sat, 27 Apr 2019 10:50:39 +0200 Subject: [PATCH] Fix #1228 NH-2648 - HQL with joins in sub-select creates wrong SQL Join in subselect based on alias for item in root select was not added This fixes the specific case in the least risky way, all tests green Signed-off-by: csharper2010 --- .editorconfig | 7 + .../NHSpecificTest/GH1228/Fixture.cs | 133 ++++++++++++++++++ .../NHSpecificTest/GH1228/Mappings.hbm.xml | 37 +++++ .../NHSpecificTest/GH1228/Model.cs | 26 ++++ src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs | 5 + 5 files changed, 208 insertions(+) create mode 100644 src/NHibernate.Test/NHSpecificTest/GH1228/Fixture.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH1228/Mappings.hbm.xml create mode 100644 src/NHibernate.Test/NHSpecificTest/GH1228/Model.cs diff --git a/.editorconfig b/.editorconfig index 67c20a705b8..c01a1487f7a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,13 @@ insert_final_newline = true indent_style = tab dotnet_sort_system_directives_first = true csharp_space_after_cast = true +csharp_new_line_before_open_brace = true +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true [*.xsd] indent_style = tab diff --git a/src/NHibernate.Test/NHSpecificTest/GH1228/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH1228/Fixture.cs new file mode 100644 index 00000000000..940b721a90b --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH1228/Fixture.cs @@ -0,0 +1,133 @@ +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH1228 +{ + public class Fixture : BugTestCase + { + [Test] + public void TestOk() + { + using (ISession s = OpenSession()) + { + using (ITransaction t = s.BeginTransaction()) + { + try + { + { + var queryThatWorks = s.CreateQuery(@" + SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS ROOT + WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS inv + , ROOT.Folder AS ROOT_Folder + WHERE ROOT_Folder.Shelf = inv AND inv.Id = 1 + ) ) + AND ROOT.Name = 'SomeName'"); + queryThatWorks.List(); + } + { + var queryThatWorks = s.CreateQuery(@" + SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS ROOT + WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS sheet + , ROOT.Folders AS ROOT_Folder + WHERE ROOT_Folder = sheet.Folder AND sheet.Name = 'SomeName' + ) ) + AND ROOT.Id = 1"); + queryThatWorks.List(); + } + } + finally + { + s.Delete("from Sheet"); + s.Delete("from Folder"); + s.Delete("from Shelf"); + t.Commit(); + } + } + } + } + + [Test] + public void TestWrongSql() + { + using (ISession s = OpenSession()) + { + using (ITransaction t = s.BeginTransaction()) + { + try + { + { + var queryThatCreatesWrongSQL = s.CreateQuery(@" + SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS ROOT + WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS inv + JOIN ROOT.Folder AS ROOT_Folder + WHERE ROOT_Folder.Shelf = inv AND inv.Id = 1 + ) ) + AND ROOT.Name = 'SomeName'"); + queryThatCreatesWrongSQL.List(); + } + { + // The only assertion here is that the generated SQL is valid and can be executed. + // Right now, the generated SQL is missing the JOIN inside the subselect (EXISTS) to Folder. + var queryThatCreatesWrongSQL = s.CreateQuery(@" + SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS ROOT + WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS sheet + JOIN ROOT.Folders AS ROOT_Folder + WHERE ROOT_Folder = sheet.Folder AND sheet.Name = 'SomeName' + ) ) + AND ROOT.Id = 1"); + queryThatCreatesWrongSQL.List(); + // The only assertion here is that the generated SQL is valid and can be executed. + // Right now, the generated SQL is missing the JOIN inside the subselect (EXISTS) to Folder. + } + } + finally + { + s.Delete("from Sheet"); + s.Delete("from Folder"); + s.Delete("from Shelf"); + t.Commit(); + } + } + } + } + + [Test] + public void Test3() { + using (ISession s = OpenSession()) { + using (ITransaction t = s.BeginTransaction()) { + try { + { + // The only assertion here is that the generated SQL is valid and can be executed. + // Right now, the generated SQL is missing the JOIN inside the subselect (EXISTS) to Folder. + var queryThatCreatesWrongSQL = s.CreateQuery(@" + SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS ROOT + WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS sheet + JOIN sheet.Folder AS folder + WHERE folder.Shelf = ROOT AND sheet.Name = 'SomeName' + ) ) + AND ROOT.Id = 1"); + queryThatCreatesWrongSQL.List(); + // The only assertion here is that the generated SQL is valid and can be executed. + // Right now, the generated SQL is missing the JOIN inside the subselect (EXISTS) to Folder. + } + { + var queryThatCreatesWrongSQL = s.CreateQuery(@" + SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS ROOT + WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS inv + JOIN inv.Folders AS folder + WHERE folder = ROOT.Folder AND inv.Id = 1 + ) ) + AND ROOT.Name = 'SomeName'"); + queryThatCreatesWrongSQL.List(); + } + } + finally { + s.Delete("from Sheet"); + s.Delete("from Folder"); + s.Delete("from Shelf"); + t.Commit(); + } + } + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH1228/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/GH1228/Mappings.hbm.xml new file mode 100644 index 00000000000..e34a34bb9c0 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH1228/Mappings.hbm.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/NHibernate.Test/NHSpecificTest/GH1228/Model.cs b/src/NHibernate.Test/NHSpecificTest/GH1228/Model.cs new file mode 100644 index 00000000000..86d8f5cceb7 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH1228/Model.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.GH1228 +{ + public class Shelf + { + public virtual int Id { get; set; } + public virtual string Name { get; set; } + public virtual ISet Folders { get; protected set; } = new HashSet(); + } + + public class Folder + { + public virtual int Id { get; set; } + public virtual Shelf Shelf { get; set; } + public virtual string Name { get; set; } + public virtual ISet Sheets { get; protected set; } = new HashSet(); + } + + public class Sheet + { + public virtual int Id { get; set; } + public virtual Folder Folder { get; set; } + public virtual string Name { get; set; } + } +} diff --git a/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs b/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs index 9ab54dd02f4..417b4c62883 100644 --- a/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs +++ b/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs @@ -736,6 +736,11 @@ void CreateFromJoinElement( HandleWithFragment(fromElement, with); } + + if (fromElement.Parent == null) + { + fromElement.FromClause.AddChild(fromElement); + } } if ( log.IsDebugEnabled() )