IGNITE-4359 .NET: Support DateTime properties in LINQ
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/3bae8589 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/3bae8589 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/3bae8589 Branch: refs/heads/ignite-4450 Commit: 3bae858986f78dbb288cf39d970b3f163c3da247 Parents: 126ab60 Author: Pavel Tupitsyn <[email protected]> Authored: Tue Dec 20 15:32:39 2016 +0300 Committer: Pavel Tupitsyn <[email protected]> Committed: Tue Dec 20 15:32:39 2016 +0300 ---------------------------------------------------------------------- .../Cache/Query/CacheLinqTest.cs | 24 ++++++++++---- .../Impl/CacheQueryExpressionVisitor.cs | 12 ++----- .../Apache.Ignite.Linq/Impl/MethodVisitor.cs | 34 ++++++++++++++++++-- 3 files changed, 52 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/3bae8589/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs index 1ac7fa7..46979ef 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs @@ -63,7 +63,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query private bool _runDbConsole; /** */ - private static readonly DateTime StartDateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc); + private static readonly DateTime StartDateTime = new DateTime(2000, 5, 17, 15, 4, 5, DateTimeKind.Utc); /// <summary> /// Fixture set up. @@ -111,7 +111,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query roleCache[new RoleKey(1, 101)] = new Role {Name = "Role_1", Date = StartDateTime}; roleCache[new RoleKey(2, 102)] = new Role {Name = "Role_2", Date = StartDateTime.AddYears(1)}; - roleCache[new RoleKey(3, 103)] = new Role {Name = null, Date = StartDateTime.AddYears(2)}; + roleCache[new RoleKey(3, 103)] = new Role {Name = null, Date = StartDateTime.AddHours(5432)}; } /// <summary> @@ -123,7 +123,8 @@ namespace Apache.Ignite.Core.Tests.Cache.Query { BinaryConfiguration = new BinaryConfiguration(typeof(Person), typeof(Organization), typeof(Address), typeof(Role), typeof(RoleKey), typeof(Numerics)), - GridName = gridName + GridName = gridName, + JvmOptions = { "-Duser.timezone=UTC" } }; } @@ -735,7 +736,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query // Test retrieval var dates = roles.OrderBy(x => x.Value.Date).Select(x => x.Value.Date); - var expDates = new[] {StartDateTime, StartDateTime.AddYears(1), StartDateTime.AddYears(2)}; + var expDates = GetRoleCache().Select(x => x.Value.Date).OrderBy(x => x).ToArray(); Assert.AreEqual(expDates, dates.ToArray()); // Filtering @@ -748,10 +749,21 @@ namespace Apache.Ignite.Core.Tests.Cache.Query join person in persons on role.Value.Date equals person.Value.Birthday select person; - Assert.AreEqual(RoleCount, join.Count()); + Assert.AreEqual(2, join.Count()); // Functions - Assert.AreEqual("01 01 2000 00:00:00", dates.Select(x => x.ToString("DD MM YYYY HH:mm:ss")).First()); + var strings = dates.Select(x => x.ToString("dd MM YYYY HH:mm:ss")).ToArray(); + Assert.AreEqual(new[] {"17 05 2000 15:04:05", "29 12 2000 23:04:05", "17 05 2001 15:04:05"}, strings); + + // Properties + Assert.AreEqual(new[] {2000, 2000, 2001}, dates.Select(x => x.Year).ToArray()); + Assert.AreEqual(new[] {5, 12, 5}, dates.Select(x => x.Month).ToArray()); + Assert.AreEqual(new[] {17, 29, 17}, dates.Select(x => x.Day).ToArray()); + Assert.AreEqual(expDates.Select(x => x.DayOfYear).ToArray(), dates.Select(x => x.DayOfYear).ToArray()); + Assert.AreEqual(expDates.Select(x => x.DayOfWeek).ToArray(), dates.Select(x => x.DayOfWeek).ToArray()); + Assert.AreEqual(new[] {15, 23, 15}, dates.Select(x => x.Hour).ToArray()); + Assert.AreEqual(new[] { 4, 4, 4 }, dates.Select(x => x.Minute).ToArray()); + Assert.AreEqual(new[] { 5, 5, 5 }, dates.Select(x => x.Second).ToArray()); } /// <summary> http://git-wip-us.apache.org/repos/asf/ignite/blob/3bae8589/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs index 8231053..1f9da1c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs @@ -276,17 +276,9 @@ namespace Apache.Ignite.Linq.Impl { // Field hierarchy is flattened (Person.Address.Street is just Street), append as is, do not call Visit. - // Special case: string.Length - if (expression.Member == MethodVisitor.StringLength) - { - ResultBuilder.Append("length("); - - VisitMember((MemberExpression) expression.Expression); - - ResultBuilder.Append(")"); - + // Property call (string.Length, DateTime.Month, etc). + if (MethodVisitor.VisitPropertyCall(expression, this)) return expression; - } // Special case: grouping if (VisitGroupByMember(expression.Expression)) http://git-wip-us.apache.org/repos/asf/ignite/blob/3bae8589/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/MethodVisitor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/MethodVisitor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/MethodVisitor.cs index 3c8acc7..e83c448 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/MethodVisitor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/MethodVisitor.cs @@ -29,8 +29,19 @@ namespace Apache.Ignite.Linq.Impl /// </summary> internal static class MethodVisitor { - /// <summary> The string length method. </summary> - public static readonly MemberInfo StringLength = typeof (string).GetProperty("Length"); + /// <summary> Property visitors. </summary> + private static readonly Dictionary<MemberInfo, string> Properties = new Dictionary<MemberInfo, string> + { + {typeof(string).GetProperty("Length"), "length"}, + {typeof(DateTime).GetProperty("Year"), "year"}, + {typeof(DateTime).GetProperty("Month"), "month"}, + {typeof(DateTime).GetProperty("Day"), "day_of_month"}, + {typeof(DateTime).GetProperty("DayOfYear"), "day_of_year"}, + {typeof(DateTime).GetProperty("DayOfWeek"), "-1 + day_of_week"}, + {typeof(DateTime).GetProperty("Hour"), "hour"}, + {typeof(DateTime).GetProperty("Minute"), "minute"}, + {typeof(DateTime).GetProperty("Second"), "second"} + }; /// <summary> Method visit delegate. </summary> private delegate void VisitMethodDelegate(MethodCallExpression expression, CacheQueryExpressionVisitor visitor); @@ -103,6 +114,25 @@ namespace Apache.Ignite.Linq.Impl }.ToDictionary(x => x.Key, x => x.Value); /// <summary> + /// Visits the property call expression. + /// </summary> + public static bool VisitPropertyCall(MemberExpression expression, CacheQueryExpressionVisitor visitor) + { + string funcName; + + if (!Properties.TryGetValue(expression.Member, out funcName)) + return false; + + visitor.ResultBuilder.Append(funcName).Append('('); + + visitor.Visit(expression.Expression); + + visitor.ResultBuilder.Append(')'); + + return true; + } + + /// <summary> /// Visits the method call expression. /// </summary> public static void VisitMethodCall(MethodCallExpression expression, CacheQueryExpressionVisitor visitor)
