diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH3113/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH3113/FixtureByCode.cs
new file mode 100644
index 00000000000..13702eb1171
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3113/FixtureByCode.cs
@@ -0,0 +1,91 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by AsyncGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+
+using System.Linq;
+using NHibernate.Cfg;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Dialect;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+using NHibernate.Linq;
+
+namespace NHibernate.Test.NHSpecificTest.GH3113
+{
+ using System.Threading.Tasks;
+ [TestFixture]
+ public class ByCodeFixtureAsync : TestCaseMappingByCode
+ {
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
+ rc.Property(x => x.Name);
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override bool AppliesTo(Dialect.Dialect dialect)
+ {
+ return dialect is Oracle9iDialect;
+ }
+
+ protected override void Configure(Configuration configuration)
+ {
+ var dialect = NHibernate.Dialect.Dialect.GetDialect(configuration.Properties);
+ if (dialect is Oracle8iDialect)
+ configuration.SetProperty(Environment.Dialect, typeof(Oracle9iDialect).FullName);
+
+ base.Configure(configuration);
+ }
+
+ protected override void OnSetUp()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var e1 = new Entity { Name = "Bob" };
+ session.Save(e1);
+
+ var e2 = new Entity { Name = "Sally" };
+ session.Save(e2);
+
+ transaction.Commit();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ session.CreateQuery("delete from System.Object").ExecuteUpdate();
+
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public async Task JoinFailsOnOracle9DialectAsync()
+ {
+ using (var session = OpenSession())
+ {
+ var result = from e in session.Query()
+ join e2 in session.Query() on e.Id equals e2.Id
+ where e.Name == "Bob"
+ select e.Name;
+
+ Assert.That(await (result.ToListAsync()), Has.Count.EqualTo(1));
+ }
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3113/Entity.cs b/src/NHibernate.Test/NHSpecificTest/GH3113/Entity.cs
new file mode 100644
index 00000000000..b76b80c8423
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3113/Entity.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.GH3113
+{
+ class Entity
+ {
+ public virtual Guid Id { get; set; }
+ public virtual string Name { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3113/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH3113/FixtureByCode.cs
new file mode 100644
index 00000000000..0138c8b8d27
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3113/FixtureByCode.cs
@@ -0,0 +1,79 @@
+using System.Linq;
+using NHibernate.Cfg;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Dialect;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3113
+{
+ [TestFixture]
+ public class ByCodeFixture : TestCaseMappingByCode
+ {
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
+ rc.Property(x => x.Name);
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override bool AppliesTo(Dialect.Dialect dialect)
+ {
+ return dialect is Oracle9iDialect;
+ }
+
+ protected override void Configure(Configuration configuration)
+ {
+ var dialect = NHibernate.Dialect.Dialect.GetDialect(configuration.Properties);
+ if (dialect is Oracle8iDialect)
+ configuration.SetProperty(Environment.Dialect, typeof(Oracle9iDialect).FullName);
+
+ base.Configure(configuration);
+ }
+
+ protected override void OnSetUp()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var e1 = new Entity { Name = "Bob" };
+ session.Save(e1);
+
+ var e2 = new Entity { Name = "Sally" };
+ session.Save(e2);
+
+ transaction.Commit();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ session.CreateQuery("delete from System.Object").ExecuteUpdate();
+
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public void JoinFailsOnOracle9Dialect()
+ {
+ using (var session = OpenSession())
+ {
+ var result = from e in session.Query()
+ join e2 in session.Query() on e.Id equals e2.Id
+ where e.Name == "Bob"
+ select e.Name;
+
+ Assert.That(result.ToList(), Has.Count.EqualTo(1));
+ }
+ }
+ }
+}
diff --git a/src/NHibernate/Hql/Ast/ANTLR/Util/JoinProcessor.cs b/src/NHibernate/Hql/Ast/ANTLR/Util/JoinProcessor.cs
index 8fbcfba7fd7..ac4d1448f10 100644
--- a/src/NHibernate/Hql/Ast/ANTLR/Util/JoinProcessor.cs
+++ b/src/NHibernate/Hql/Ast/ANTLR/Util/JoinProcessor.cs
@@ -117,14 +117,14 @@ private void AddJoinNodes(IRestrictableStatement query, JoinSequence join, FromE
SqlString frag = joinFragment.ToFromFragmentString;
SqlString whereFrag = joinFragment.ToWhereFragmentString;
- // If the from element represents a JOIN_FRAGMENT and it is
- // a theta-style join, convert its type from JOIN_FRAGMENT
- // to FROM_FRAGMENT
- if ( fromElement.Type == HqlSqlWalker.JOIN_FRAGMENT &&
- ( join.IsThetaStyle || SqlStringHelper.IsNotEmpty( whereFrag ) ) )
+ // If the from element represents a JOIN_FRAGMENT or ENTITY_JOIN and it is
+ // a theta-style join, convert its type to FROM_FRAGMENT.
+ if ((fromElement.Type == HqlSqlWalker.JOIN_FRAGMENT || fromElement.Type == HqlSqlWalker.ENTITY_JOIN) &&
+ (join.IsThetaStyle || SqlStringHelper.IsNotEmpty(whereFrag)))
{
fromElement.Type = HqlSqlWalker.FROM_FRAGMENT;
- fromElement.JoinSequence.SetUseThetaStyle( true ); // this is used during SqlGenerator processing
+ // This is used during SqlGenerator processing.
+ fromElement.JoinSequence.SetUseThetaStyle(true);
}
// If there is a FROM fragment and the FROM element is an explicit, then add the from part.