Skip to content

Port HQL Entity Join #2025

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

Merged
merged 1 commit into from
Mar 1, 2019
Merged
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
294 changes: 294 additions & 0 deletions src/NHibernate.Test/Async/Hql/EntityJoinHqlTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
//------------------------------------------------------------------------------
// <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.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode;
using NHibernate.Test.Hql.EntityJoinHqlTestEntities;
using NUnit.Framework;

namespace NHibernate.Test.Hql
{
using System.Threading.Tasks;
/// <summary>
/// Tests for explicit entity joins (not associated entities)
/// </summary>
[TestFixture]
public class EntityJoinHqlTestAsync : TestCaseMappingByCode
{
private const string _customEntityName = "CustomEntityName";
private EntityWithCompositeId _entityWithCompositeId;
private EntityWithNoAssociation _noAssociation;
private EntityCustomEntityName _entityWithCustomEntityName;

[Test]
public async Task CanJoinNotAssociatedEntityAsync()
{
using (var sqlLog = new SqlLogSpy())
using (var session = OpenSession())
{
EntityComplex entityComplex =
await (session
.CreateQuery("select ex " +
"from EntityWithNoAssociation root " +
"left join EntityComplex ex with root.Complex1Id = ex.Id")
.SetMaxResults(1)
.UniqueResultAsync<EntityComplex>());

Assert.That(entityComplex, Is.Not.Null);
Assert.That(NHibernateUtil.IsInitialized(entityComplex), Is.True);
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected");
}
}

[Test]
public async Task EntityJoinForCompositeKeyAsync()
{
using (var sqlLog = new SqlLogSpy())
using (var session = OpenSession())
{
await (session.CreateQuery(
"select root, ejComposite from EntityWithNoAssociation root " +
"inner join EntityWithCompositeId ejComposite " +
" with (root.Composite1Key1 = ejComposite.Key.Id1 and root.Composite1Key2 = ejComposite.Key.Id2)")
.SetMaxResults(1).ListAsync());

var composite = await (session.LoadAsync<EntityWithCompositeId>(_entityWithCompositeId.Key));

Assert.That(composite, Is.Not.Null);
Assert.That(NHibernateUtil.IsInitialized(composite), Is.True, "Object must be initialized");
Assert.That(composite, Is.EqualTo(_entityWithCompositeId).Using((EntityWithCompositeId x, EntityWithCompositeId y) => (Equals(x.Key, y.Key) && Equals(x.Name, y.Name)) ? 0 : 1));
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected");
}
}

[Test]
public async Task NullLeftEntityJoinAsync()
{
using (var sqlLog = new SqlLogSpy())
using (var session = OpenSession())
{
var objs =await (session.CreateQuery(
"select ejLeftNull, root " +
"from EntityWithNoAssociation root " +
"left join EntityComplex ejLeftNull with ejLeftNull.Id is null")
.SetMaxResults(1).UniqueResultAsync<object[]>());
EntityComplex ejLeftNull = (EntityComplex)objs[0];
EntityWithNoAssociation root = (EntityWithNoAssociation) objs[1];

Assert.That(root, Is.Not.Null, "root should not be null (looks like left join didn't work)");
Assert.That(NHibernateUtil.IsInitialized(root), Is.True);
Assert.That(ejLeftNull, Is.Null);
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected");
}
}

[Test]
public async Task EntityJoinForCustomEntityNameAsync()
{
using (var sqlLog = new SqlLogSpy())
using (var session = OpenSession())
{
EntityCustomEntityName ejCustomEntity = await (session.CreateQuery(
$"select ejCustomEntity from EntityWithNoAssociation root inner join {_customEntityName} ejCustomEntity with ejCustomEntity.Id = root.CustomEntityNameId")
.SetMaxResults(1).UniqueResultAsync<EntityCustomEntityName>());

Assert.That(ejCustomEntity, Is.Not.Null);
Assert.That(NHibernateUtil.IsInitialized(ejCustomEntity), Is.True);
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected");
}
}

[Test]
public async Task EntityJoinFoSubqueryAsync()
{
using (var sqlLog = new SqlLogSpy())
using (var session = OpenSession())
{
EntityComplex ej = null;
EntityWithNoAssociation root = null;

var subquery = "from EntityWithNoAssociation rootSub " +
"inner join EntityComplex ejSub with rootSub.Complex1Id = ejSub.Id " +
"where ejSub.Name = ej.Name";
var objs = await (session.CreateQuery(
"select root, ej from EntityWithNoAssociation root " +
"inner join EntityComplex ej with root.Complex1Id = ej.Id " +
$"where exists ({subquery})")
.UniqueResultAsync<object[]>());
root = (EntityWithNoAssociation) objs[0];
ej = (EntityComplex)objs[1];

Assert.That(NHibernateUtil.IsInitialized(root), Is.True);
Assert.That(ej, Is.Not.Null);
Assert.That(NHibernateUtil.IsInitialized(ej), Is.True);
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected");
}
}

[Test, Ignore("Failing for unrelated reasons")]
public async Task CrossJoinAndWithClauseAsync()
{
//This is about complex theta style join fix that was implemented in hibernate along with entity join functionality
//https://hibernate.atlassian.net/browse/HHH-7321
using (var sqlLog = new SqlLogSpy())
using (var session = OpenSession())
{
await (session.CreateQuery(
"SELECT s " +
"FROM EntityComplex s, EntityComplex q " +
"LEFT JOIN s.SameTypeChild AS sa WITH sa.SameTypeChild.Id = q.SameTypeChild.Id"
).ListAsync());
}
}

#region Test Setup

protected override HbmMapping GetMappings()
{
var mapper = new ModelMapper();
mapper.Class<EntityComplex>(
rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));

rc.Version(ep => ep.Version, vm => { });

rc.Property(x => x.Name);

rc.Property(ep => ep.LazyProp, m => m.Lazy(true));

rc.ManyToOne(ep => ep.SameTypeChild, m => m.Column("SameTypeChildId"));


});


mapper.Class<EntityWithCompositeId>(
rc =>
{
rc.ComponentAsId(
e => e.Key,
ekm =>
{
ekm.Property(ek => ek.Id1);
ekm.Property(ek => ek.Id2);
});

rc.Property(e => e.Name);
});

mapper.Class<EntityWithCompositeId>(
rc =>
{
rc.ComponentAsId(
e => e.Key,
ekm =>
{
ekm.Property(ek => ek.Id1);
ekm.Property(ek => ek.Id2);
});

rc.Property(e => e.Name);
});

mapper.Class<EntityWithNoAssociation>(
rc =>
{
rc.Id(e => e.Id, m => m.Generator(Generators.GuidComb));

rc.Property(e => e.Complex1Id);
rc.Property(e => e.Complex2Id);
rc.Property(e => e.Simple1Id);
rc.Property(e => e.Simple2Id);
rc.Property(e => e.Composite1Key1);
rc.Property(e => e.Composite1Key2);
rc.Property(e => e.CustomEntityNameId);

});

mapper.Class<EntityCustomEntityName>(
rc =>
{
rc.EntityName(_customEntityName);

rc.Id(e => e.Id, m => m.Generator(Generators.GuidComb));
rc.Property(e => e.Name);
});

return mapper.CompileMappingForAllExplicitlyAddedEntities();
}

protected override void OnTearDown()
{
using (ISession session = OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Delete("from System.Object");

session.Flush();
transaction.Commit();
}
}

protected override void OnSetUp()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var parent = new EntityComplex
{
Name = "ComplexEnityParent",
LazyProp = "SomeBigValue",
SameTypeChild = new EntityComplex()
{
Name = "ComplexEntityChild"
}
};

_entityWithCompositeId = new EntityWithCompositeId
{
Key = new CompositeKey
{
Id1 = 1,
Id2 = 2
},
Name = "Composite"
};

session.Save(parent.SameTypeChild);
session.Save(parent);
session.Save(_entityWithCompositeId);

_entityWithCustomEntityName = new EntityCustomEntityName()
{
Name = "EntityCustomEntityName"
};

session.Save(_customEntityName, _entityWithCustomEntityName);

_noAssociation = new EntityWithNoAssociation()
{
Complex1Id = parent.Id,
Complex2Id = parent.SameTypeChild.Id,
Composite1Key1 = _entityWithCompositeId.Key.Id1,
Composite1Key2 = _entityWithCompositeId.Key.Id2,
CustomEntityNameId = _entityWithCustomEntityName.Id
};

session.Save(_noAssociation);

session.Flush();
transaction.Commit();
}
}

#endregion Test Setup
}
}
Loading