Description
I bet the "component with more than N properties" qualification raised some eyebrows. It certainly raised mines...
Test Environment
.NET Framework 4.6.2
NHibernate 5.3.8
SQLite.Core
MSTest 2.2.4
I initially stumbled on this on a real project with NHibernate 4.1.2 and MSSQL Server, then narrowed it down to this issue and tested on a new project.
Repro
See this gist.
- Have a component with 4 or more properties mapped, of any type.
Session.Query<Entity>(e => e.Component == null).First()
- There is no step 3.
Exception detail
Exception:
- Type: NHibernate.Hql.Ast.ANTLR.QuerySyntaxException
- Message: "A recognition error occurred."
- QueryString: ".First[Entity](.Where[Entity](NHibernate.Linq.NhQueryable`1[Entity], Quote((e, ) => (Equal(e.Component, NULL))), ), )"
- StackTrace:
in NHibernate.Hql.Ast.ANTLR.ErrorCounter.ThrowQueryException()
in NHibernate.Hql.Ast.ANTLR.HqlSqlGenerator.Generate()
in NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.DoCompile(IDictionary`2 replacements, Boolean shallow, String collectionRole)
in NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IQueryExpression queryExpression, IASTNode ast, String queryIdentifier, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
in NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
in NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)
in NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)
in NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)
in NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query)
in NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
in NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
in System.Linq.Queryable.First[TSource](IQueryable`1 source)
in [my code]
- InnerException:
-- Type: Antlr.Runtime.MismatchedTreeNodeException
-- Node: "is null"
-- StackTrace:
en Antlr.Runtime.Tree.TreeParser.RecoverFromMismatchedToken(IIntStream input, Int32 ttype, BitSet follow)
en Antlr.Runtime.BaseRecognizer.Match(IIntStream input, Int32 ttype, BitSet follow)
en NHibernate.Hql.Ast.ANTLR.SqlGenerator.booleanOp(Boolean parens)
Observations
This happen no matter the types of the properties of the component. At first I figured there was something wrong with my mapping, or perhaps because value types (int, bool, etc) are never null (though the mapped column may be, and I'm querying on the component which is a reference type). I tested many permutations on a minimal model, sometimes the queries crashed, sometimes they ran. I tried changing the types, of the properties, mixing them, etc. The only pattern I could see is, once there are over 4 mapped properties, it crashes. So that's what I'm going with, but I don't doubt the cause is something else really.
From the exception thrown, I guess the underlying DB is irrelevant because it crashes while translating LINQ to HQL.