Skip to content

Commit 89e4422

Browse files
csharper2010hazzik
authored andcommitted
Fix HQL with joins in sub-select creating wrong SQL (#2146)
Join in subselect based on alias for item in root select was not added. This fixes the specific case in the least risky way. Fixes #1228
1 parent 3819f09 commit 89e4422

File tree

5 files changed

+208
-0
lines changed

5 files changed

+208
-0
lines changed

.editorconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ insert_final_newline = true
77
indent_style = tab
88
dotnet_sort_system_directives_first = true
99
csharp_space_after_cast = true
10+
csharp_new_line_before_open_brace = true
11+
csharp_new_line_before_else = true
12+
csharp_new_line_before_catch = true
13+
csharp_new_line_before_finally = true
14+
csharp_new_line_before_members_in_object_initializers = true
15+
csharp_new_line_before_members_in_anonymous_types = true
16+
csharp_new_line_between_query_expression_clauses = true
1017

1118
[*.xsd]
1219
indent_style = tab
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
using NUnit.Framework;
2+
3+
namespace NHibernate.Test.NHSpecificTest.GH1228
4+
{
5+
public class Fixture : BugTestCase
6+
{
7+
[Test]
8+
public void TestOk()
9+
{
10+
using (ISession s = OpenSession())
11+
{
12+
using (ITransaction t = s.BeginTransaction())
13+
{
14+
try
15+
{
16+
{
17+
var queryThatWorks = s.CreateQuery(@"
18+
SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS ROOT
19+
WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS inv
20+
, ROOT.Folder AS ROOT_Folder
21+
WHERE ROOT_Folder.Shelf = inv AND inv.Id = 1
22+
) )
23+
AND ROOT.Name = 'SomeName'");
24+
queryThatWorks.List();
25+
}
26+
{
27+
var queryThatWorks = s.CreateQuery(@"
28+
SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS ROOT
29+
WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS sheet
30+
, ROOT.Folders AS ROOT_Folder
31+
WHERE ROOT_Folder = sheet.Folder AND sheet.Name = 'SomeName'
32+
) )
33+
AND ROOT.Id = 1");
34+
queryThatWorks.List();
35+
}
36+
}
37+
finally
38+
{
39+
s.Delete("from Sheet");
40+
s.Delete("from Folder");
41+
s.Delete("from Shelf");
42+
t.Commit();
43+
}
44+
}
45+
}
46+
}
47+
48+
[Test]
49+
public void TestWrongSql()
50+
{
51+
using (ISession s = OpenSession())
52+
{
53+
using (ITransaction t = s.BeginTransaction())
54+
{
55+
try
56+
{
57+
{
58+
var queryThatCreatesWrongSQL = s.CreateQuery(@"
59+
SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS ROOT
60+
WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS inv
61+
JOIN ROOT.Folder AS ROOT_Folder
62+
WHERE ROOT_Folder.Shelf = inv AND inv.Id = 1
63+
) )
64+
AND ROOT.Name = 'SomeName'");
65+
queryThatCreatesWrongSQL.List();
66+
}
67+
{
68+
// The only assertion here is that the generated SQL is valid and can be executed.
69+
// Right now, the generated SQL is missing the JOIN inside the subselect (EXISTS) to Folder.
70+
var queryThatCreatesWrongSQL = s.CreateQuery(@"
71+
SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS ROOT
72+
WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS sheet
73+
JOIN ROOT.Folders AS ROOT_Folder
74+
WHERE ROOT_Folder = sheet.Folder AND sheet.Name = 'SomeName'
75+
) )
76+
AND ROOT.Id = 1");
77+
queryThatCreatesWrongSQL.List();
78+
// The only assertion here is that the generated SQL is valid and can be executed.
79+
// Right now, the generated SQL is missing the JOIN inside the subselect (EXISTS) to Folder.
80+
}
81+
}
82+
finally
83+
{
84+
s.Delete("from Sheet");
85+
s.Delete("from Folder");
86+
s.Delete("from Shelf");
87+
t.Commit();
88+
}
89+
}
90+
}
91+
}
92+
93+
[Test]
94+
public void Test3() {
95+
using (ISession s = OpenSession()) {
96+
using (ITransaction t = s.BeginTransaction()) {
97+
try {
98+
{
99+
// The only assertion here is that the generated SQL is valid and can be executed.
100+
// Right now, the generated SQL is missing the JOIN inside the subselect (EXISTS) to Folder.
101+
var queryThatCreatesWrongSQL = s.CreateQuery(@"
102+
SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS ROOT
103+
WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS sheet
104+
JOIN sheet.Folder AS folder
105+
WHERE folder.Shelf = ROOT AND sheet.Name = 'SomeName'
106+
) )
107+
AND ROOT.Id = 1");
108+
queryThatCreatesWrongSQL.List();
109+
// The only assertion here is that the generated SQL is valid and can be executed.
110+
// Right now, the generated SQL is missing the JOIN inside the subselect (EXISTS) to Folder.
111+
}
112+
{
113+
var queryThatCreatesWrongSQL = s.CreateQuery(@"
114+
SELECT ROOT FROM NHibernate.Test.NHSpecificTest.GH1228.Sheet AS ROOT
115+
WHERE (EXISTS (FROM NHibernate.Test.NHSpecificTest.GH1228.Shelf AS inv
116+
JOIN inv.Folders AS folder
117+
WHERE folder = ROOT.Folder AND inv.Id = 1
118+
) )
119+
AND ROOT.Name = 'SomeName'");
120+
queryThatCreatesWrongSQL.List();
121+
}
122+
}
123+
finally {
124+
s.Delete("from Sheet");
125+
s.Delete("from Folder");
126+
s.Delete("from Shelf");
127+
t.Commit();
128+
}
129+
}
130+
}
131+
}
132+
}
133+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
3+
namespace="NHibernate.Test.NHSpecificTest.GH1228"
4+
assembly="NHibernate.Test"
5+
>
6+
<class name="Shelf" >
7+
<id name="Id">
8+
<generator class="increment"/>
9+
</id>
10+
<property name="Name"/>
11+
<set name="Folders" lazy="true" cascade="all-delete-orphan" inverse="true">
12+
<key column="Shelf"/>
13+
<one-to-many class="Folder"/>
14+
</set>
15+
</class>
16+
17+
<class name="Folder" >
18+
<id name="Id">
19+
<generator class="increment"/>
20+
</id>
21+
<property name="Name"/>
22+
<many-to-one name="Shelf" class="Shelf"/>
23+
<set name="Sheets" lazy="true" cascade="all-delete-orphan" inverse="true">
24+
<key column="Folder"/>
25+
<one-to-many class="Sheet"/>
26+
</set>
27+
</class>
28+
29+
<class name="Sheet" >
30+
<id name="Id">
31+
<generator class="increment"/>
32+
</id>
33+
<property name="Name"/>
34+
<many-to-one name="Folder" class="Folder"/>
35+
</class>
36+
37+
</hibernate-mapping>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System.Collections.Generic;
2+
3+
namespace NHibernate.Test.NHSpecificTest.GH1228
4+
{
5+
public class Shelf
6+
{
7+
public virtual int Id { get; set; }
8+
public virtual string Name { get; set; }
9+
public virtual ISet<Folder> Folders { get; protected set; } = new HashSet<Folder>();
10+
}
11+
12+
public class Folder
13+
{
14+
public virtual int Id { get; set; }
15+
public virtual Shelf Shelf { get; set; }
16+
public virtual string Name { get; set; }
17+
public virtual ISet<Sheet> Sheets { get; protected set; } = new HashSet<Sheet>();
18+
}
19+
20+
public class Sheet
21+
{
22+
public virtual int Id { get; set; }
23+
public virtual Folder Folder { get; set; }
24+
public virtual string Name { get; set; }
25+
}
26+
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,11 @@ void CreateFromJoinElement(
736736

737737
HandleWithFragment(fromElement, with);
738738
}
739+
740+
if (fromElement.Parent == null)
741+
{
742+
fromElement.FromClause.AddChild(fromElement);
743+
}
739744
}
740745

741746
if ( log.IsDebugEnabled() )

0 commit comments

Comments
 (0)