diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH3215/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH3215/FixtureByCode.cs
new file mode 100644
index 00000000000..8d5772bf3d5
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3215/FixtureByCode.cs
@@ -0,0 +1,64 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by AsyncGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+
+using NHibernate.Cfg;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3215
+{
+ using System.Threading.Tasks;
+ [TestFixture]
+ public class ByCodeFixtureAsync : TestCaseMappingByCode
+ {
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Code);
+ rc.Property(x => x.Name);
+ rc.Property(x => x.Date);
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
+ rc.ManyToOne(x => x.Member);
+ });
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override bool AppliesTo(Dialect.Dialect dialect)
+ {
+ return TestDialect.SupportsCountDistinct;
+ }
+
+ protected override void Configure(Configuration configuration)
+ {
+ base.Configure(configuration);
+ configuration.SetProperty(Environment.Hbm2ddlKeyWords, "auto-quote");
+ }
+
+ [Test]
+ public async Task CountDistinctWithReservedWordsAsync()
+ {
+ using (var session = OpenSession())
+ {
+ var hql = "select Count(DISTINCT r.Member.id), Count(DISTINCT Date(r.Member.Date)) from Request r";
+ var result = await (session.CreateQuery(hql).ListAsync());
+
+ Assert.That(result, Has.Count.EqualTo(1));
+ }
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3215/Entity.cs b/src/NHibernate.Test/NHSpecificTest/GH3215/Entity.cs
new file mode 100644
index 00000000000..bd40de89544
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3215/Entity.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.GH3215
+{
+ class Member
+ {
+ public virtual int Code { get; set; }
+ public virtual string Name { get; set; }
+ public virtual DateTime Date { get; set; }
+ }
+
+ class Request
+ {
+ public virtual Guid Id { get; set; }
+ public virtual Member Member { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3215/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH3215/FixtureByCode.cs
new file mode 100644
index 00000000000..9935fd79940
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3215/FixtureByCode.cs
@@ -0,0 +1,53 @@
+using NHibernate.Cfg;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3215
+{
+ [TestFixture]
+ public class ByCodeFixture : TestCaseMappingByCode
+ {
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Code);
+ rc.Property(x => x.Name);
+ rc.Property(x => x.Date);
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
+ rc.ManyToOne(x => x.Member);
+ });
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override bool AppliesTo(Dialect.Dialect dialect)
+ {
+ return TestDialect.SupportsCountDistinct;
+ }
+
+ protected override void Configure(Configuration configuration)
+ {
+ base.Configure(configuration);
+ configuration.SetProperty(Environment.Hbm2ddlKeyWords, "auto-quote");
+ }
+
+ [Test]
+ public void CountDistinctWithReservedWords()
+ {
+ using (var session = OpenSession())
+ {
+ var hql = "select Count(DISTINCT r.Member.id), Count(DISTINCT Date(r.Member.Date)) from Request r";
+ var result = session.CreateQuery(hql).List();
+
+ Assert.That(result, Has.Count.EqualTo(1));
+ }
+ }
+ }
+}
diff --git a/src/NHibernate/Hql/Ast/ANTLR/Hql.g b/src/NHibernate/Hql/Ast/ANTLR/Hql.g
index 8dcd5dbc533..281e997138f 100644
--- a/src/NHibernate/Hql/Ast/ANTLR/Hql.g
+++ b/src/NHibernate/Hql/Ast/ANTLR/Hql.g
@@ -600,7 +600,7 @@ vectorExpr
// NOTE: handleDotIdent() is called immediately after the first IDENT is recognized because
// the method looks a head to find keywords after DOT and turns them into identifiers.
identPrimary
- : identifier { HandleDotIdent(); }
+ : identifier {{ HandleDotIdent(); }}
( options {greedy=true;} : DOT^ ( identifier | o=OBJECT { $o.Type = IDENT; } ) )*
( ( op=OPEN^ { $op.Type = METHOD_CALL;} exprList CLOSE! )
)?