Skip to content

Commit 3e78b69

Browse files
bahusoidhazzik
authored andcommitted
Unify handling of composite values in hql and Criteria (#2159)
Fixes #1376
1 parent 0ca3028 commit 3e78b69

File tree

12 files changed

+346
-200
lines changed

12 files changed

+346
-200
lines changed

src/NHibernate.Test/Async/CompositeId/ClassWithCompositeIdFixture.cs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,5 +239,110 @@ public async Task HqlAsync()
239239
Assert.AreEqual(1, results.Count);
240240
}
241241
}
242+
243+
[Test]
244+
public async Task HqlInClauseAsync()
245+
{
246+
//Need to port changes from InLogicOperatorNode.mutateRowValueConstructorSyntaxInInListSyntax
247+
if (!Dialect.SupportsRowValueConstructorSyntaxInInList)
248+
Assert.Ignore();
249+
250+
// insert the new objects
251+
using (ISession s = OpenSession())
252+
using (ITransaction t = s.BeginTransaction())
253+
{
254+
await (s.SaveAsync(new ClassWithCompositeId(id) {OneProperty = 5}));
255+
await (s.SaveAsync(new ClassWithCompositeId(secondId) {OneProperty = 10}));
256+
await (s.SaveAsync(new ClassWithCompositeId(new Id(id.KeyString, id.GetKeyShort(), secondId.KeyDateTime))));
257+
258+
await (t.CommitAsync());
259+
}
260+
261+
using (var s = OpenSession())
262+
{
263+
var results = await (s.CreateQuery("from ClassWithCompositeId x where x.Id in (:id1, :id2)")
264+
.SetParameter("id1", id)
265+
.SetParameter("id2", secondId)
266+
.ListAsync<ClassWithCompositeId>());
267+
Assert.That(results.Count, Is.EqualTo(2));
268+
}
269+
}
270+
271+
[Test]
272+
public async Task QueryOverInClauseSubqueryAsync()
273+
{
274+
if (!TestDialect.SupportsRowValueConstructorSyntax)
275+
{
276+
Assert.Ignore();
277+
}
278+
279+
// insert the new objects
280+
using (ISession s = OpenSession())
281+
using (ITransaction t = s.BeginTransaction())
282+
{
283+
await (s.SaveAsync(new ClassWithCompositeId(id) {OneProperty = 5}));
284+
await (s.SaveAsync(new ClassWithCompositeId(secondId) {OneProperty = 10}));
285+
await (s.SaveAsync(new ClassWithCompositeId(new Id(id.KeyString, id.GetKeyShort(), secondId.KeyDateTime))));
286+
287+
await (t.CommitAsync());
288+
}
289+
290+
using (var s = OpenSession())
291+
{
292+
var results = await (s.QueryOver<ClassWithCompositeId>().WithSubquery.WhereProperty(p => p.Id).In(QueryOver.Of<ClassWithCompositeId>().Where(p => p.Id.KeyString == id.KeyString).Select(p => p.Id)).ListAsync());
293+
Assert.That(results.Count, Is.EqualTo(2));
294+
}
295+
}
296+
297+
[Test]
298+
public async Task HqlInClauseSubqueryAsync()
299+
{
300+
if (!TestDialect.SupportsRowValueConstructorSyntax)
301+
Assert.Ignore();
302+
303+
// insert the new objects
304+
using (ISession s = OpenSession())
305+
using (ITransaction t = s.BeginTransaction())
306+
{
307+
await (s.SaveAsync(new ClassWithCompositeId(id) {OneProperty = 5}));
308+
await (s.SaveAsync(new ClassWithCompositeId(secondId) {OneProperty = 10}));
309+
await (s.SaveAsync(new ClassWithCompositeId(new Id(id.KeyString, id.GetKeyShort(), secondId.KeyDateTime))));
310+
311+
await (t.CommitAsync());
312+
}
313+
314+
using (var s = OpenSession())
315+
{
316+
var results = await (s.CreateQuery("from ClassWithCompositeId x where x.Id in (select s.Id from ClassWithCompositeId s where s.Id.KeyString = :keyString)")
317+
.SetParameter("keyString", id.KeyString).ListAsync());
318+
Assert.That(results.Count, Is.EqualTo(2));
319+
}
320+
}
321+
322+
//GH-1376
323+
[Test]
324+
public async Task HqlInClauseSubquery_ForEntityAsync()
325+
{
326+
if (!TestDialect.SupportsRowValueConstructorSyntax)
327+
Assert.Ignore();
328+
329+
// insert the new objects
330+
using (ISession s = OpenSession())
331+
using (ITransaction t = s.BeginTransaction())
332+
{
333+
await (s.SaveAsync(new ClassWithCompositeId(id) {OneProperty = 5}));
334+
await (s.SaveAsync(new ClassWithCompositeId(secondId) {OneProperty = 10}));
335+
await (s.SaveAsync(new ClassWithCompositeId(new Id(id.KeyString, id.GetKeyShort(), secondId.KeyDateTime))));
336+
337+
await (t.CommitAsync());
338+
}
339+
340+
using (var s = OpenSession())
341+
{
342+
var results = await (s.CreateQuery("from ClassWithCompositeId x where x in (select s from ClassWithCompositeId s where s.Id.KeyString = :keyString)")
343+
.SetParameter("keyString", id.KeyString).ListAsync());
344+
Assert.That(results.Count, Is.EqualTo(2));
345+
}
346+
}
242347
}
243348
}

src/NHibernate.Test/Async/Criteria/CriteriaQueryTest.cs

Lines changed: 25 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -288,122 +288,56 @@ public async Task SubselectWithComponentAsync()
288288
await (t.CommitAsync());
289289
}
290290

291-
if (TestDialect.SupportsOperatorAll)
291+
//Note: It might require separate test dialect flag like SupportsRowValueConstructorWithOperatorAll
292+
if (TestDialect.SupportsOperatorAll && TestDialect.SupportsRowValueConstructorSyntax)
292293
{
293294
using (ISession session = OpenSession())
294-
using (ITransaction t = session.BeginTransaction())
295295
{
296-
try
297-
{
298-
await (session.CreateCriteria<Student>()
296+
await (session.CreateCriteria<Student>()
299297
.Add(Subqueries.PropertyEqAll("CityState", dc))
300298
.ListAsync());
301-
302-
Assert.Fail("should have failed because cannot compare subquery results with multiple columns");
303-
}
304-
catch (QueryException)
305-
{
306-
// expected
307-
}
308-
await (t.RollbackAsync());
309299
}
310-
}
311300

312-
if (TestDialect.SupportsOperatorAll)
313-
{
314301
using (ISession session = OpenSession())
315-
using (ITransaction t = session.BeginTransaction())
316302
{
317-
try
318-
{
319-
await (session.CreateCriteria<Student>()
303+
await (session.CreateCriteria<Student>()
320304
.Add(Property.ForName("CityState").EqAll(dc))
321305
.ListAsync());
322-
323-
Assert.Fail("should have failed because cannot compare subquery results with multiple columns");
324-
}
325-
catch (QueryException)
326-
{
327-
// expected
328-
}
329-
finally
330-
{
331-
await (t.RollbackAsync());
332-
}
333306
}
334307
}
335308

336-
using (ISession session = OpenSession())
337-
using (ITransaction t = session.BeginTransaction())
309+
if (TestDialect.SupportsRowValueConstructorSyntax)
338310
{
339-
try
311+
using (ISession session = OpenSession())
340312
{
341313
await (session.CreateCriteria<Student>()
342-
.Add(Subqueries.In(odessaWa, dc))
343-
.ListAsync());
344-
345-
Assert.Fail("should have failed because cannot compare subquery results with multiple columns");
346-
}
347-
catch (NHibernate.Exceptions.GenericADOException)
348-
{
349-
// expected
350-
}
351-
finally
352-
{
353-
await (t.RollbackAsync());
314+
.Add(Subqueries.In(odessaWa, dc))
315+
.ListAsync());
354316
}
355-
}
356-
357-
using (ISession session = OpenSession())
358-
using (ITransaction t = session.BeginTransaction())
359-
{
360-
DetachedCriteria dc2 = DetachedCriteria.For<Student>("st1")
361-
.Add(Property.ForName("st1.CityState").EqProperty("st2.CityState"))
362-
.SetProjection(Property.ForName("CityState"));
363-
364-
try
317+
318+
using (ISession session = OpenSession())
365319
{
320+
DetachedCriteria dc2 = DetachedCriteria.For<Student>("st1")
321+
.Add(Property.ForName("st1.CityState").EqProperty("st2.CityState"))
322+
.SetProjection(Property.ForName("CityState"));
366323
await (session.CreateCriteria<Student>("st2")
367-
.Add( Subqueries.Eq(odessaWa, dc2))
368-
.ListAsync());
369-
Assert.Fail("should have failed because cannot compare subquery results with multiple columns");
370-
}
371-
catch (NHibernate.Exceptions.GenericADOException)
372-
{
373-
// expected
374-
}
375-
finally
376-
{
377-
await (t.RollbackAsync());
324+
.Add( Subqueries.Eq(odessaWa, dc2))
325+
.ListAsync());
378326
}
379-
}
380-
381-
using (ISession session = OpenSession())
382-
using (ITransaction t = session.BeginTransaction())
383-
{
384-
DetachedCriteria dc3 = DetachedCriteria.For<Student>("st")
385-
.CreateCriteria("Enrolments")
386-
.CreateCriteria("Course")
387-
.Add(Property.ForName("Description").Eq("Hibernate Training"))
388-
.SetProjection(Property.ForName("st.CityState"));
389-
try
327+
328+
using (ISession session = OpenSession())
390329
{
330+
DetachedCriteria dc3 = DetachedCriteria.For<Student>("st")
331+
.CreateCriteria("Enrolments")
332+
.CreateCriteria("Course")
333+
.Add(Property.ForName("Description").Eq("Hibernate Training"))
334+
.SetProjection(Property.ForName("st.CityState"));
391335
await (session.CreateCriteria<Enrolment>("e")
392-
.Add(Subqueries.Eq(odessaWa, dc3))
393-
.ListAsync());
394-
395-
Assert.Fail("should have failed because cannot compare subquery results with multiple columns");
396-
}
397-
catch (NHibernate.Exceptions.GenericADOException)
398-
{
399-
// expected
400-
}
401-
finally
402-
{
403-
await (t.RollbackAsync());
336+
.Add(Subqueries.Eq(odessaWa, dc3))
337+
.ListAsync());
404338
}
405339
}
406-
340+
407341
using (ISession session = OpenSession())
408342
using (ITransaction t = session.BeginTransaction())
409343
{

src/NHibernate.Test/CompositeId/ClassWithCompositeIdFixture.cs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,5 +228,110 @@ public void Hql()
228228
Assert.AreEqual(1, results.Count);
229229
}
230230
}
231+
232+
[Test]
233+
public void HqlInClause()
234+
{
235+
//Need to port changes from InLogicOperatorNode.mutateRowValueConstructorSyntaxInInListSyntax
236+
if (!Dialect.SupportsRowValueConstructorSyntaxInInList)
237+
Assert.Ignore();
238+
239+
// insert the new objects
240+
using (ISession s = OpenSession())
241+
using (ITransaction t = s.BeginTransaction())
242+
{
243+
s.Save(new ClassWithCompositeId(id) {OneProperty = 5});
244+
s.Save(new ClassWithCompositeId(secondId) {OneProperty = 10});
245+
s.Save(new ClassWithCompositeId(new Id(id.KeyString, id.GetKeyShort(), secondId.KeyDateTime)));
246+
247+
t.Commit();
248+
}
249+
250+
using (var s = OpenSession())
251+
{
252+
var results = s.CreateQuery("from ClassWithCompositeId x where x.Id in (:id1, :id2)")
253+
.SetParameter("id1", id)
254+
.SetParameter("id2", secondId)
255+
.List<ClassWithCompositeId>();
256+
Assert.That(results.Count, Is.EqualTo(2));
257+
}
258+
}
259+
260+
[Test]
261+
public void QueryOverInClauseSubquery()
262+
{
263+
if (!TestDialect.SupportsRowValueConstructorSyntax)
264+
{
265+
Assert.Ignore();
266+
}
267+
268+
// insert the new objects
269+
using (ISession s = OpenSession())
270+
using (ITransaction t = s.BeginTransaction())
271+
{
272+
s.Save(new ClassWithCompositeId(id) {OneProperty = 5});
273+
s.Save(new ClassWithCompositeId(secondId) {OneProperty = 10});
274+
s.Save(new ClassWithCompositeId(new Id(id.KeyString, id.GetKeyShort(), secondId.KeyDateTime)));
275+
276+
t.Commit();
277+
}
278+
279+
using (var s = OpenSession())
280+
{
281+
var results = s.QueryOver<ClassWithCompositeId>().WithSubquery.WhereProperty(p => p.Id).In(QueryOver.Of<ClassWithCompositeId>().Where(p => p.Id.KeyString == id.KeyString).Select(p => p.Id)).List();
282+
Assert.That(results.Count, Is.EqualTo(2));
283+
}
284+
}
285+
286+
[Test]
287+
public void HqlInClauseSubquery()
288+
{
289+
if (!TestDialect.SupportsRowValueConstructorSyntax)
290+
Assert.Ignore();
291+
292+
// insert the new objects
293+
using (ISession s = OpenSession())
294+
using (ITransaction t = s.BeginTransaction())
295+
{
296+
s.Save(new ClassWithCompositeId(id) {OneProperty = 5});
297+
s.Save(new ClassWithCompositeId(secondId) {OneProperty = 10});
298+
s.Save(new ClassWithCompositeId(new Id(id.KeyString, id.GetKeyShort(), secondId.KeyDateTime)));
299+
300+
t.Commit();
301+
}
302+
303+
using (var s = OpenSession())
304+
{
305+
var results = s.CreateQuery("from ClassWithCompositeId x where x.Id in (select s.Id from ClassWithCompositeId s where s.Id.KeyString = :keyString)")
306+
.SetParameter("keyString", id.KeyString).List();
307+
Assert.That(results.Count, Is.EqualTo(2));
308+
}
309+
}
310+
311+
//GH-1376
312+
[Test]
313+
public void HqlInClauseSubquery_ForEntity()
314+
{
315+
if (!TestDialect.SupportsRowValueConstructorSyntax)
316+
Assert.Ignore();
317+
318+
// insert the new objects
319+
using (ISession s = OpenSession())
320+
using (ITransaction t = s.BeginTransaction())
321+
{
322+
s.Save(new ClassWithCompositeId(id) {OneProperty = 5});
323+
s.Save(new ClassWithCompositeId(secondId) {OneProperty = 10});
324+
s.Save(new ClassWithCompositeId(new Id(id.KeyString, id.GetKeyShort(), secondId.KeyDateTime)));
325+
326+
t.Commit();
327+
}
328+
329+
using (var s = OpenSession())
330+
{
331+
var results = s.CreateQuery("from ClassWithCompositeId x where x in (select s from ClassWithCompositeId s where s.Id.KeyString = :keyString)")
332+
.SetParameter("keyString", id.KeyString).List();
333+
Assert.That(results.Count, Is.EqualTo(2));
334+
}
335+
}
231336
}
232337
}

src/NHibernate.Test/CompositeId/Id.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public string KeyString
2828
set { _keyString = value; }
2929
}
3030

31+
//KeyShort is commented to test access attributes; So expose it as method instead
32+
public short GetKeyShort() => _keyShort;
3133
// public short KeyShort {
3234
// get { return _keyShort;}
3335
// set {_keyShort = value;}
@@ -55,4 +57,4 @@ public override bool Equals(object obj)
5557
return false;
5658
}
5759
}
58-
}
60+
}

0 commit comments

Comments
 (0)