Skip to content

[WIP] Cacheable Multicriteria/Future'd query with aliased join throw exception #1733

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

Closed
Closed
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
157 changes: 157 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/NH3864/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using NHibernate.Linq;
using NUnit.Framework;
using System.Collections.Generic;
using System.Linq;

namespace NHibernate.Test.NHSpecificTest.NH3864
{
using System.Threading.Tasks;
[TestFixture]
public class FixtureAsync : BugTestCase
{
protected override void OnSetUp()
{
Clear2ndLevelCache();
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var p1 = new Person() { Name = "A" };
var p1c1 = new Person() { Name = "AA" };
var p1c2 = new Person() { Name = "AB" };
var p1c3 = new Person() { Name = "AC" };
p1.Children = new HashSet<Person>(new[] { p1c1, p1c2, p1c3 });
session.Save(p1);

var p2 = new Person() { Name = "B" };
var p2c1 = new Person() { Name = "BA" };
var p2c2 = new Person() { Name = "BB" };
var p2c3 = new Person() { Name = "BC" };
p2.Children = new HashSet<Person>(new[] { p2c1, p2c2, p2c3 });
session.Save(p2);

transaction.Commit();
}
}

protected override void OnTearDown()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
session.Delete("from Person");
transaction.Commit();
}
}

[Test]
public async Task CacheableMulticriteria_QueryOverWithAliasedJoinQueryOverAsync()
{
foreach (var checkCache in new[] { false, true })
{
using (var sqlLogSpy = new SqlLogSpy())
{
using (var session = Sfi.OpenSession())
{
var query = CreateQueryOverWithAliasedJoinQueryOver(session);

var multiCriteria = session.CreateMultiCriteria();
multiCriteria.Add("myQuery", query);
multiCriteria.SetCacheable(true);

var list = (IList<Person>)await (multiCriteria.GetResultAsync("myQuery"));
AssertQueryResult(list);
}

if (checkCache && !string.IsNullOrEmpty(sqlLogSpy.GetWholeLog()))
{
Assert.Fail("SQL executed. 2nd level cache should be used instead.");
}
}
}
}

[Test]
public async Task CacheableMulticriteria_QueryOverWithJoinAliasAsync()
{
foreach (var checkCache in new[] { false, true })
{
using (var sqlLogSpy = new SqlLogSpy())
{
using (var s = Sfi.OpenSession())
{
var query = CreateQueryOverWithJoinAlias(s);

var multiCriteria = s.CreateMultiCriteria();
multiCriteria.Add("myQuery", query);
multiCriteria.SetCacheable(true);

var list = (IList<Person>)await (multiCriteria.GetResultAsync("myQuery"));
AssertQueryResult(list);
}
if (checkCache && !string.IsNullOrEmpty(sqlLogSpy.GetWholeLog()))
{
Assert.Fail("SQL executed. 2nd level cache should be used instead.");
}
}
}
}

private static void AssertQueryResult(IList<Person> list)
{
Assert.AreEqual(6, list.Count, "Returned records count is wrong.");
var person1 = list.FirstOrDefault(p => p.Name == "A");
Assert.NotNull(person1);
var person2 = list.FirstOrDefault(p => p.Name == "B");
Assert.NotNull(person2);

CollectionAssert.AreEquivalent(person1.Children.Select(c => c.Name), new[] { "AA", "AB", "AC" });
CollectionAssert.AreEquivalent(person2.Children.Select(c => c.Name), new[] { "BA", "BB", "BC" });
}

private static IFutureEnumerable<Person> CreateCacheableQueryWithSubquery(ISession session)
{
var subQuery = session.Query<Person>()
.WithOptions(p => p.SetCacheable(true));

var query = session.Query<Person>()
.FetchMany(p => p.Children)
.Where(p => subQuery.Contains(p) && p.Parent == null)
.WithOptions(o => o.SetCacheable(true))
.ToFuture();

return query;
}

private static IQueryOver<Person, Person> CreateQueryOverWithJoinAlias(ISession session)
{
Person childAlias = null;
return session.QueryOver<Person>()
.Where(p => p.Parent == null)
.JoinAlias(x => x.Children, () => childAlias);
}

private static IQueryOver<Person, Person> CreateQueryOverWithAliasedJoinQueryOver(ISession session)
{
Person childAlias = null;
return session.QueryOver<Person>()
.Where(p => p.Parent == null)
.JoinQueryOver(x => x.Children, () => childAlias);
}

private void Clear2ndLevelCache()
{
Sfi.EvictQueries();
Sfi.Evict(typeof(Person));
}
}
}
216 changes: 216 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/NH3864/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
using NHibernate.Linq;
using NUnit.Framework;
using System.Collections.Generic;
using System.Linq;

namespace NHibernate.Test.NHSpecificTest.NH3864
{
[TestFixture]
public class Fixture : BugTestCase
{
protected override void OnSetUp()
{
Clear2ndLevelCache();
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var p1 = new Person() { Name = "A" };
var p1c1 = new Person() { Name = "AA" };
var p1c2 = new Person() { Name = "AB" };
var p1c3 = new Person() { Name = "AC" };
p1.Children = new HashSet<Person>(new[] { p1c1, p1c2, p1c3 });
session.Save(p1);

var p2 = new Person() { Name = "B" };
var p2c1 = new Person() { Name = "BA" };
var p2c2 = new Person() { Name = "BB" };
var p2c3 = new Person() { Name = "BC" };
p2.Children = new HashSet<Person>(new[] { p2c1, p2c2, p2c3 });
session.Save(p2);

transaction.Commit();
}
}

protected override void OnTearDown()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
session.Delete("from Person");
transaction.Commit();
}
}

[Test]
public void CacheableMulticriteria_QueryOverWithAliasedJoinQueryOver()
{
foreach (var checkCache in new[] { false, true })
{
using (var sqlLogSpy = new SqlLogSpy())
{
using (var session = Sfi.OpenSession())
{
var query = CreateQueryOverWithAliasedJoinQueryOver(session);

var multiCriteria = session.CreateMultiCriteria();
multiCriteria.Add("myQuery", query);
multiCriteria.SetCacheable(true);

var list = (IList<Person>)multiCriteria.GetResult("myQuery");
AssertQueryResult(list);
}

if (checkCache && !string.IsNullOrEmpty(sqlLogSpy.GetWholeLog()))
{
Assert.Fail("SQL executed. 2nd level cache should be used instead.");
}
}
}
}

[Test]
public void CacheableFuture_QueryOverWithAliasedJoinQueryOver()
{
foreach (var checkCache in new[] { false, true })
{
using (var sqlLogSpy = new SqlLogSpy())
{
using (var s = Sfi.OpenSession())
{
var query = CreateQueryOverWithAliasedJoinQueryOver(s)
.Cacheable()
.Future();

var list = query.ToList();
AssertQueryResult(list);
}
if (checkCache && !string.IsNullOrEmpty(sqlLogSpy.GetWholeLog()))
{
Assert.Fail("SQL executed. 2nd level cache should be used instead.");
}
}
}
}

[Test]
public void CacheableMulticriteria_QueryOverWithJoinAlias()
{
foreach (var checkCache in new[] { false, true })
{
using (var sqlLogSpy = new SqlLogSpy())
{
using (var s = Sfi.OpenSession())
{
var query = CreateQueryOverWithJoinAlias(s);

var multiCriteria = s.CreateMultiCriteria();
multiCriteria.Add("myQuery", query);
multiCriteria.SetCacheable(true);

var list = (IList<Person>)multiCriteria.GetResult("myQuery");
AssertQueryResult(list);
}
if (checkCache && !string.IsNullOrEmpty(sqlLogSpy.GetWholeLog()))
{
Assert.Fail("SQL executed. 2nd level cache should be used instead.");
}
}
}
}

[Test]
public void CacheableFuture_QueryOverWithJoinAlias()
{
foreach (var checkCache in new[] { false, true })
{
using (var sqlLogSpy = new SqlLogSpy())
{
using (var s = Sfi.OpenSession())
{
var query = CreateQueryOverWithJoinAlias(s)
.Cacheable()
.Future();

var list = query.ToList();
AssertQueryResult(list);
}
if (checkCache && !string.IsNullOrEmpty(sqlLogSpy.GetWholeLog()))
{
Assert.Fail("SQL executed. 2nd level cache should be used instead.");
}
}
}
}

[Test]
public void CacheableFuture_QueryWithSubQuery()
{
foreach (var checkCache in new[] { false, true })
{
using (var sqlLogSpy = new SqlLogSpy())
{
using (var session = Sfi.OpenSession())
{
var query = CreateCacheableQueryWithSubquery(session);

var list = query.ToList();
AssertQueryResult(list);
}
if (checkCache && !string.IsNullOrEmpty(sqlLogSpy.GetWholeLog()))
{
Assert.Fail("SQL executed. 2nd level cache should be used instead.");
}
}
}
}

private static void AssertQueryResult(IList<Person> list)
{
Assert.AreEqual(6, list.Count, "Returned records count is wrong.");
var person1 = list.FirstOrDefault(p => p.Name == "A");
Assert.NotNull(person1);
var person2 = list.FirstOrDefault(p => p.Name == "B");
Assert.NotNull(person2);

CollectionAssert.AreEquivalent(person1.Children.Select(c => c.Name), new[] { "AA", "AB", "AC" });
CollectionAssert.AreEquivalent(person2.Children.Select(c => c.Name), new[] { "BA", "BB", "BC" });
}

private static IFutureEnumerable<Person> CreateCacheableQueryWithSubquery(ISession session)
{
var subQuery = session.Query<Person>()
.WithOptions(p => p.SetCacheable(true));

var query = session.Query<Person>()
.FetchMany(p => p.Children)
.Where(p => subQuery.Contains(p) && p.Parent == null)
.WithOptions(o => o.SetCacheable(true))
.ToFuture();

return query;
}

private static IQueryOver<Person, Person> CreateQueryOverWithJoinAlias(ISession session)
{
Person childAlias = null;
return session.QueryOver<Person>()
.Where(p => p.Parent == null)
.JoinAlias(x => x.Children, () => childAlias);
}

private static IQueryOver<Person, Person> CreateQueryOverWithAliasedJoinQueryOver(ISession session)
{
Person childAlias = null;
return session.QueryOver<Person>()
.Where(p => p.Parent == null)
.JoinQueryOver(x => x.Children, () => childAlias);
}

private void Clear2ndLevelCache()
{
Sfi.EvictQueries();
Sfi.Evict(typeof(Person));
}
}
}
18 changes: 18 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/NH3864/Mappings.hbm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="NHibernate.Test.NHSpecificTest.NH3864"
assembly="NHibernate.Test">

<class name="Person">
<id name="Id">
<generator class="native" />
</id>
<property name="Name" />
<many-to-one name="Parent" column="parent_id" />
<set name="Children" cascade="all">
<key column="parent_id" />
<one-to-many class="Person" />
</set>
</class>
</hibernate-mapping>
Loading