Skip to content

Commit db0d6e8

Browse files
committed
NH-3784, NH-3785 Change the way collection filtering is handled.
1) Move conversion of filter-implied from elements to separate preprocessing stage. This removes confusing idiom of mutating input AST during AST walking with Antlr Tree Parser. 2) Disallow DML queries in collection filters. 3) Do not apply collection filters to inner subqueries. Also remove some old hacks from Antlr grammars.
1 parent c13f70d commit db0d6e8

File tree

15 files changed

+5428
-5261
lines changed

15 files changed

+5428
-5261
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ current-test-configuration
1111
# This will be copied from the build directory to the lib directory in order
1212
# to satisfy later build steps. But it should not be committed.
1313
NHibernate.dll
14+
TestResult.xml
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using Antlr.Runtime;
6+
using NHibernate.Hql.Ast.ANTLR;
7+
using NUnit.Framework;
8+
using System.Collections;
9+
using NHibernate.DomainModel;
10+
11+
namespace NHibernate.Test.CollectionFilterTest
12+
{
13+
[TestFixture]
14+
public class CollectionFilterQueriesTest : TestCase
15+
{
16+
protected override IList Mappings
17+
{
18+
get
19+
{
20+
return new string[] { "One.hbm.xml", "Many.hbm.xml" };
21+
}
22+
}
23+
24+
private One one;
25+
26+
protected override void OnSetUp()
27+
{
28+
base.OnSetUp();
29+
30+
// create the objects to search on
31+
one = new One();
32+
one.X = 20;
33+
one.Manies = new HashSet<Many>();
34+
35+
Many many1 = new Many();
36+
many1.X = 10;
37+
many1.One = one;
38+
one.Manies.Add( many1 );
39+
40+
Many many2 = new Many();
41+
many2.X = 20;
42+
many2.One = one;
43+
one.Manies.Add( many2 );
44+
45+
using( ISession s = OpenSession() )
46+
using( ITransaction t = s.BeginTransaction() )
47+
{
48+
s.Save( one );
49+
s.Save( many1 );
50+
s.Save( many2 );
51+
t.Commit();
52+
}
53+
}
54+
55+
protected override void OnTearDown()
56+
{
57+
using( ISession session = OpenSession() )
58+
using( ITransaction tx = session.BeginTransaction() )
59+
{
60+
session.Delete( "from Many" );
61+
session.Delete( "from One" );
62+
tx.Commit();
63+
}
64+
base.OnTearDown();
65+
}
66+
67+
[Test]
68+
public void UpdateShouldBeDisallowed()
69+
{
70+
using (ISession s = OpenSession())
71+
using (ITransaction t = s.BeginTransaction())
72+
{
73+
One one2 = (One)s.CreateQuery("from One").UniqueResult();
74+
75+
Assert.Throws<QuerySyntaxException>(() =>
76+
{
77+
s.CreateFilter(one2.Manies, "update Many set X = 1")
78+
.ExecuteUpdate();
79+
// Collection filtering disallows DML queries
80+
});
81+
82+
t.Rollback();
83+
}
84+
}
85+
86+
[Test]
87+
public void DeleteShouldBeDisallowed()
88+
{
89+
using (ISession s = OpenSession())
90+
using (ITransaction t = s.BeginTransaction())
91+
{
92+
One one2 = (One)s.CreateQuery("from One").UniqueResult();
93+
94+
Assert.Throws<QuerySyntaxException>(() =>
95+
{
96+
s.CreateFilter(one2.Manies, "delete from Many")
97+
.ExecuteUpdate();
98+
// Collection filtering disallows DML queries
99+
});
100+
101+
t.Rollback();
102+
}
103+
}
104+
105+
[Test]
106+
public void InsertShouldBeDisallowed()
107+
{
108+
using (ISession s = OpenSession())
109+
using (ITransaction t = s.BeginTransaction())
110+
{
111+
One one2 = (One)s.CreateQuery("from One").UniqueResult();
112+
113+
Assert.Throws<QuerySyntaxException>(() =>
114+
{
115+
s.CreateFilter(one2.Manies, "insert into Many (X) select t0.X from Many t0")
116+
.ExecuteUpdate();
117+
// Collection filtering disallows DML queries
118+
});
119+
120+
t.Rollback();
121+
}
122+
}
123+
124+
[Test]
125+
public void InnerSubqueryShouldNotBeFiltered()
126+
{
127+
using (ISession s = OpenSession())
128+
using (ITransaction t = s.BeginTransaction())
129+
{
130+
One one2 = (One)s.CreateQuery("from One").UniqueResult();
131+
132+
s.CreateFilter(one2.Manies, "where this.X in (select t0.X from Many t0)")
133+
.List();
134+
// Filter should only affect outer query, not inner
135+
136+
t.Rollback();
137+
}
138+
}
139+
140+
[Test]
141+
public void InnerSubqueryMustHaveFromClause()
142+
{
143+
using (ISession s = OpenSession())
144+
using (ITransaction t = s.BeginTransaction())
145+
{
146+
One one2 = (One)s.CreateQuery("from One").UniqueResult();
147+
148+
Assert.Throws<QuerySyntaxException>(() =>
149+
{
150+
s.CreateFilter(one2.Manies, "where this.X in (select X)")
151+
.List();
152+
// Inner query for filter query should have FROM clause
153+
});
154+
155+
t.Rollback();
156+
}
157+
}
158+
}
159+
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@
178178
<Compile Include="Classic\LifecycleFixture.cs" />
179179
<Compile Include="Classic\ValidatableFixture.cs" />
180180
<Compile Include="Classic\Video.cs" />
181+
<Compile Include="CollectionFilterTest\CollectionFilterQueriesTest.cs" />
181182
<Compile Include="CollectionTest\A.cs" />
182183
<Compile Include="CollectionTest\IdBagFixture.cs" />
183184
<Compile Include="CollectionTest\NullableValueTypeElementMapFixture.cs" />

0 commit comments

Comments
 (0)