From: <ric...@us...> - 2011-03-02 22:20:30
|
Revision: 5414 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5414&view=rev Author: ricbrown Date: 2011-03-02 22:20:24 +0000 (Wed, 02 Mar 2011) Log Message: ----------- Fix NH-2400 (Linq query fail when using contains from an empty Collection) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs 2011-03-02 05:35:53 UTC (rev 5413) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs 2011-03-02 22:20:24 UTC (rev 5414) @@ -1,5 +1,5 @@ +using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -82,6 +82,8 @@ // Nulls generate different query plans. X = variable generates a different query depending on if variable is null or not. if (param.Value == null) _string.Append("NULL"); + if (param.Value is ICollection && ((ICollection)param.Value).Count == 0) + _string.Append("EmptyList"); else _string.Append(param.Name); } Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs 2011-03-02 05:35:53 UTC (rev 5413) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessContains.cs 2011-03-02 22:20:24 UTC (rev 5414) @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections; +using System.Linq; using NHibernate.Hql.Ast; using Remotion.Data.Linq.Clauses.ResultOperators; @@ -18,7 +19,15 @@ if (source is HqlParameter) { // This is an "in" style statement - tree.SetRoot(tree.TreeBuilder.In(itemExpression, source)); + if (IsEmptyList((HqlParameter)source, queryModelVisitor.VisitorParameters)) + { + // if the list is empty the expression will always be false, so generate "1 = 0" + tree.SetRoot(tree.TreeBuilder.Equality(tree.TreeBuilder.Constant(1), tree.TreeBuilder.Constant(0))); + } + else + { + tree.SetRoot(tree.TreeBuilder.In(itemExpression, source)); + } } else { @@ -39,5 +48,12 @@ { return node.NodesPreOrder.Single(n => n is HqlRange).Children.Single(n => n is HqlAlias) as HqlAlias; } + + private static bool IsEmptyList(HqlParameter source, VisitorParameters parameters) + { + var parameterName = source.NodesPreOrder.Single(n => n is HqlIdent).AstNode.Text; + var parameterValue = parameters.ConstantToParameterMap.Single(p => p.Value.Name == parameterName).Key.Value; + return ((ICollection)parameterValue).Count == 0; + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs 2011-03-02 05:35:53 UTC (rev 5413) +++ trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs 2011-03-02 22:20:24 UTC (rev 5414) @@ -327,6 +327,18 @@ } [Test] + public void UsersWithEmptyList_NH2400() + { + var names = new List<string>(); + + var query = (from user in db.Users + where names.Contains(user.Name) + select user).ToList(); + + Assert.That(query.Count, Is.EqualTo(0)); + } + + [Test] public void WhenTheSourceOfConstantIsICollectionThenNoThrows() { ICollection<string> names = new List<string> {"ayende", "rahien"}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |