From: <ric...@us...> - 2011-05-22 16:34:18
|
Revision: 5855 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5855&view=rev Author: ricbrown Date: 2011-05-22 16:34:11 +0000 (Sun, 22 May 2011) Log Message: ----------- NH-2683: Updated QueryOver Concat() extension to allow arbitrary parameters Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/Projections.cs trunk/nhibernate/src/NHibernate/Criterion/ProjectionsExtensions.cs trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs Modified: trunk/nhibernate/src/NHibernate/Criterion/Projections.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/Projections.cs 2011-05-22 14:58:58 UTC (rev 5854) +++ trunk/nhibernate/src/NHibernate/Criterion/Projections.cs 2011-05-22 16:34:11 UTC (rev 5855) @@ -451,5 +451,25 @@ { return Projections.Sum(ExpressionProcessor.FindMemberExpression(expression.Body)); } + + /// <summary> + /// Project SQL function concat() + /// Note: throws an exception outside of a QueryOver expression + /// </summary> + public static string Concat(params string[] strings) + { + throw new Exception("Not to be used directly - use inside QueryOver expression"); + } + + internal static IProjection ProcessConcat(MethodCallExpression methodCallExpression) + { + NewArrayExpression args = (NewArrayExpression)methodCallExpression.Arguments[0]; + IProjection[] projections = new IProjection[args.Expressions.Count]; + + for (var i=0; i<args.Expressions.Count; i++) + projections[i] = ExpressionProcessor.FindMemberProjection(args.Expressions[i]); + + return Projections.SqlFunction("concat", NHibernateUtil.String, projections); + } } } Modified: trunk/nhibernate/src/NHibernate/Criterion/ProjectionsExtensions.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/ProjectionsExtensions.cs 2011-05-22 14:58:58 UTC (rev 5854) +++ trunk/nhibernate/src/NHibernate/Criterion/ProjectionsExtensions.cs 2011-05-22 16:34:11 UTC (rev 5855) @@ -341,22 +341,6 @@ } /// <summary> - /// Project SQL function concat() - /// Note: throws an exception outside of a QueryOver expression - /// </summary> - public static string ConcatStr(this string stringProperty, string value) - { - throw new Exception("Not to be used directly - use inside QueryOver expression"); - } - - internal static IProjection ProcessConcatStr(MethodCallExpression methodCallExpression) - { - IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]); - object concatWithValue = ExpressionProcessor.FindValue(methodCallExpression.Arguments[1]); - return Projections.SqlFunction("concat", NHibernateUtil.String, property, Projections.Constant(string.Empty), Projections.Constant(concatWithValue)); - } - - /// <summary> /// Project SQL function mod() /// Note: throws an exception outside of a QueryOver expression /// </summary> Modified: trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-05-22 14:58:58 UTC (rev 5854) +++ trunk/nhibernate/src/NHibernate/Impl/ExpressionProcessor.cs 2011-05-22 16:34:11 UTC (rev 5855) @@ -109,7 +109,7 @@ RegisterCustomProjection(() => ProjectionsExtensions.CharIndex(string.Empty, string.Empty, 0), ProjectionsExtensions.ProcessCharIndex); RegisterCustomProjection(() => ProjectionsExtensions.Coalesce<DBNull>(null, null), ProjectionsExtensions.ProcessCoalesce); RegisterCustomProjection(() => ProjectionsExtensions.Coalesce<int>(null, 0), ProjectionsExtensions.ProcessCoalesce); - RegisterCustomProjection(() => ProjectionsExtensions.ConcatStr(string.Empty, string.Empty), ProjectionsExtensions.ProcessConcatStr); + RegisterCustomProjection(() => Projections.Concat(null), Projections.ProcessConcat); RegisterCustomProjection(() => ProjectionsExtensions.Mod(0, 0), ProjectionsExtensions.ProcessMod); RegisterCustomProjection(() => ProjectionsExtensions.Abs(default(int)), ProjectionsExtensions.ProcessIntAbs); RegisterCustomProjection(() => ProjectionsExtensions.Abs(default(double)), ProjectionsExtensions.ProcessDoubleAbs); @@ -163,6 +163,9 @@ /// </summary> public static IProjection FindMemberProjection(Expression expression) { + if (!IsMemberExpression(expression)) + return Projections.Constant(FindValue(expression)); + if (expression is UnaryExpression) { UnaryExpression unaryExpression = (UnaryExpression)expression; @@ -309,6 +312,9 @@ private static bool IsMemberExpression(Expression expression) { + if (expression is ParameterExpression) + return true; + if (expression is MemberExpression) { MemberExpression memberExpression = (MemberExpression)expression; @@ -319,6 +325,13 @@ if (memberExpression.Expression.NodeType == ExpressionType.Parameter) return true; + if (IsNullableOfT(memberExpression.Member.DeclaringType)) + { + // it's a Nullable<T>, so ignore any .Value + if (memberExpression.Member.Name == "Value") + return IsMemberExpression(memberExpression.Expression); + } + if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess) { // if the member has a null value, it was an alias @@ -337,6 +350,25 @@ return IsMemberExpression(unaryExpression.Operand); } + if (expression is MethodCallExpression) + { + MethodCallExpression methodCallExpression = (MethodCallExpression)expression; + + string signature = Signature(methodCallExpression.Method); + if (_customProjectionProcessors.ContainsKey(signature)) + return true; + + if (methodCallExpression.Method.Name == "GetType" + || methodCallExpression.Method.Name == "get_Item" + || methodCallExpression.Method.Name == "First") + { + if (IsMemberExpression(methodCallExpression.Object)) + return true; + + return EvaluatesToNull(methodCallExpression.Object); + } + } + return false; } Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2011-05-22 14:58:58 UTC (rev 5854) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/IntegrationFixture.cs 2011-05-22 16:34:11 UTC (rev 5855) @@ -575,7 +575,7 @@ { s.Save(new Person() { Name = "p1", BirthDate = new DateTime(2009, 08, 07), Age = 90 }); s.Save(new Person() { Name = "p2", BirthDate = new DateTime(2008, 07, 06) }); - s.Save(new Person() { Name = "p3", BirthDate = new DateTime(2007, 06, 05) }); + s.Save(new Person() { Name = "pP3", BirthDate = new DateTime(2007, 06, 05) }); t.Commit(); } @@ -614,6 +614,29 @@ sqrtOfAge.GetType().Should().Be(typeof(double)); string.Format("{0:0.00}", sqrtOfAge).Should().Be("9.49"); } + + using (ISession s = OpenSession()) + { + var names = + s.QueryOver<Person>() + .Where(p => p.Name == "pP3") + .Select(p => p.Name.Lower(), p => p.Name.Upper()) + .SingleOrDefault<object[]>(); + + names[0].Should().Be("pp3"); + names[1].Should().Be("PP3"); + } + + using (ISession s = OpenSession()) + { + var name = + s.QueryOver<Person>() + .Where(p => p.Name == "p1") + .Select(p => Projections.Concat(p.Name, ", ", p.Name)) + .SingleOrDefault<string>(); + + name.Should().Be("p1, p1"); + } } [Test] Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs 2011-05-22 14:58:58 UTC (rev 5854) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/Lambda/RestrictionsFixture.cs 2011-05-22 16:34:11 UTC (rev 5855) @@ -277,7 +277,7 @@ .Add(Restrictions.Eq(Projections.SqlFunction("locate", NHibernateUtil.String, Projections.Constant("e"), Projections.Property("Name"), Projections.Constant(1)), 2)) .Add(Restrictions.Eq(Projections.SqlFunction("coalesce", NHibernateUtil.Object, Projections.Property("Name"), Projections.Constant("not-null-val")), "test")) .Add(Restrictions.Eq(Projections.SqlFunction("coalesce", NHibernateUtil.Object, Projections.Property("NullableIsParent"), Projections.Constant(true)), true)) - .Add(Restrictions.Eq(Projections.SqlFunction("concat", NHibernateUtil.String, Projections.Property("Name"), Projections.Constant(string.Empty), Projections.Constant("A")), "testA")) + .Add(Restrictions.Eq(Projections.SqlFunction("concat", NHibernateUtil.String, Projections.Property("Name"), Projections.Constant(", "), Projections.Property("Name")), "test, test")) .Add(Restrictions.Eq(Projections.SqlFunction("mod", NHibernateUtil.Int32, Projections.Property("Height"), Projections.Constant(10)), 0)); IQueryOver<Person> actual = @@ -299,7 +299,7 @@ .And(p => p.Name.CharIndex("e", 1) == 2) .And(p => p.Name.Coalesce("not-null-val") == "test") .And(p => p.NullableIsParent.Coalesce(true) == true) - .And(p => p.Name.ConcatStr("A") == "testA") + .And(p => Projections.Concat(p.Name, ", ", p.Name) == "test, test") .And(p => p.Height.Mod(10) == 0); AssertCriteriaAreEqual(expected, actual); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |