You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2017/07/04 11:51:33 UTC
[1/3] ignite git commit: IGNITE-5532 .NET: Split CacheLinqTest into
partial classes
Repository: ignite
Updated Branches:
refs/heads/master 15613e2af -> 84c7427a5
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
new file mode 100644
index 0000000..c4ef11f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
@@ -0,0 +1,350 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System;
+ using System.Linq;
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests the empty query.
+ /// </summary>
+ [Test]
+ public void TestEmptyQuery()
+ {
+ // There are both persons and organizations in the same cache, but query should only return specific type
+ Assert.AreEqual(PersonCount, GetPersonCache().AsCacheQueryable().ToArray().Length);
+ Assert.AreEqual(RoleCount, GetRoleCache().AsCacheQueryable().ToArray().Length);
+ }
+
+ /// <summary>
+ /// Tests the single field query.
+ /// </summary>
+ [Test]
+ public void TestSingleFieldQuery()
+ {
+ var cache = GetPersonCache().AsCacheQueryable();
+
+ // Multiple values
+ Assert.AreEqual(new[] { 0, 1, 2 },
+ cache.Where(x => x.Key < 3).Select(x => x.Value.Address.Zip).ToArray());
+
+ // Single value
+ Assert.AreEqual(0, cache.Where(x => x.Key < 0).Select(x => x.Value.Age).FirstOrDefault());
+ Assert.AreEqual(3, cache.Where(x => x.Key == 3).Select(x => x.Value.Age).FirstOrDefault());
+ Assert.AreEqual(3, cache.Where(x => x.Key == 3).Select(x => x.Value).Single().Age);
+ Assert.AreEqual(3, cache.Select(x => x.Key).Single(x => x == 3));
+ Assert.AreEqual(7,
+ cache.Select(x => x.Value)
+ .Where(x => x.Age == 7)
+ .Select(x => x.Address)
+ .Where(x => x.Zip > 0)
+ .Select(x => x.Zip)
+ .Single());
+ }
+
+ /// <summary>
+ /// Tests the field projection.
+ /// </summary>
+ [Test]
+ public void TestFieldProjection()
+ {
+ var cache = GetPersonCache().AsCacheQueryable();
+
+ // Project whole cache entry to anonymous class
+ Assert.AreEqual(5, cache.Where(x => x.Key == 5).Select(x => new { Foo = x }).Single().Foo.Key);
+ }
+
+ /// <summary>
+ /// Tests the multi field query.
+ /// </summary>
+ [Test]
+ public void TestMultiFieldQuery()
+ {
+ var cache = GetPersonCache().AsCacheQueryable();
+
+ // Test anonymous type (ctor invoke)
+ var data = cache
+ .Select(x => new { Id = x.Key + 20, Age_ = x.Value.Age + 10, Addr = x.Value.Address })
+ .Where(x => x.Id < 25)
+ .ToArray();
+
+ Assert.AreEqual(5, data.Length);
+
+ foreach (var t in data)
+ {
+ Assert.AreEqual(t.Age_ - 10, t.Id - 20);
+ Assert.AreEqual(t.Age_ - 10, t.Addr.Zip);
+ }
+ }
+
+ /// <summary>
+ /// Tests the scalar query.
+ /// </summary>
+ [Test]
+ public void TestScalarQuery()
+ {
+ var cache = GetPersonCache().AsCacheQueryable();
+
+ Assert.AreEqual(PersonCount - 1, cache.Max(x => x.Value.Age));
+ Assert.AreEqual(0, cache.Min(x => x.Value.Age));
+
+ Assert.AreEqual(21, cache.Where(x => x.Key > 5 && x.Value.Age < 9).Select(x => x.Value.Age).Sum());
+
+ Assert.AreEqual(PersonCount, cache.Count());
+ Assert.AreEqual(PersonCount, cache.Count(x => x.Key < PersonCount));
+ }
+
+ /// <summary>
+ /// Tests conditions.
+ /// </summary>
+ [Test]
+ public void TestConditions()
+ {
+ TestConditional("even", "odd");
+ TestConditional(new Address { Zip = 99999 }, new Address { Zip = 7777777 }, (a1, a2) => a1.Zip == a2.Zip);
+ TestConditional(new RoleKey(int.MaxValue, long.MinValue), new RoleKey(int.MinValue, long.MaxValue));
+ TestConditionalWithNullableStructs<int>();
+ TestConditionalWithNullableStructs<uint>();
+ TestConditionalWithNullableStructs<Guid>();
+ TestConditionalWithNullableStructs<byte>();
+ TestConditionalWithNullableStructs<sbyte>();
+ TestConditionalWithNullableStructs<short>();
+ TestConditionalWithNullableStructs<ushort>();
+ TestConditionalWithNullableStructs<bool>();
+ TestConditionalWithNullableStructs<long>();
+ TestConditionalWithNullableStructs<ulong>();
+ TestConditionalWithNullableStructs<double>();
+ TestConditionalWithNullableStructs<float>();
+ TestConditionalWithNullableStructs<decimal>();
+ TestConditionalWithNullableStructs<DateTime>(DateTime.UtcNow);
+
+ var charException = Assert.Throws<NotSupportedException>(() => TestConditionalWithNullableStructs<char>());
+ Assert.AreEqual("Type is not supported for SQL mapping: System.Char", charException.Message);
+
+ var roles = GetRoleCache().AsCacheQueryable();
+ CheckFunc(x => x.Value.Name ?? "def_name", roles);
+ }
+
+ /// <summary>
+ /// Tests the SelectMany from field collection.
+ /// </summary>
+ [Test]
+ public void TestSelectManySameTable()
+ {
+ var persons = GetPersonCache().AsCacheQueryable();
+
+ // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+ var ex = Assert.Throws<NotSupportedException>(() => persons.SelectMany(x => x.Value.Name).ToArray());
+
+ Assert.IsTrue(ex.Message.StartsWith("FROM clause must be IQueryable: from Char"));
+ }
+
+ /// <summary>
+ /// Tests nulls.
+ /// </summary>
+ [Test]
+ public void TestNulls()
+ {
+ var roles = GetRoleCache().AsCacheQueryable();
+
+ var nullNameRole = roles.Single(x => x.Value.Name == null);
+ Assert.AreEqual(null, nullNameRole.Value.Name);
+
+ var nonNullNameRoles = roles.Where(x => x.Value.Name != null);
+ Assert.AreEqual(RoleCount - 1, nonNullNameRoles.Count());
+ }
+
+ /// <summary>
+ /// Tests aliases.
+ /// </summary>
+ [Test]
+ public void TestAliases()
+ {
+ var cache = GetPersonCache().AsCacheQueryable();
+
+ var res = cache.Where(x => x.Key == 1)
+ .Select(x => new { X = x.Value.AliasTest, Y = x.Value.Address.AliasTest })
+ .Single();
+
+ Assert.AreEqual(new { X = -1, Y = 1 }, res);
+ }
+
+ /// <summary>
+ /// Tests the cache of primitive types.
+ /// </summary>
+ [Test]
+ public void TestPrimitiveCache()
+ {
+ // Create partitioned cache
+ var cache = Ignition.GetIgnite()
+ .GetOrCreateCache<int, string>(
+ new CacheConfiguration("primitiveCache",
+ new QueryEntity(typeof(int), typeof(string)))
+ {
+ CacheMode = CacheMode.Replicated,
+ SqlEscapeAll = GetSqlEscapeAll()
+ });
+
+ var qry = cache.AsCacheQueryable();
+
+ // Populate
+ const int count = 100;
+ cache.PutAll(Enumerable.Range(0, count).ToDictionary(x => x, x => x.ToString()));
+
+ // Test
+ Assert.AreEqual(count, qry.ToArray().Length);
+ Assert.AreEqual(10, qry.Where(x => x.Key < 10).ToArray().Length);
+ Assert.AreEqual(1, qry.Count(x => x.Value.Contains("99")));
+ }
+
+ /// <summary>
+ /// Tests the local query.
+ /// </summary>
+ [Test]
+ public void TestLocalQuery()
+ {
+ // Create partitioned cache
+ var cache =
+ Ignition.GetIgnite().GetOrCreateCache<int, int>(new CacheConfiguration("partCache", typeof(int))
+ {
+ SqlEscapeAll = GetSqlEscapeAll()
+ });
+
+ // Populate
+ const int count = 100;
+ cache.PutAll(Enumerable.Range(0, count).ToDictionary(x => x, x => x));
+
+ // Non-local query returns all records
+ Assert.AreEqual(count, cache.AsCacheQueryable(false).ToArray().Length);
+
+ // Local query returns only some of the records
+ var localCount = cache.AsCacheQueryable(true).ToArray().Length;
+ Assert.Less(localCount, count);
+ Assert.Greater(localCount, 0);
+ }
+
+ /// <summary>
+ /// Tests the table name inference.
+ /// </summary>
+ [Test]
+ public void TestTableNameInference()
+ {
+ // Try with multi-type cache: explicit type is required
+ var cache = GetCacheOf<IPerson>();
+
+ Assert.Throws<CacheException>(() => cache.AsCacheQueryable());
+
+ var names = cache.AsCacheQueryable(false, "Person").Select(x => x.Value.Name).ToArray();
+
+ Assert.AreEqual(PersonCount, names.Length);
+
+ // With single-type cache, interface inference works
+ var roleCache = Ignition.GetIgnite().GetCache<object, IRole>(RoleCacheName).AsCacheQueryable();
+
+ var roleNames = roleCache.Select(x => x.Value.Name).OrderBy(x => x).ToArray();
+
+ CollectionAssert.AreEquivalent(new[] { "Role_1", "Role_2", null }, roleNames);
+
+ // Check non-queryable cache
+ var nonQueryableCache = Ignition.GetIgnite().GetOrCreateCache<Role, Person>("nonQueryable");
+
+ Assert.Throws<CacheException>(() => nonQueryableCache.AsCacheQueryable());
+ }
+
+ /// <summary>
+ /// Tests the distributed joins.
+ /// </summary>
+ [Test]
+ public void TestDistributedJoins()
+ {
+ var ignite = Ignition.GetIgnite();
+
+ // Create and populate partitioned caches
+ var personCache = ignite.CreateCache<int, Person>(new CacheConfiguration("partitioned_persons",
+ new QueryEntity(typeof(int), typeof(Person)))
+ {
+ SqlEscapeAll = GetSqlEscapeAll()
+ });
+
+ personCache.PutAll(GetSecondPersonCache().ToDictionary(x => x.Key, x => x.Value));
+
+ var roleCache = ignite.CreateCache<int, Role>(new CacheConfiguration("partitioned_roles",
+ new QueryEntity(typeof(int), typeof(Role)))
+ {
+ SqlEscapeAll = GetSqlEscapeAll()
+ });
+
+ roleCache.PutAll(GetRoleCache().ToDictionary(x => x.Key.Foo, x => x.Value));
+
+ // Test non-distributed join: returns partial results
+ var persons = personCache.AsCacheQueryable();
+ var roles = roleCache.AsCacheQueryable();
+
+ var res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
+ .ToArray();
+
+ Assert.AreEqual(res.Length, RoleCount);
+
+ // Test distributed join: returns complete results
+ persons = personCache.AsCacheQueryable(new QueryOptions { EnableDistributedJoins = true });
+ roles = roleCache.AsCacheQueryable(new QueryOptions { EnableDistributedJoins = true });
+
+ res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
+ .ToArray();
+
+ Assert.AreEqual(RoleCount, res.Length);
+ }
+
+ /// <summary>
+ /// Tests the query timeout.
+ /// </summary>
+ [Test]
+ public void TestTimeout()
+ {
+ var persons = GetPersonCache().AsCacheQueryable(new QueryOptions
+ {
+ Timeout = TimeSpan.FromMilliseconds(1),
+ EnableDistributedJoins = true
+ });
+
+ // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+ var ex = Assert.Throws<CacheException>(() =>
+ persons.SelectMany(p => GetRoleCache().AsCacheQueryable()).ToArray());
+
+ Assert.IsTrue(ex.ToString().Contains("QueryCancelledException: The query was cancelled while executing."));
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Numerics.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Numerics.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Numerics.cs
new file mode 100644
index 0000000..3f973aa
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Numerics.cs
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System;
+ using System.Linq;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests numerics.
+ /// </summary>
+ [Test]
+ public void TestNumerics()
+ {
+ var cache = Ignition.GetIgnite()
+ .GetOrCreateCache<int, Numerics>(new CacheConfiguration("numerics", typeof(Numerics))
+ {
+ SqlEscapeAll = GetSqlEscapeAll()
+ });
+
+ for (var i = 0; i < 100; i++)
+ cache[i] = new Numerics(((double)i - 50) / 3);
+
+ var query = cache.AsCacheQueryable().Select(x => x.Value);
+
+ var bytes = query.Select(x => x.Byte);
+ var sbytes = query.Select(x => x.Sbyte);
+ var shorts = query.Select(x => x.Short);
+ var ushorts = query.Select(x => x.Ushort);
+ var ints = query.Select(x => x.Int);
+ var uints = query.Select(x => x.Uint);
+ var longs = query.Select(x => x.Long);
+ var ulongs = query.Select(x => x.Ulong);
+ var doubles = query.Select(x => x.Double);
+ var decimals = query.Select(x => x.Decimal);
+ var floats = query.Select(x => x.Float);
+
+ CheckFunc(x => Math.Abs(x), doubles);
+ CheckFunc(x => Math.Abs((sbyte)x), bytes);
+ CheckFunc(x => Math.Abs(x), sbytes);
+ CheckFunc(x => Math.Abs(x), shorts);
+ CheckFunc(x => Math.Abs((short)x), ushorts);
+ CheckFunc(x => Math.Abs(x), ints);
+ CheckFunc(x => Math.Abs((int)x), uints);
+ CheckFunc(x => Math.Abs(x), longs);
+ CheckFunc(x => Math.Abs((long)x), ulongs);
+ CheckFunc(x => Math.Abs(x), decimals);
+ CheckFunc(x => Math.Abs(x), floats);
+
+ CheckFunc(x => Math.Acos(x), doubles);
+ CheckFunc(x => Math.Asin(x), doubles);
+ CheckFunc(x => Math.Atan(x), doubles);
+ CheckFunc(x => Math.Atan2(x, 0.5), doubles);
+
+ CheckFunc(x => Math.Ceiling(x), doubles);
+ CheckFunc(x => Math.Ceiling(x), decimals);
+
+ CheckFunc(x => Math.Cos(x), doubles);
+ CheckFunc(x => Math.Cosh(x), doubles);
+ CheckFunc(x => Math.Exp(x), doubles);
+
+ CheckFunc(x => Math.Floor(x), doubles);
+ CheckFunc(x => Math.Floor(x), decimals);
+
+ CheckFunc(x => Math.Log(x), doubles);
+ CheckFunc(x => Math.Log10(x), doubles);
+
+ CheckFunc(x => Math.Pow(x, 3.7), doubles);
+
+ CheckFunc(x => Math.Round(x), doubles);
+ CheckFunc(x => Math.Round(x, 3), doubles);
+ CheckFunc(x => Math.Round(x), decimals);
+ CheckFunc(x => Math.Round(x, 3), decimals);
+
+ CheckFunc(x => Math.Sign(x), doubles);
+ CheckFunc(x => Math.Sign(x), decimals);
+ CheckFunc(x => Math.Sign(x), floats);
+ CheckFunc(x => Math.Sign(x), ints);
+ CheckFunc(x => Math.Sign(x), longs);
+ CheckFunc(x => Math.Sign(x), shorts);
+ CheckFunc(x => Math.Sign(x), sbytes);
+
+ CheckFunc(x => Math.Sin(x), doubles);
+ CheckFunc(x => Math.Sinh(x), doubles);
+ CheckFunc(x => Math.Sqrt(x), doubles);
+ CheckFunc(x => Math.Tan(x), doubles);
+ CheckFunc(x => Math.Tanh(x), doubles);
+
+ CheckFunc(x => Math.Truncate(x), doubles);
+ CheckFunc(x => Math.Truncate(x), decimals);
+
+ // Operators
+ CheckFunc(x => x * 7, doubles);
+ CheckFunc(x => x / 7, doubles);
+ CheckFunc(x => x % 7, doubles);
+ CheckFunc(x => x + 7, doubles);
+ CheckFunc(x => x - 7, doubles);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Strings.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Strings.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Strings.cs
new file mode 100644
index 0000000..7457d0a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Strings.cs
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text.RegularExpressions;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests strings.
+ /// </summary>
+ [Test]
+ public void TestStrings()
+ {
+ var strings = GetSecondPersonCache().AsCacheQueryable().Select(x => x.Value.Name);
+
+ CheckFunc(x => x.ToLower(), strings);
+ CheckFunc(x => x.ToUpper(), strings);
+ CheckFunc(x => x.StartsWith("Person_9"), strings);
+ CheckFunc(x => x.EndsWith("7"), strings);
+ CheckFunc(x => x.Contains("son_3"), strings);
+ CheckFunc(x => x.Length, strings);
+
+ CheckFunc(x => x.IndexOf("9"), strings);
+ CheckFunc(x => x.IndexOf("7", 4), strings);
+
+ CheckFunc(x => x.Substring(4), strings);
+ CheckFunc(x => x.Substring(4, 5), strings);
+
+ CheckFunc(x => x.Trim(), strings);
+ CheckFunc(x => x.Trim('P'), strings);
+ var toTrim = new[] { 'P' };
+ CheckFunc(x => x.Trim(toTrim), strings);
+ CheckFunc(x => x.Trim(new List<char> { 'P' }.ToArray()), strings);
+ CheckFunc(x => x.Trim('3'), strings);
+ CheckFunc(x => x.TrimStart('P'), strings);
+ CheckFunc(x => x.TrimStart(toTrim), strings);
+ CheckFunc(x => x.TrimStart('3'), strings);
+ Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimStart('P', 'e'), strings));
+ CheckFunc(x => x.TrimEnd('P'), strings);
+ CheckFunc(x => x.TrimEnd(toTrim), strings);
+ CheckFunc(x => x.TrimEnd('3'), strings);
+ var toTrimFails = new[] { 'P', 'c' };
+ Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.Trim(toTrimFails), strings));
+ Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimStart(toTrimFails), strings));
+ Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimEnd(toTrimFails), strings));
+
+ CheckFunc(x => Regex.Replace(x, @"son.\d", "kele!"), strings);
+ CheckFunc(x => x.Replace("son", ""), strings);
+ CheckFunc(x => x.Replace("son", "kele"), strings);
+
+ // Concat
+ CheckFunc(x => x + x, strings);
+
+ // String + int
+ CheckFunc(x => x + 10, strings);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSimpleName.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSimpleName.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSimpleName.cs
new file mode 100644
index 0000000..1665a64
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSimpleName.cs
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using Apache.Ignite.Core.Binary;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// LINQ test with simple name mapper.
+ /// </summary>
+ [TestFixture]
+ public class CacheLinqTestSimpleName : CacheLinqTest
+ {
+ /** <inheritdoc /> */
+ protected override IBinaryNameMapper GetNameMapper()
+ {
+ return BinaryBasicNameMapper.SimpleNameInstance;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSqlEscapeAll.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSqlEscapeAll.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSqlEscapeAll.cs
new file mode 100644
index 0000000..6b05f7b
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTestSqlEscapeAll.cs
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using NUnit.Framework;
+
+ /// <summary>
+ /// LINQ test with simple name mapper.
+ /// </summary>
+ [TestFixture]
+ public class CacheLinqTestSqlEscapeAll : CacheLinqTest
+ {
+ /** <inheritdoc /> */
+ protected override bool GetSqlEscapeAll()
+ {
+ return true;
+ }
+ }
+}
\ No newline at end of file
[3/3] ignite git commit: IGNITE-5532 .NET: Split CacheLinqTest into
partial classes
Posted by pt...@apache.org.
IGNITE-5532 .NET: Split CacheLinqTest into partial classes
This closes #2226
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/84c7427a
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/84c7427a
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/84c7427a
Branch: refs/heads/master
Commit: 84c7427a53a8e1712b1d0b763d7539c9cb844cb6
Parents: 15613e2
Author: Sergey Stronchinskiy <gu...@gmail.com>
Authored: Tue Jul 4 14:51:25 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Jul 4 14:51:25 2017 +0300
----------------------------------------------------------------------
.../Apache.Ignite.Core.Tests.csproj | 17 +-
.../Cache/Query/CacheLinqTest.cs | 2084 ------------------
.../Cache/Query/CacheLinqTestSimpleName.cs | 35 -
.../Cache/Query/CacheLinqTestSqlEscapeAll.cs | 34 -
.../Query/Linq/CacheLinqTest.Aggregates.cs | 91 +
.../Cache/Query/Linq/CacheLinqTest.Base.cs | 506 +++++
.../Query/Linq/CacheLinqTest.CompiledQuery.cs | 215 ++
.../Cache/Query/Linq/CacheLinqTest.Contains.cs | 128 ++
.../Cache/Query/Linq/CacheLinqTest.Custom.cs | 107 +
.../Cache/Query/Linq/CacheLinqTest.DateTime.cs | 89 +
.../Cache/Query/Linq/CacheLinqTest.Functions.cs | 211 ++
.../Query/Linq/CacheLinqTest.Introspection.cs | 145 ++
.../Linq/CacheLinqTest.Join.LocalCollection.cs | 182 ++
.../Cache/Query/Linq/CacheLinqTest.Join.cs | 310 +++
.../Cache/Query/Linq/CacheLinqTest.Misc.cs | 350 +++
.../Cache/Query/Linq/CacheLinqTest.Numerics.cs | 131 ++
.../Cache/Query/Linq/CacheLinqTest.Strings.cs | 91 +
.../Cache/Query/Linq/CacheLinqTestSimpleName.cs | 35 +
.../Query/Linq/CacheLinqTestSqlEscapeAll.cs | 34 +
19 files changed, 2639 insertions(+), 2156 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 09eac70..71631b2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -77,6 +77,17 @@
<Compile Include="Binary\BinarySelfTestSimpleName.cs" />
<Compile Include="Binary\EnumsTestOnline.cs" />
<Compile Include="Cache\PersistentStoreTest.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.CompiledQuery.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.DateTime.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.Aggregates.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.Join.LocalCollection.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.Strings.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.Functions.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.Numerics.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.Introspection.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.Misc.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.Custom.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.Contains.cs" />
<Compile Include="Deployment\GetAddressFunc.cs" />
<Compile Include="Deployment\PeerAssemblyLoadingAllApisTest.cs" />
<Compile Include="Deployment\PeerAssemblyLoadingVersioningTest.cs" />
@@ -110,8 +121,8 @@
<Compile Include="Cache\Query\CacheDmlQueriesTest.cs" />
<Compile Include="Cache\CacheAbstractTransactionalTest.cs" />
<Compile Include="Cache\Query\CacheDmlQueriesTestSimpleName.cs" />
- <Compile Include="Cache\Query\CacheLinqTestSqlEscapeAll.cs" />
- <Compile Include="Cache\Query\CacheLinqTestSimpleName.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTestSqlEscapeAll.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTestSimpleName.cs" />
<Compile Include="Cache\Query\CacheQueriesTestSimpleName.cs" />
<Compile Include="Cache\Query\Continuous\ContinuousQueryTest.cs" />
<Compile Include="Cache\Store\CacheStoreAdapterTest.cs" />
@@ -158,7 +169,7 @@
<Compile Include="Cache\CachePartitionedTest.cs" />
<Compile Include="Cache\CacheReplicatedAtomicTest.cs" />
<Compile Include="Cache\CacheReplicatedTest.cs" />
- <Compile Include="Cache\Query\CacheLinqTest.cs" />
+ <Compile Include="Cache\Query\Linq\CacheLinqTest.Base.cs" />
<Compile Include="Cache\Query\CacheQueriesCodeConfigurationTest.cs" />
<Compile Include="Cache\Query\Continuous\ContinuousQueryAbstractTest.cs" />
<Compile Include="Cache\Query\Continuous\ContinuousQueryAtomicBackupTest.cs" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/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
deleted file mode 100644
index e46ae0b..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
+++ /dev/null
@@ -1,2084 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// ReSharper disable SuspiciousTypeConversion.Global
-// ReSharper disable MemberCanBePrivate.Global
-// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
-// ReSharper disable UnusedAutoPropertyAccessor.Global
-// ReSharper disable StringIndexOfIsCultureSpecific.1
-// ReSharper disable StringIndexOfIsCultureSpecific.2
-// ReSharper disable StringCompareToIsCultureSpecific
-// ReSharper disable StringCompareIsCultureSpecific.1
-// ReSharper disable UnusedMemberInSuper.Global
-namespace Apache.Ignite.Core.Tests.Cache.Query
-{
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Text.RegularExpressions;
- using System.Threading;
- using Apache.Ignite.Core.Binary;
- using Apache.Ignite.Core.Cache;
- using Apache.Ignite.Core.Cache.Configuration;
- using Apache.Ignite.Core.Cache.Query;
- using Apache.Ignite.Core.Common;
- using Apache.Ignite.Linq;
- using NUnit.Framework;
-
- /// <summary>
- /// Tests LINQ.
- /// </summary>
- public class CacheLinqTest
- {
- /** Cache name. */
- private const string PersonOrgCacheName = "person_org";
-
- /** Cache name. */
- private const string PersonSecondCacheName = "person_cache";
-
- /** Role cache name. */
- private const string RoleCacheName = "role_cache";
-
- /** */
- private const int RoleCount = 3;
-
- /** */
- private const int PersonCount = 900;
-
- /** */
- private bool _runDbConsole;
-
- /** */
- private static readonly DateTime StartDateTime = new DateTime(2000, 5, 17, 15, 4, 5, DateTimeKind.Utc);
-
- /// <summary>
- /// Fixture set up.
- /// </summary>
- [TestFixtureSetUp]
- public void FixtureSetUp()
- {
- _runDbConsole = false; // set to true to open H2 console
-
- if (_runDbConsole)
- Environment.SetEnvironmentVariable("IGNITE_H2_DEBUG_CONSOLE", "true");
-
- Ignition.Start(GetConfig());
- Ignition.Start(GetConfig("grid2"));
-
- // Populate caches
- var cache = GetPersonCache();
- var personCache = GetSecondPersonCache();
-
- for (var i = 0; i < PersonCount; i++)
- {
- cache.Put(i, new Person(i, string.Format(" Person_{0} ", i))
- {
- Address = new Address {Zip = i, Street = "Street " + i, AliasTest = i},
- OrganizationId = i%2 + 1000,
- Birthday = StartDateTime.AddYears(i),
- AliasTest = -i
- });
-
- var i2 = i + PersonCount;
- personCache.Put(i2, new Person(i2, "Person_" + i2)
- {
- Address = new Address {Zip = i2, Street = "Street " + i2},
- OrganizationId = i%2 + 1000,
- Birthday = StartDateTime.AddYears(i)
- });
- }
-
- var orgCache = GetOrgCache();
-
- orgCache[1000] = new Organization {Id = 1000, Name = "Org_0"};
- orgCache[1001] = new Organization {Id = 1001, Name = "Org_1"};
- orgCache[1002] = new Organization {Id = 1002, Name = null};
-
- var roleCache = GetRoleCache();
-
- 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.AddHours(5432)};
- }
-
- /// <summary>
- /// Gets the configuration.
- /// </summary>
- private IgniteConfiguration GetConfig(string gridName = null)
- {
- return new IgniteConfiguration(TestUtils.GetTestConfiguration())
- {
- BinaryConfiguration = new BinaryConfiguration(typeof(Person),
- typeof(Organization), typeof(Address), typeof(Role), typeof(RoleKey), typeof(Numerics))
- {
- NameMapper = GetNameMapper()
- },
- IgniteInstanceName = gridName
- };
- }
-
- /// <summary>
- /// Gets the name mapper.
- /// </summary>
- protected virtual IBinaryNameMapper GetNameMapper()
- {
- return BinaryBasicNameMapper.FullNameInstance;
- }
-
- /// <summary>
- /// Gets the SqlEscapeAll setting.
- /// </summary>
- protected virtual bool GetSqlEscapeAll()
- {
- return false;
- }
-
- /// <summary>
- /// Fixture tear down.
- /// </summary>
- [TestFixtureTearDown]
- public void FixtureTearDown()
- {
- if (_runDbConsole)
- Thread.Sleep(Timeout.Infinite);
- Ignition.StopAll(true);
- }
-
- /// <summary>
- /// Tests the empty query.
- /// </summary>
- [Test]
- public void TestEmptyQuery()
- {
- // There are both persons and organizations in the same cache, but query should only return specific type
- Assert.AreEqual(PersonCount, GetPersonCache().AsCacheQueryable().ToArray().Length);
- Assert.AreEqual(RoleCount, GetRoleCache().AsCacheQueryable().ToArray().Length);
- }
-
- /// <summary>
- /// Tests where clause.
- /// </summary>
- [Test]
- public void TestWhere()
- {
- var cache = GetPersonCache().AsCacheQueryable();
-
- // Test const and var parameters
- const int age = 10;
- var key = 15;
-
- Assert.AreEqual(age, cache.Where(x => x.Value.Age < age).ToArray().Length);
- Assert.AreEqual(age, cache.Where(x => x.Value.Address.Zip < age).ToArray().Length);
- Assert.AreEqual(19, cache.Where(x => x.Value.Age > age && x.Value.Age < 30).ToArray().Length);
- Assert.AreEqual(20, cache.Where(x => x.Value.Age > age).Count(x => x.Value.Age < 30 || x.Value.Age == 50));
- Assert.AreEqual(key, cache.Where(x => x.Key < key).ToArray().Length);
- Assert.AreEqual(key, cache.Where(x => -x.Key > -key).ToArray().Length);
-
- Assert.AreEqual(1, GetRoleCache().AsCacheQueryable().Where(x => x.Key.Foo < 2).ToArray().Length);
- Assert.AreEqual(2, GetRoleCache().AsCacheQueryable().Where(x => x.Key.Bar > 2 && x.Value.Name != "11")
- .ToArray().Length);
- }
-
- /// <summary>
- /// Tests the single field query.
- /// </summary>
- [Test]
- public void TestSingleFieldQuery()
- {
- var cache = GetPersonCache().AsCacheQueryable();
-
- // Multiple values
- Assert.AreEqual(new[] {0, 1, 2},
- cache.Where(x => x.Key < 3).Select(x => x.Value.Address.Zip).ToArray());
-
- // Single value
- Assert.AreEqual(0, cache.Where(x => x.Key < 0).Select(x => x.Value.Age).FirstOrDefault());
- Assert.AreEqual(3, cache.Where(x => x.Key == 3).Select(x => x.Value.Age).FirstOrDefault());
- Assert.AreEqual(3, cache.Where(x => x.Key == 3).Select(x => x.Value).Single().Age);
- Assert.AreEqual(3, cache.Select(x => x.Key).Single(x => x == 3));
- Assert.AreEqual(7,
- cache.Select(x => x.Value)
- .Where(x => x.Age == 7)
- .Select(x => x.Address)
- .Where(x => x.Zip > 0)
- .Select(x => x.Zip)
- .Single());
- }
-
- /// <summary>
- /// Tests the field projection.
- /// </summary>
- [Test]
- public void TestFieldProjection()
- {
- var cache = GetPersonCache().AsCacheQueryable();
-
- // Project whole cache entry to anonymous class
- Assert.AreEqual(5, cache.Where(x => x.Key == 5).Select(x => new { Foo = x }).Single().Foo.Key);
- }
-
- /// <summary>
- /// Tests the multi field query.
- /// </summary>
- [Test]
- public void TestMultiFieldQuery()
- {
- var cache = GetPersonCache().AsCacheQueryable();
-
- // Test anonymous type (ctor invoke)
- var data = cache
- .Select(x => new {Id = x.Key + 20, Age_ = x.Value.Age + 10, Addr = x.Value.Address})
- .Where(x => x.Id < 25)
- .ToArray();
-
- Assert.AreEqual(5, data.Length);
-
- foreach (var t in data)
- {
- Assert.AreEqual(t.Age_ - 10, t.Id - 20);
- Assert.AreEqual(t.Age_ - 10, t.Addr.Zip);
- }
- }
-
- /// <summary>
- /// Tests the scalar query.
- /// </summary>
- [Test]
- public void TestScalarQuery()
- {
- var cache = GetPersonCache().AsCacheQueryable();
-
- Assert.AreEqual(PersonCount - 1, cache.Max(x => x.Value.Age));
- Assert.AreEqual(0, cache.Min(x => x.Value.Age));
-
- Assert.AreEqual(21, cache.Where(x => x.Key > 5 && x.Value.Age < 9).Select(x => x.Value.Age).Sum());
-
- Assert.AreEqual(PersonCount, cache.Count());
- Assert.AreEqual(PersonCount, cache.Count(x => x.Key < PersonCount));
- }
-
- /// <summary>
- /// Tests strings.
- /// </summary>
- [Test]
- public void TestStrings()
- {
- var strings = GetSecondPersonCache().AsCacheQueryable().Select(x => x.Value.Name);
-
- CheckFunc(x => x.ToLower(), strings);
- CheckFunc(x => x.ToUpper(), strings);
- CheckFunc(x => x.StartsWith("Person_9"), strings);
- CheckFunc(x => x.EndsWith("7"), strings);
- CheckFunc(x => x.Contains("son_3"), strings);
- CheckFunc(x => x.Length, strings);
-
- CheckFunc(x => x.IndexOf("9"), strings);
- CheckFunc(x => x.IndexOf("7", 4), strings);
-
- CheckFunc(x => x.Substring(4), strings);
- CheckFunc(x => x.Substring(4, 5), strings);
-
- CheckFunc(x => x.Trim(), strings);
- CheckFunc(x => x.Trim('P'), strings);
- var toTrim = new[] {'P'};
- CheckFunc(x => x.Trim(toTrim), strings);
- CheckFunc(x => x.Trim(new List<char> {'P'}.ToArray()), strings);
- CheckFunc(x => x.Trim('3'), strings);
- CheckFunc(x => x.TrimStart('P'), strings);
- CheckFunc(x => x.TrimStart(toTrim), strings);
- CheckFunc(x => x.TrimStart('3'), strings);
- Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimStart('P', 'e'), strings));
- CheckFunc(x => x.TrimEnd('P'), strings);
- CheckFunc(x => x.TrimEnd(toTrim), strings);
- CheckFunc(x => x.TrimEnd('3'), strings);
- var toTrimFails = new[] {'P', 'c'};
- Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.Trim(toTrimFails), strings));
- Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimStart(toTrimFails), strings));
- Assert.Throws<NotSupportedException>(() => CheckFunc(x => x.TrimEnd(toTrimFails), strings));
-
- CheckFunc(x => Regex.Replace(x, @"son.\d", "kele!"), strings);
- CheckFunc(x => x.Replace("son", ""), strings);
- CheckFunc(x => x.Replace("son", "kele"), strings);
-
- // Concat
- CheckFunc(x => x + x, strings);
-
- // String + int
- CheckFunc(x => x + 10, strings);
- }
-
- /// <summary>
- /// Tests aggregates.
- /// </summary>
- [Test]
- public void TestAggregates()
- {
- var cache = GetPersonCache().AsCacheQueryable();
-
- Assert.AreEqual(PersonCount, cache.Count());
- Assert.AreEqual(PersonCount, cache.Select(x => x.Key).Count());
- Assert.AreEqual(2, cache.Select(x => x.Value.OrganizationId).Distinct().Count());
-
- // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
- Assert.Throws<NotSupportedException>(() => cache.Select(x => new {x.Key, x.Value}).Count());
-
- // Min/max/sum/avg
- var ints = cache.Select(x => x.Key);
- Assert.AreEqual(0, ints.Min());
- Assert.AreEqual(PersonCount - 1, ints.Max());
- Assert.AreEqual(ints.ToArray().Sum(), ints.Sum());
- Assert.AreEqual((int)ints.ToArray().Average(), (int)ints.Average());
-
- var dupInts = ints.Select(x => x/10); // duplicate values
- CollectionAssert.AreEquivalent(dupInts.ToArray().Distinct().ToArray(), dupInts.Distinct().ToArray());
- Assert.AreEqual(dupInts.ToArray().Distinct().Sum(), dupInts.Distinct().Sum());
-
- // All/any
- Assert.IsFalse(ints.Where(x => x > -5).Any(x => x > PersonCount && x > 0));
- Assert.IsTrue(ints.Any(x => x < PersonCount / 2));
-
- // Skip/take
- var keys = cache.Select(x => x.Key).OrderBy(x => x);
- Assert.AreEqual(new[] {0, 1}, keys.Take(2).ToArray());
- Assert.AreEqual(new[] {1, 2}, keys.Skip(1).Take(2).ToArray());
- Assert.AreEqual(new[] {PersonCount - 2, PersonCount - 1}, keys.Skip(PersonCount - 2).ToArray());
- }
-
- /// <summary>
- /// Tests aggregates with all clause.
- /// </summary>
- [Test]
- public void TestAggregatesAll()
- {
- var ints = GetPersonCache().AsCacheQueryable().Select(x => x.Key);
-
- // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
- var ex = Assert.Throws<NotSupportedException>(() => ints.Where(x => x > -10)
- .All(x => x < PersonCount && x >= 0));
-
- Assert.IsTrue(ex.Message.StartsWith("Operator is not supported: All"));
- }
-
- /// <summary>
- /// Tests conditions.
- /// </summary>
- [Test]
- public void TestConditions()
- {
- TestConditional("even", "odd");
- TestConditional(new Address { Zip = 99999 }, new Address { Zip = 7777777 }, (a1, a2) => a1.Zip == a2.Zip);
- TestConditional(new RoleKey(int.MaxValue, long.MinValue), new RoleKey(int.MinValue, long.MaxValue));
- TestConditionalWithNullableStructs<int>();
- TestConditionalWithNullableStructs<uint>();
- TestConditionalWithNullableStructs<Guid>();
- TestConditionalWithNullableStructs<byte>();
- TestConditionalWithNullableStructs<sbyte>();
- TestConditionalWithNullableStructs<short>();
- TestConditionalWithNullableStructs<ushort>();
- TestConditionalWithNullableStructs<bool>();
- TestConditionalWithNullableStructs<long>();
- TestConditionalWithNullableStructs<ulong>();
- TestConditionalWithNullableStructs<double>();
- TestConditionalWithNullableStructs<float>();
- TestConditionalWithNullableStructs<decimal>();
- TestConditionalWithNullableStructs<DateTime>(DateTime.UtcNow);
-
- var charException = Assert.Throws<NotSupportedException>(() => TestConditionalWithNullableStructs<char>());
- Assert.AreEqual("Type is not supported for SQL mapping: System.Char", charException.Message);
-
- var roles = GetRoleCache().AsCacheQueryable();
- CheckFunc(x => x.Value.Name ?? "def_name", roles);
- }
-
- /// <summary>
- /// Tests the same cache join.
- /// </summary>
- [Test]
- public void TestSameCacheJoin()
- {
- // Select persons in specific organization
- var organizations = GetOrgCache().AsCacheQueryable();
- var persons = GetPersonCache().AsCacheQueryable();
-
- var res = persons.Join(organizations, person => person.Value.OrganizationId + 3, org => org.Value.Id + 3,
- (person, org) => new {Person = person.Value, Org = org.Value})
- .Where(x => x.Org.Name == "Org_1")
- .ToList();
-
- Assert.AreEqual(PersonCount / 2, res.Count);
-
- Assert.IsTrue(res.All(r => r.Person.OrganizationId == r.Org.Id));
-
- // Test full projection (selects pair of ICacheEntry)
- var res2 = persons.Join(organizations, person => person.Value.OrganizationId - 1, org => org.Value.Id - 1,
- (person, org) => new {Person = person, Org = org})
- .Where(x => x.Org.Value.Name.ToLower() == "org_0")
- .ToList();
-
- Assert.AreEqual(PersonCount / 2, res2.Count);
- }
-
- /// <summary>
- /// Tests the multi key join.
- /// </summary>
- [Test]
- public void TestMultiKeyJoin()
- {
- var organizations = GetOrgCache().AsCacheQueryable();
- var persons = GetPersonCache().AsCacheQueryable();
-
- var multiKey =
- from person in persons
- join org in organizations on
- new { OrgId = person.Value.OrganizationId, person.Key } equals
- new { OrgId = org.Value.Id, Key = org.Key - 1000 }
- where person.Key == 1
- select new { PersonName = person.Value.Name, OrgName = org.Value.Name };
-
- Assert.AreEqual(" Person_1 ", multiKey.Single().PersonName);
- }
-
- /// <summary>
- /// Tests the cross cache join.
- /// </summary>
- [Test]
- public void TestCrossCacheJoin()
- {
- var persons = GetPersonCache().AsCacheQueryable();
- var roles = GetRoleCache().AsCacheQueryable();
-
- var res = persons.Join(roles, person => person.Key, role => role.Key.Foo, (person, role) => role)
- .OrderBy(x => x.Key.Bar)
- .ToArray();
-
- Assert.AreEqual(RoleCount, res.Length);
- Assert.AreEqual(101, res[0].Key.Bar);
- }
-
- /// <summary>
- /// Tests the cross cache join.
- /// </summary>
- [Test]
- public void TestCrossCacheJoinInline()
- {
- var res = GetPersonCache().AsCacheQueryable().Join(GetRoleCache().AsCacheQueryable(),
- person => person.Key, role => role.Key.Foo, (person, role) => role)
- .OrderBy(x => x.Key.Bar).ToArray();
-
- Assert.AreEqual(RoleCount, res.Length);
- Assert.AreEqual(101, res[0].Key.Bar);
- }
-
- /// <summary>
- /// Tests the multi cache join.
- /// </summary>
- [Test]
- public void TestMultiCacheJoin()
- {
- var organizations = GetOrgCache().AsCacheQueryable();
- var persons = GetPersonCache().AsCacheQueryable();
- var roles = GetRoleCache().AsCacheQueryable();
-
- var res = roles.Join(persons, role => role.Key.Foo, person => person.Key,
- (role, person) => new {person, role})
- .Join(organizations, pr => pr.person.Value.OrganizationId, org => org.Value.Id,
- (pr, org) => new {org, pr.person, pr.role}).ToArray();
-
- Assert.AreEqual(RoleCount, res.Length);
- }
-
- /// <summary>
- /// Tests the multi cache join subquery.
- /// </summary>
- [Test]
- public void TestMultiCacheJoinSubquery()
- {
- var organizations = GetOrgCache().AsCacheQueryable().Where(x => x.Key == 1001);
- var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key < 20);
- var roles = GetRoleCache().AsCacheQueryable().Where(x => x.Key.Foo >= 0);
-
- var res = roles.Join(persons, role => role.Key.Foo, person => person.Key,
- (role, person) => new {person, role})
- .Join(organizations, pr => pr.person.Value.OrganizationId, org => org.Value.Id,
- (pr, org) => new {org, pr.person, pr.role}).ToArray();
-
- Assert.AreEqual(2, res.Length);
- }
-
- /// <summary>
- /// Tests the outer join.
- /// </summary>
- [Test]
- public void TestOuterJoin()
- {
- var persons = GetPersonCache().AsCacheQueryable();
- var roles = GetRoleCache().AsCacheQueryable();
-
- var res = persons.Join(roles.Where(r => r.Key.Bar > 0).DefaultIfEmpty(),
- person => person.Key, role => role.Key.Foo,
- (person, role) => new
- {
- PersonName = person.Value.Name,
- RoleName = role.Value.Name
- })
- .Where(x => x.PersonName != " ")
- .ToArray();
-
- Assert.AreEqual(PersonCount, res.Length);
- }
-
- /// <summary>
- /// Tests the subquery join.
- /// </summary>
- [Test]
- public void TestSubqueryJoin()
- {
- var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key >= 0);
-
- var orgs = GetOrgCache().AsCacheQueryable().Where(x => x.Key > 10);
-
- var qry1 = persons.Join(orgs,
- p => p.Value.OrganizationId,
- o => o.Value.Id,
- (p, o) => p)
- .Where(x => x.Key >= 0)
- .ToList();
-
- Assert.AreEqual(PersonCount, qry1.Count);
-
- // With selector inline
- var qry2 = persons
- .Join(orgs.Select(orgEntry => orgEntry.Key),
- e => e.Value.OrganizationId,
- i => i,
- (e, i) => e)
- .ToList();
-
- Assert.AreEqual(PersonCount, qry2.Count);
-
- // With selector from variable
- var innerSequence = orgs
- .Select(orgEntry => orgEntry.Key);
-
- var qry3 = persons
- .Join(innerSequence,
- e => e.Value.OrganizationId,
- i => i,
- (e, i) => e)
- .ToList();
-
- Assert.AreEqual(PersonCount, qry3.Count);
- }
-
- /// <summary>
- /// Tests the join with local collection.
- /// </summary>
- [Test]
- public void TestLocalJoin()
- {
- var persons = GetPersonCache().AsCacheQueryable();
- var orgs = GetOrgCache().AsCacheQueryable();
-
- var localOrgs = orgs
- .Select(e => e.Value)
- .ToArray();
-
- var allOrganizationIds = localOrgs
- .Select(e => e.Id)
- .ToArray();
-
- // Join with local collection
- var qry1 = persons.Join(allOrganizationIds,
- pe => pe.Value.OrganizationId,
- i => i,
- (pe, o) => pe
- )
- .ToArray();
-
- Assert.AreEqual(PersonCount, qry1.Length);
-
- // Join using expression in innerKeySelector
- var qry2 = persons.Join(allOrganizationIds,
- pe => pe.Value.OrganizationId,
- i => i + 1 - 1,
- (pe, o) => pe
- )
- .ToArray();
-
- Assert.AreEqual(PersonCount, qry2.Length);
-
- // Local collection subquery
- var qry3 = persons.Join(localOrgs.Select(e => e.Id),
- pe => pe.Value.OrganizationId,
- i => i,
- (pe, o) => pe
- )
- .ToArray();
-
- Assert.AreEqual(PersonCount, qry3.Length);
-
- // Compiled query
- var qry4 = CompiledQuery.Compile(() => persons.Join(allOrganizationIds,
- pe => pe.Value.OrganizationId,
- i => i,
- (pe, o) => pe
- ));
-
- Assert.AreEqual(PersonCount, qry4().Count());
-
- // Compiled query with outer join
- var qry4A = CompiledQuery.Compile(() => persons.Join(new int[] {}.DefaultIfEmpty(),
- pe => pe.Value.OrganizationId,
- i => i,
- (pe, o) => pe
- ));
-
- Assert.AreEqual(PersonCount, qry4A().Count());
-
- // Compiled query
- var qry5 = CompiledQuery.Compile(() => persons.Join(new[] { -1, -2 }.DefaultIfEmpty(),
- pe => pe.Value.OrganizationId,
- i => i,
- (pe, o) => pe
- ));
-
- Assert.AreEqual(PersonCount, qry5().Count());
-
- // Outer join
- var qry6 = persons.Join(new[] { -1, -2 }.DefaultIfEmpty(),
- pe => pe.Value.OrganizationId,
- i => i,
- (pe, o) => pe
- )
- .ToArray();
-
- Assert.AreEqual(PersonCount, qry6.Length);
-
- // Join with local list
- var qry7 = persons.Join(new List<int> {1000, 1001, 1002, 1003},
- pe => pe.Value.OrganizationId,
- i => i,
- (pe, o) => pe
- )
- .ToArray();
-
- Assert.AreEqual(PersonCount, qry7.Length);
-
- // Join with local list variable
- var list = new List<int> { 1000, 1001, 1002, 1003 };
- var qry8 = persons.Join(list,
- pe => pe.Value.OrganizationId,
- i => i,
- (pe, o) => pe
- )
- .ToArray();
-
- Assert.AreEqual(PersonCount, qry8.Length);
- }
-
- /// <summary>
- /// Tests the compiled query containing join with local collection passed as parameter.
- /// </summary>
- [Test]
- [Ignore("IGNITE-5404")]
- public void TestLocalJoinCompiledQueryParameter()
- {
- var persons = GetPersonCache().AsCacheQueryable();
- var orgs = GetOrgCache().AsCacheQueryable();
-
- var localOrgs = orgs
- .Select(e => e.Value)
- .ToArray();
-
- var allOrganizationIds = localOrgs
- .Select(e => e.Id)
- .ToArray();
-
- // Join with local collection passed as parameter
- var qry1 = CompiledQuery.Compile((IEnumerable<int> lc) => persons.Join(lc,
- pe => pe.Value.OrganizationId,
- i => i,
- (pe, o) => pe
- ));
-
- Assert.AreEqual(PersonCount, qry1(allOrganizationIds).Count());
-
- //Compiled query with outer join
- var qry2 = CompiledQuery.Compile((IEnumerable<int> lc) => persons.Join(lc.DefaultIfEmpty(),
- pe => pe.Value.OrganizationId,
- i => i,
- (pe, o) => pe
- ));
-
- Assert.AreEqual(PersonCount, qry2(new[] { -11 }).Count());
- }
-
- /// <summary>
- /// Tests the invalid join.
- /// </summary>
- [Test]
- public void TestInvalidJoin()
- {
- var localComplexTypeCollection = GetOrgCache().AsCacheQueryable()
- .Select(e => e.Value)
- .ToArray();
-
- // Join on non-IQueryable with complex(not supported) type
- var ex = Assert.Throws<NotSupportedException>(() =>
- // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
- {
- GetPersonCache().AsCacheQueryable().Join(localComplexTypeCollection, p => p.Value.OrganizationId,
- o => o.Id, (p, o) => p).ToList();
- });
-
- Assert.IsTrue(ex.Message.StartsWith("Not supported item type for Join with local collection"));
- }
-
- /// <summary>
- /// Tests query with multiple from clause.
- /// </summary>
- [Test]
- public void TestMultipleFrom()
- {
- var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key < PersonCount);
- var roles = GetRoleCache().AsCacheQueryable().Where(x => x.Value.Name != "1");
-
- var all = persons.SelectMany(person => roles.Select(role => new { role, person }));
- Assert.AreEqual(RoleCount * PersonCount, all.Count());
-
- var filtered =
- from person in persons
- from role in roles
- where person.Key == role.Key.Foo
- select new {Person = person.Value.Name, Role = role.Value.Name};
-
- var res = filtered.ToArray();
-
- Assert.AreEqual(RoleCount, res.Length);
- }
-
- /// <summary>
- /// Tests query with multiple from clause with inline query sources.
- /// </summary>
- [Test]
- public void TestMultipleFromInline()
- {
- var filtered =
- from person in GetPersonCache().AsCacheQueryable()
- from role in GetRoleCache().AsCacheQueryable()
- where person.Key == role.Key.Foo
- select new {Person = person.Value.Name, Role = role.Value.Name};
-
- var res = filtered.ToArray();
-
- Assert.AreEqual(RoleCount, res.Length);
- }
-
- /// <summary>
- /// Tests the join of a table to itself.
- /// </summary>
- [Test]
- public void TestSelfJoin()
- {
- // Different queryables
- var p1 = GetPersonCache().AsCacheQueryable();
- var p2 = GetPersonCache().AsCacheQueryable();
-
- var qry = p1.Join(p2, x => x.Value.Age, x => x.Key, (x, y) => x.Key);
- Assert.AreEqual(PersonCount, qry.ToArray().Distinct().Count());
-
- // Same queryables
- var qry2 = p1.Join(p1, x => x.Value.Age, x => x.Key, (x, y) => x.Key);
- Assert.AreEqual(PersonCount, qry2.ToArray().Distinct().Count());
- }
-
- /// <summary>
- /// Tests the join of a table to itself with inline queryable.
- /// </summary>
- [Test]
- public void TestSelfJoinInline()
- {
- var qry = GetPersonCache().AsCacheQueryable().Join(GetPersonCache().AsCacheQueryable(),
- x => x.Value.Age, x => x.Key, (x, y) => x.Key);
-
- Assert.AreEqual(PersonCount, qry.ToArray().Distinct().Count());
- }
-
- /// <summary>
- /// Tests the SelectMany from field collection.
- /// </summary>
- [Test]
- public void TestSelectManySameTable()
- {
- var persons = GetPersonCache().AsCacheQueryable();
-
- // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
- var ex = Assert.Throws<NotSupportedException>(() => persons.SelectMany(x => x.Value.Name).ToArray());
-
- Assert.IsTrue(ex.Message.StartsWith("FROM clause must be IQueryable: from Char"));
- }
-
- /// <summary>
- /// Tests the group by.
- /// </summary>
- [Test]
- public void TestGroupBy()
- {
- var persons = GetPersonCache().AsCacheQueryable();
- var orgs = GetOrgCache().AsCacheQueryable();
-
- // Simple, unordered
- CollectionAssert.AreEquivalent(new[] {1000, 1001},
- persons.GroupBy(x => x.Value.OrganizationId).Select(x => x.Key).ToArray());
-
- // Aggregate
- Assert.AreEqual(1000,
- persons.GroupBy(x => x.Value.OrganizationId).Select(x => x.Key).OrderBy(x => x).First());
-
- // Ordering and count
- var res1 =
- from p in persons
- orderby p.Value.Name
- group p by p.Value.OrganizationId
- into gs
- orderby gs.Key
- where gs.Count() > 10
- select new {Count = gs.Count(), OrgId = gs.Key, AvgAge = gs.Average(x => x.Value.Age)};
-
- var resArr = res1.ToArray();
-
- Assert.AreEqual(new[]
- {
- new {Count = PersonCount/2, OrgId = 1000, AvgAge = (double) PersonCount/2 - 1},
- new {Count = PersonCount/2, OrgId = 1001, AvgAge = (double) PersonCount/2}
- }, resArr);
-
- // Join and sum
- var res2 = persons.Join(orgs.Where(o => o.Key > 10), p => p.Value.OrganizationId, o => o.Key,
- (p, o) => new {p, o})
- .GroupBy(x => x.o.Value.Name)
- .Select(g => new {Org = g.Key, AgeSum = g.Select(x => x.p.Value.Age).Sum()});
-
- var resArr2 = res2.ToArray();
-
- Assert.AreEqual(new[]
- {
- new {Org = "Org_0", AgeSum = persons.Where(x => x.Value.OrganizationId == 1000).Sum(x => x.Value.Age)},
- new {Org = "Org_1", AgeSum = persons.Where(x => x.Value.OrganizationId == 1001).Sum(x => x.Value.Age)}
- }, resArr2);
- }
-
- /// <summary>
- /// Tests the union.
- /// </summary>
- [Test]
- public void TestUnion()
- {
- // Direct union
- var persons = GetPersonCache().AsCacheQueryable();
- var persons2 = GetSecondPersonCache().AsCacheQueryable();
-
- var res = persons.Union(persons2).ToArray();
-
- Assert.AreEqual(PersonCount * 2, res.Length);
-
- // Subquery
- var roles = GetRoleCache().AsCacheQueryable().Select(x => -x.Key.Foo);
- var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Union(roles).ToArray();
-
- Assert.AreEqual(RoleCount + PersonCount, ids.Length);
- }
-
- /// <summary>
- /// Tests intersect.
- /// </summary>
- [Test]
- public void TestIntersect()
- {
- // Direct intersect
- var persons = GetPersonCache().AsCacheQueryable();
- var persons2 = GetSecondPersonCache().AsCacheQueryable();
-
- var res = persons.Intersect(persons2).ToArray();
-
- Assert.AreEqual(0, res.Length);
-
- // Subquery
- var roles = GetRoleCache().AsCacheQueryable().Select(x => x.Key.Foo);
- var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Intersect(roles).ToArray();
-
- Assert.AreEqual(RoleCount, ids.Length);
- }
-
- /// <summary>
- /// Tests except.
- /// </summary>
- [Test]
- public void TestExcept()
- {
- // Direct except
- var persons = GetPersonCache().AsCacheQueryable();
- var persons2 = GetSecondPersonCache().AsCacheQueryable();
-
- var res = persons.Except(persons2).ToArray();
-
- Assert.AreEqual(PersonCount, res.Length);
-
- // Subquery
- var roles = GetRoleCache().AsCacheQueryable().Select(x => x.Key.Foo);
- var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Except(roles).ToArray();
-
- Assert.AreEqual(PersonCount - RoleCount, ids.Length);
- }
-
- /// <summary>
- /// Tests ordering.
- /// </summary>
- [Test]
- public void TestOrdering()
- {
- var persons = GetPersonCache().AsCacheQueryable()
- .OrderByDescending(x => x.Key)
- .ThenBy(x => x.Value.Age)
- .ToArray();
-
- Assert.AreEqual(Enumerable.Range(0, PersonCount).Reverse().ToArray(),
- persons.Select(x => x.Key).ToArray());
-
- var personsByOrg = GetPersonCache().AsCacheQueryable()
- .Join(GetOrgCache().AsCacheQueryable(), p => p.Value.OrganizationId, o => o.Value.Id,
- (p, o) => new
- {
- PersonId = p.Key,
- PersonName = p.Value.Name.ToUpper(),
- OrgName = o.Value.Name
- })
- .OrderBy(x => x.OrgName.ToLower())
- .ThenBy(x => x.PersonName)
- .ToArray();
-
- var expectedIds = Enumerable.Range(0, PersonCount)
- .OrderBy(x => (x%2).ToString())
- .ThenBy(x => x.ToString())
- .ToArray();
-
- var actualIds = personsByOrg.Select(x => x.PersonId).ToArray();
-
- Assert.AreEqual(expectedIds, actualIds);
- }
-
- /// <summary>
- /// Tests IEnumerable.Contains.
- /// </summary>
- [Test]
- public void TestContains()
- {
- var cache = GetPersonCache().AsCacheQueryable();
- var orgCache = GetOrgCache().AsCacheQueryable();
-
- var keys = new[] { 1, 2, 3 };
- var emptyKeys = new int[0];
-
- var bigNumberOfKeys = 10000;
- var aLotOfKeys = Enumerable.Range(-bigNumberOfKeys + 10 - PersonCount, bigNumberOfKeys + PersonCount)
- .ToArray();
- var hashSetKeys = new HashSet<int>(keys);
- var defferedCollection = Enumerable.Range(1, 10)
- .Select(i => new {Id = i})
- .Select(arg => arg.Id);
-
- CheckWhereFunc(cache, e => new[] { 1, 2, 3 }.Contains(e.Key));
- CheckWhereFunc(cache, e => emptyKeys.Contains(e.Key));
- CheckWhereFunc(cache, e => new int[0].Contains(e.Key));
- CheckWhereFunc(cache, e => new int[0].Contains(e.Key));
- CheckWhereFunc(cache, e => new List<int> { 1, 2, 3 }.Contains(e.Key));
- CheckWhereFunc(cache, e => new List<int>(keys).Contains(e.Key));
- CheckWhereFunc(cache, e => aLotOfKeys.Contains(e.Key));
- CheckWhereFunc(cache, e => hashSetKeys.Contains(e.Key));
- CheckWhereFunc(cache, e => !keys.Contains(e.Key));
- CheckWhereFunc(cache, e => defferedCollection.Contains(e.Key));
- CheckWhereFunc(orgCache, e => new[] { "Org_1", "NonExistentName", null }.Contains(e.Value.Name));
- CheckWhereFunc(orgCache, e => !new[] { "Org_1", "NonExistentName", null }.Contains(e.Value.Name));
- CheckWhereFunc(orgCache, e => new[] { "Org_1", null, null }.Contains(e.Value.Name));
- CheckWhereFunc(orgCache, e => !new[] { "Org_1", null, null }.Contains(e.Value.Name));
- CheckWhereFunc(orgCache, e => new string[] { null }.Contains(e.Value.Name));
- CheckWhereFunc(orgCache, e => !new string[] { null }.Contains(e.Value.Name));
- CheckWhereFunc(orgCache, e => !new string[] { null, null }.Contains(e.Value.Name));
- CheckWhereFunc(orgCache, e => new string[] { null, null }.Contains(e.Value.Name));
-
- //check passing a null object as collection
- int[] nullKeys = null;
- var nullKeysEntries = cache
- .Where(e => nullKeys.Contains(e.Key))
- .ToArray();
- Assert.AreEqual(0, nullKeysEntries.Length, "Evaluating 'null.Contains' should return zero results");
-
-
- Func<int[]> getKeysFunc = () => null;
- var funcNullKeyEntries = cache
- .Where(e => getKeysFunc().Contains(e.Key))
- .ToArray();
- Assert.AreEqual(0, funcNullKeyEntries.Length, "Evaluating 'null.Contains' should return zero results");
-
-
- // Check subselect from other cache
- var subSelectCount = cache
- .Count(entry => orgCache
- .Where(orgEntry => orgEntry.Value.Name == "Org_1")
- .Select(orgEntry => orgEntry.Key)
- .Contains(entry.Value.OrganizationId));
- var orgNumberOne = orgCache
- .Where(orgEntry => orgEntry.Value.Name == "Org_1")
- .Select(orgEntry => orgEntry.Key)
- .First();
- var subSelectCheckCount = cache.Count(entry => entry.Value.OrganizationId == orgNumberOne);
- Assert.AreEqual(subSelectCheckCount, subSelectCount, "subselecting another CacheQueryable failed");
-
- var ex = Assert.Throws<NotSupportedException>(() =>
- CompiledQuery.Compile((int[] k) => cache.Where(x => k.Contains(x.Key))));
- Assert.AreEqual("'Contains' clause on compiled query parameter is not supported.", ex.Message);
-
- // check subquery from another cache put in separate variable
- var orgIds = orgCache
- .Where(o => o.Value.Name == "Org_1")
- .Select(o => o.Key);
-
- var subQueryFromVar = cache
- .Where(x => orgIds.Contains(x.Value.OrganizationId))
- .ToArray();
-
- var subQueryInline = cache
- .Where(x => orgCache.Where(o => o.Value.Name == "Org_1")
- .Select(o => o.Key).Contains(x.Value.OrganizationId))
- .ToArray();
-
- Assert.AreEqual(subQueryInline.Length, subQueryFromVar.Length);
- }
-
- /// <summary>
- /// Tests nulls.
- /// </summary>
- [Test]
- public void TestNulls()
- {
- var roles = GetRoleCache().AsCacheQueryable();
-
- var nullNameRole = roles.Single(x => x.Value.Name == null);
- Assert.AreEqual(null, nullNameRole.Value.Name);
-
- var nonNullNameRoles = roles.Where(x => x.Value.Name != null);
- Assert.AreEqual(RoleCount - 1, nonNullNameRoles.Count());
- }
-
- /// <summary>
- /// Tests date time.
- /// </summary>
- [Test]
- public void TestDateTime()
- {
- var roles = GetRoleCache().AsCacheQueryable();
- var persons = GetPersonCache().AsCacheQueryable();
-
- // Invalid dateTime
- // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
- var ex = Assert.Throws<BinaryObjectException>(() =>
- roles.Where(x => x.Value.Date > DateTime.Now).ToArray());
- Assert.AreEqual("DateTime is not UTC. Only UTC DateTime can be used for interop with other platforms.",
- ex.Message);
-
- // Test retrieval
- var dates = roles.OrderBy(x => x.Value.Date).Select(x => x.Value.Date);
- var expDates = GetRoleCache().Select(x => x.Value.Date).OrderBy(x => x).ToArray();
- Assert.AreEqual(expDates, dates.ToArray());
-
- // Filtering
- Assert.AreEqual(1, persons.Count(x => x.Value.Birthday == StartDateTime));
- Assert.AreEqual(PersonCount, persons.Count(x => x.Value.Birthday >= StartDateTime));
- Assert.Greater(persons.Count(x => x.Value.Birthday > DateTime.UtcNow), 1);
-
- // Joins
- var join =
- from role in roles
- join person in persons on role.Value.Date equals person.Value.Birthday
- select person;
-
- Assert.AreEqual(2, join.Count());
-
- // Functions
- 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>
- /// Tests numerics.
- /// </summary>
- [Test]
- public void TestNumerics()
- {
- var cache = Ignition.GetIgnite()
- .GetOrCreateCache<int, Numerics>(new CacheConfiguration("numerics", typeof (Numerics))
- {
- SqlEscapeAll = GetSqlEscapeAll()
- });
-
- for (var i = 0; i < 100; i++)
- cache[i] = new Numerics(((double) i - 50)/3);
-
- var query = cache.AsCacheQueryable().Select(x => x.Value);
-
- var bytes = query.Select(x => x.Byte);
- var sbytes = query.Select(x => x.Sbyte);
- var shorts = query.Select(x => x.Short);
- var ushorts = query.Select(x => x.Ushort);
- var ints = query.Select(x => x.Int);
- var uints = query.Select(x => x.Uint);
- var longs = query.Select(x => x.Long);
- var ulongs = query.Select(x => x.Ulong);
- var doubles = query.Select(x => x.Double);
- var decimals = query.Select(x => x.Decimal);
- var floats = query.Select(x => x.Float);
-
- CheckFunc(x => Math.Abs(x), doubles);
- CheckFunc(x => Math.Abs((sbyte) x), bytes);
- CheckFunc(x => Math.Abs(x), sbytes);
- CheckFunc(x => Math.Abs(x), shorts);
- CheckFunc(x => Math.Abs((short) x), ushorts);
- CheckFunc(x => Math.Abs(x), ints);
- CheckFunc(x => Math.Abs((int) x), uints);
- CheckFunc(x => Math.Abs(x), longs);
- CheckFunc(x => Math.Abs((long) x), ulongs);
- CheckFunc(x => Math.Abs(x), decimals);
- CheckFunc(x => Math.Abs(x), floats);
-
- CheckFunc(x => Math.Acos(x), doubles);
- CheckFunc(x => Math.Asin(x), doubles);
- CheckFunc(x => Math.Atan(x), doubles);
- CheckFunc(x => Math.Atan2(x, 0.5), doubles);
-
- CheckFunc(x => Math.Ceiling(x), doubles);
- CheckFunc(x => Math.Ceiling(x), decimals);
-
- CheckFunc(x => Math.Cos(x), doubles);
- CheckFunc(x => Math.Cosh(x), doubles);
- CheckFunc(x => Math.Exp(x), doubles);
-
- CheckFunc(x => Math.Floor(x), doubles);
- CheckFunc(x => Math.Floor(x), decimals);
-
- CheckFunc(x => Math.Log(x), doubles);
- CheckFunc(x => Math.Log10(x), doubles);
-
- CheckFunc(x => Math.Pow(x, 3.7), doubles);
-
- CheckFunc(x => Math.Round(x), doubles);
- CheckFunc(x => Math.Round(x, 3), doubles);
- CheckFunc(x => Math.Round(x), decimals);
- CheckFunc(x => Math.Round(x, 3), decimals);
-
- CheckFunc(x => Math.Sign(x), doubles);
- CheckFunc(x => Math.Sign(x), decimals);
- CheckFunc(x => Math.Sign(x), floats);
- CheckFunc(x => Math.Sign(x), ints);
- CheckFunc(x => Math.Sign(x), longs);
- CheckFunc(x => Math.Sign(x), shorts);
- CheckFunc(x => Math.Sign(x), sbytes);
-
- CheckFunc(x => Math.Sin(x), doubles);
- CheckFunc(x => Math.Sinh(x), doubles);
- CheckFunc(x => Math.Sqrt(x), doubles);
- CheckFunc(x => Math.Tan(x), doubles);
- CheckFunc(x => Math.Tanh(x), doubles);
-
- CheckFunc(x => Math.Truncate(x), doubles);
- CheckFunc(x => Math.Truncate(x), decimals);
-
- // Operators
- CheckFunc(x => x*7, doubles);
- CheckFunc(x => x/7, doubles);
- CheckFunc(x => x%7, doubles);
- CheckFunc(x => x+7, doubles);
- CheckFunc(x => x-7, doubles);
- }
-
- /// <summary>
- /// Tests aliases.
- /// </summary>
- [Test]
- public void TestAliases()
- {
- var cache = GetPersonCache().AsCacheQueryable();
-
- var res = cache.Where(x => x.Key == 1)
- .Select(x => new {X = x.Value.AliasTest, Y = x.Value.Address.AliasTest})
- .Single();
-
- Assert.AreEqual(new {X = -1, Y = 1}, res);
- }
-
- /// <summary>
- /// Tests the compiled query with various constructs.
- /// </summary>
- [Test]
- public void TestCompiledQuery()
- {
- var persons = GetPersonCache().AsCacheQueryable();
- var roles = GetRoleCache().AsCacheQueryable();
-
- // Embedded args
- var qry0 = CompiledQuery.Compile(() => persons.Where(x => x.Key < 3 && x.Value.Name.Contains("son")));
- Assert.AreEqual(3, qry0().Count());
-
- // Lambda args
- var qry1 = CompiledQuery.Compile((int minKey, int take, int skip) => persons.Where(x => x.Key > minKey)
- .Take(take).Skip(skip));
- Assert.AreEqual(3, qry1(-1, 3, 1).GetAll().Count);
-
- qry1 = CompiledQuery.Compile((int skip, int take, int minKey) => persons.Where(x => x.Key > minKey)
- .Take(take).Skip(skip));
-
- Assert.AreEqual(5, qry1(2, 5, 20).GetAll().Count);
-
- // Mixed args
- var qry2 = CompiledQuery.Compile((int maxKey, int minKey) =>
- persons.Where(x => x.Key < maxKey
- && x.Value.Name.Contains("er")
- && x.Value.Age < maxKey
- && x.Key > minKey).Skip(2));
-
- Assert.AreEqual(6, qry2(10, 1).Count());
-
- // Join
- var qry3 = CompiledQuery.Compile(() =>
- roles.Join(persons, r => r.Key.Foo, p => p.Key, (r, p) => r.Value.Name));
-
- Assert.AreEqual(RoleCount, qry3().Count());
-
- // Join with subquery
- var qry4 = CompiledQuery.Compile(
- (int a, int b, string sep) =>
- roles
- .Where(x => x.Key.Bar > a)
- .OrderBy(x => x.Key.Bar)
- .Join(persons.Where(x => x.Key < b && x.Key > 0),
- r => r.Key.Foo,
- p => p.Value.Address.Zip,
- (r, p) => p.Value.Name + sep + r.Value.Name + "|")
- .Skip(a).Take(1000)
- );
-
- Assert.AreEqual(new[] { " Person_2 =Role_2|", " Person_3 =|"}, qry4(1, PersonCount, "=").ToArray());
-
- // Union
- var qry5 = CompiledQuery.Compile(() => roles.Select(x => -x.Key.Foo).Union(persons.Select(x => x.Key)));
-
- Assert.AreEqual(RoleCount + PersonCount, qry5().Count());
-
- // Projection
- var qry6 = CompiledQuery.Compile((int minAge) => persons
- .Select(x => x.Value)
- .Where(x => x.Age >= minAge)
- .Select(x => new { x.Name, x.Age })
- .OrderBy(x => x.Name));
-
- var res = qry6(PersonCount - 3).GetAll();
-
- Assert.AreEqual(3, res.Count);
- Assert.AreEqual(PersonCount - 3, res[0].Age);
- }
-
- /// <summary>
- /// Tests the compiled query overloads.
- /// </summary>
- [Test]
- public void TestCompiledQueryOverloads()
- {
- var cache = GetPersonCache().AsCacheQueryable();
-
- // const args are allowed
- Assert.AreEqual(5, CompiledQuery.Compile(() => cache.Where(x => x.Key < 5))().GetAll().Count);
-
- // 0 arg
- var qry0 = CompiledQuery.Compile(() => cache.Select(x => x.Value.Name));
- Assert.AreEqual(PersonCount, qry0().ToArray().Length);
-
- // 1 arg
- var qry1 = CompiledQuery.Compile((int k) => cache.Where(x => x.Key < k));
- Assert.AreEqual(3, qry1(3).ToArray().Length);
-
- // 1 arg twice
- var qry1T = CompiledQuery.Compile((int k) => cache.Where(x => x.Key < k && x.Value.Age < k));
- Assert.AreEqual(3, qry1T(3).ToArray().Length);
-
- // 2 arg
- var qry2 =
- CompiledQuery.Compile((int i, string s) => cache.Where(x => x.Key < i && x.Value.Name.StartsWith(s)));
- Assert.AreEqual(5, qry2(5, " Pe").ToArray().Length);
-
- // Changed param order
- var qry2R =
- CompiledQuery.Compile((string s, int i) => cache.Where(x => x.Key < i && x.Value.Name.StartsWith(s)));
- Assert.AreEqual(5, qry2R(" Pe", 5).ToArray().Length);
-
- // 3 arg
- var qry3 = CompiledQuery.Compile((int i, string s, double d) =>
- cache.Where(x => x.Value.Address.Zip > d && x.Key < i && x.Value.Name.Contains(s)));
- Assert.AreEqual(5, qry3(5, "son", -10).ToArray().Length);
-
- // 4 arg
- var qry4 = CompiledQuery.Compile((int a, int b, int c, int d) =>
- cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d));
- Assert.AreEqual(new[] {3, 4}, qry4(0, 1, 2, 5).ToArray());
-
- // 5 arg
- var qry5 = CompiledQuery.Compile((int a, int b, int c, int d, int e) =>
- cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e));
- Assert.AreEqual(new[] {3, 4}, qry5(0, 1, 2, 5, 6).ToArray());
-
- // 6 arg
- var qry6 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f) =>
- cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e && k < f));
- Assert.AreEqual(new[] {3, 4}, qry6(0, 1, 2, 5, 6, 7).ToArray());
-
- // 7 arg
- var qry7 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f, int g) =>
- cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e && k < f && k < g));
- Assert.AreEqual(new[] {3, 4}, qry7(0, 1, 2, 5, 6, 7, 8).ToArray());
-
- // 8 arg
- var qry8 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f, int g, int h) =>
- cache.Select(x => x.Key)
- .Where(k => k > a && k > b && k > c && k < d && k < e && k < f && k < g && k < h));
- Assert.AreEqual(new[] {3, 4}, qry8(0, 1, 2, 5, 6, 7, 8, 9).ToArray());
- }
-
- /// <summary>
- /// Tests the free-form compiled query, where user provides an array of arguments.
- /// </summary>
- [Test]
- public void TestCompiledQueryFreeform()
- {
- var cache = GetPersonCache().AsCacheQueryable();
-
- var qry = cache.Where(x => x.Key < 5);
-
- // Simple
- var compiled = CompiledQuery.Compile(qry);
-
- Assert.AreEqual(5, compiled(5).Count());
- Assert.AreEqual(6, compiled(6).Count());
-
- // Select
- var compiledSelect = CompiledQuery.Compile(qry.Select(x => x.Value.Name).OrderBy(x => x));
-
- Assert.AreEqual(3, compiledSelect(3).Count());
- Assert.AreEqual(" Person_0 ", compiledSelect(1).Single());
-
- // Join
- var compiledJoin = CompiledQuery.Compile(qry.Join(
- GetOrgCache().AsCacheQueryable().Where(x => x.Value.Name.StartsWith("Org")),
- p => p.Value.OrganizationId, o => o.Value.Id, (p, o) => o.Key));
-
- Assert.AreEqual(1000, compiledJoin("Org", 1).Single());
-
- // Many parameters
- var qry2 = cache.Where(x => x.Key < 3)
- .Where(x => x.Key > 0)
- .Where(x => x.Value.Name.Contains(""))
- .Where(x => x.Value.Address.Zip > 0)
- .Where(x => x.Value.Age == 7);
-
- var compiled2 = CompiledQuery.Compile(qry2);
-
- Assert.AreEqual(17, compiled2(18, 16, "ers", 13, 17).Single().Key);
- }
-
- /// <summary>
- /// Tests the cache of primitive types.
- /// </summary>
- [Test]
- public void TestPrimitiveCache()
- {
- // Create partitioned cache
- var cache = Ignition.GetIgnite()
- .GetOrCreateCache<int, string>(
- new CacheConfiguration("primitiveCache",
- new QueryEntity(typeof(int), typeof(string)))
- {
- CacheMode = CacheMode.Replicated,
- SqlEscapeAll = GetSqlEscapeAll()
- });
-
- var qry = cache.AsCacheQueryable();
-
- // Populate
- const int count = 100;
- cache.PutAll(Enumerable.Range(0, count).ToDictionary(x => x, x => x.ToString()));
-
- // Test
- Assert.AreEqual(count, qry.ToArray().Length);
- Assert.AreEqual(10, qry.Where(x => x.Key < 10).ToArray().Length);
- Assert.AreEqual(1, qry.Count(x => x.Value.Contains("99")));
- }
-
- /// <summary>
- /// Tests the local query.
- /// </summary>
- [Test]
- public void TestLocalQuery()
- {
- // Create partitioned cache
- var cache =
- Ignition.GetIgnite().GetOrCreateCache<int, int>(new CacheConfiguration("partCache", typeof (int))
- {
- SqlEscapeAll = GetSqlEscapeAll()
- });
-
- // Populate
- const int count = 100;
- cache.PutAll(Enumerable.Range(0, count).ToDictionary(x => x, x => x));
-
- // Non-local query returns all records
- Assert.AreEqual(count, cache.AsCacheQueryable(false).ToArray().Length);
-
- // Local query returns only some of the records
- var localCount = cache.AsCacheQueryable(true).ToArray().Length;
- Assert.Less(localCount, count);
- Assert.Greater(localCount, 0);
- }
-
- /// <summary>
- /// Tests the introspection.
- /// </summary>
- [Test]
- public void TestIntrospection()
- {
- var cache = GetPersonCache();
-
- // Check regular query
- var query = cache.AsCacheQueryable(new QueryOptions
- {
- Local = true,
- PageSize = 999,
- EnforceJoinOrder = true,
- Timeout = TimeSpan.FromSeconds(2.5),
- ReplicatedOnly = true,
- Colocated = true
- }).Where(x => x.Key > 10).ToCacheQueryable();
-
- Assert.AreEqual(cache.Name, query.CacheName);
- Assert.AreEqual(cache.Ignite, query.Ignite);
-
- var fq = query.GetFieldsQuery();
-
- Assert.AreEqual(
- GetSqlEscapeAll()
- ? "select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where (_T0.\"_KEY\" > ?)"
- : "select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where (_T0._KEY > ?)",
- fq.Sql);
-
- Assert.AreEqual(new[] {10}, fq.Arguments);
- Assert.IsTrue(fq.Local);
- Assert.AreEqual(PersonCount - 11, cache.QueryFields(fq).GetAll().Count);
- Assert.AreEqual(999, fq.PageSize);
- Assert.IsFalse(fq.EnableDistributedJoins);
- Assert.IsTrue(fq.EnforceJoinOrder);
- Assert.IsTrue(fq.ReplicatedOnly);
- Assert.IsTrue(fq.Colocated);
- Assert.AreEqual(TimeSpan.FromSeconds(2.5), fq.Timeout);
-
- var str = query.ToString();
- Assert.AreEqual(GetSqlEscapeAll()
- ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
- "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
- "(_T0.\"_KEY\" > ?), Arguments=[10], " +
- "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
- "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=]]"
- : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
- "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
- "(_T0._KEY > ?), Arguments=[10], " +
- "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
- "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=]]", str);
-
- // Check fields query
- var fieldsQuery = (ICacheQueryable) cache.AsCacheQueryable().Select(x => x.Value.Name);
-
- Assert.AreEqual(cache.Name, fieldsQuery.CacheName);
- Assert.AreEqual(cache.Ignite, fieldsQuery.Ignite);
-
- fq = fieldsQuery.GetFieldsQuery();
- Assert.AreEqual(GetSqlEscapeAll()
- ? "select _T0.\"Name\" from \"person_org\".\"Person\" as _T0"
- : "select _T0.NAME from \"person_org\".Person as _T0",
- fq.Sql);
-
- Assert.IsFalse(fq.Local);
- Assert.AreEqual(SqlFieldsQuery.DefaultPageSize, fq.PageSize);
- Assert.IsFalse(fq.EnableDistributedJoins);
- Assert.IsFalse(fq.EnforceJoinOrder);
-
- str = fieldsQuery.ToString();
- Assert.AreEqual(GetSqlEscapeAll()
- ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
- "[Sql=select _T0.\"Name\" from \"person_org\".\"Person\" as _T0, Arguments=[], Local=False, " +
- "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
- "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]"
- : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
- "[Sql=select _T0.NAME from \"person_org\".Person as _T0, Arguments=[], Local=False, " +
- "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
- "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]", str);
-
- // Check distributed joins flag propagation
- var distrQuery = cache.AsCacheQueryable(new QueryOptions {EnableDistributedJoins = true})
- .Where(x => x.Key > 10 && x.Value.Age > 20 && x.Value.Name.Contains("x"));
-
- query = distrQuery.ToCacheQueryable();
-
- Assert.IsTrue(query.GetFieldsQuery().EnableDistributedJoins);
-
- str = distrQuery.ToString();
- Assert.AreEqual(GetSqlEscapeAll()
- ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
- "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
- "(((_T0.\"_KEY\" > ?) and (_T0.\"age1\" > ?)) " +
- "and (_T0.\"Name\" like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
- "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
- "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]"
- : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
- "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
- "(((_T0._KEY > ?) and (_T0.AGE1 > ?)) " +
- "and (_T0.NAME like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
- "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
- "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]", str);
- }
-
- /// <summary>
- /// Tests the table name inference.
- /// </summary>
- [Test]
- public void TestTableNameInference()
- {
- // Try with multi-type cache: explicit type is required
- var cache = GetCacheOf<IPerson>();
-
- Assert.Throws<CacheException>(() => cache.AsCacheQueryable());
-
- var names = cache.AsCacheQueryable(false, "Person").Select(x => x.Value.Name).ToArray();
-
- Assert.AreEqual(PersonCount, names.Length);
-
- // With single-type cache, interface inference works
- var roleCache = Ignition.GetIgnite().GetCache<object, IRole>(RoleCacheName).AsCacheQueryable();
-
- var roleNames = roleCache.Select(x => x.Value.Name).OrderBy(x => x).ToArray();
-
- CollectionAssert.AreEquivalent(new[] {"Role_1", "Role_2", null}, roleNames);
-
- // Check non-queryable cache
- var nonQueryableCache = Ignition.GetIgnite().GetOrCreateCache<Role, Person>("nonQueryable");
-
- Assert.Throws<CacheException>(() => nonQueryableCache.AsCacheQueryable());
- }
-
- /// <summary>
- /// Tests the distributed joins.
- /// </summary>
- [Test]
- public void TestDistributedJoins()
- {
- var ignite = Ignition.GetIgnite();
-
- // Create and populate partitioned caches
- var personCache = ignite.CreateCache<int, Person>(new CacheConfiguration("partitioned_persons",
- new QueryEntity(typeof(int), typeof(Person)))
- {
- SqlEscapeAll = GetSqlEscapeAll()
- });
-
- personCache.PutAll(GetSecondPersonCache().ToDictionary(x => x.Key, x => x.Value));
-
- var roleCache = ignite.CreateCache<int, Role>(new CacheConfiguration("partitioned_roles",
- new QueryEntity(typeof(int), typeof(Role)))
- {
- SqlEscapeAll = GetSqlEscapeAll()
- });
-
- roleCache.PutAll(GetRoleCache().ToDictionary(x => x.Key.Foo, x => x.Value));
-
- // Test non-distributed join: returns partial results
- var persons = personCache.AsCacheQueryable();
- var roles = roleCache.AsCacheQueryable();
-
- var res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
- .ToArray();
-
- Assert.AreEqual(res.Length, RoleCount);
-
- // Test distributed join: returns complete results
- persons = personCache.AsCacheQueryable(new QueryOptions {EnableDistributedJoins = true});
- roles = roleCache.AsCacheQueryable(new QueryOptions {EnableDistributedJoins = true});
-
- res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
- .ToArray();
-
- Assert.AreEqual(RoleCount, res.Length);
- }
-
- /// <summary>
- /// Tests the query timeout.
- /// </summary>
- [Test]
- public void TestTimeout()
- {
- var persons = GetPersonCache().AsCacheQueryable(new QueryOptions
- {
- Timeout = TimeSpan.FromMilliseconds(1),
- EnableDistributedJoins = true
- });
-
- // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
- var ex = Assert.Throws<CacheException>(() =>
- persons.SelectMany(p => GetRoleCache().AsCacheQueryable()).ToArray());
-
- Assert.IsTrue(ex.ToString().Contains("QueryCancelledException: The query was cancelled while executing."));
- }
-
- /// <summary>
- /// Tests the RemoveAll extension.
- /// </summary>
- [Test]
- public void TestRemoveAll()
- {
- // Use new cache to avoid touching static data.
- var cache = Ignition.GetIgnite().CreateCache<int, Person>(new CacheConfiguration("deleteAllTest",
- new QueryEntity(typeof(int), typeof(Person)))
- {
- SqlEscapeAll = GetSqlEscapeAll()
- });
-
- Enumerable.Range(1, 10).ToList().ForEach(x => cache.Put(x, new Person(x, x.ToString())));
-
- var queryable = cache.AsCacheQueryable();
-
- Func<int[]> getKeys = () => cache.Select(x => x.Key).OrderBy(x => x).ToArray();
-
- // Without predicate.
- var res = queryable.Where(x => x.Key < 3).RemoveAll();
- Assert.AreEqual(2, res);
- Assert.AreEqual(Enumerable.Range(3, 8), getKeys());
-
- // With predicate.
- res = queryable.RemoveAll(x => x.Key < 7);
- Assert.AreEqual(4, res);
- Assert.AreEqual(Enumerable.Range(7, 4), getKeys());
-
- // Subquery-style join.
- var ids = GetPersonCache().AsCacheQueryable().Where(x => x.Key == 7).Select(x => x.Key);
-
- res = queryable.Where(x => ids.Contains(x.Key)).RemoveAll();
- Assert.AreEqual(1, res);
- Assert.AreEqual(Enumerable.Range(8, 3), getKeys());
-
- // Row number limit.
- res = queryable.Take(2).RemoveAll();
- Assert.AreEqual(2, res);
- Assert.AreEqual(1, getKeys().Length);
-
- // Unconditional.
- queryable.RemoveAll();
- Assert.AreEqual(0, cache.GetSize());
-
- // Skip is not supported with DELETE.
- var nex = Assert.Throws<NotSupportedException>(() => queryable.Skip(1).RemoveAll());
- Assert.AreEqual(
- "RemoveAll can not be combined with result operators (other than Take): SkipResultOperator",
- nex.Message);
-
- // Multiple result operators are not supported with DELETE.
- nex = Assert.Throws<NotSupportedException>(() => queryable.Skip(1).Take(1).RemoveAll());
- Assert.AreEqual(
- "RemoveAll can not be combined with result operators (other than Take): SkipResultOperator, " +
- "TakeResultOperator, RemoveAllResultOperator", nex.Message);
-
- // Joins are not supported in H2.
- var qry = queryable
- .Where(x => x.Key == 7)
- .Join(GetPersonCache().AsCacheQueryable(), p => p.Key, p => p.Key, (p1, p2) => p1);
-
- var ex = Assert.Throws<IgniteException>(() => qry.RemoveAll());
- Assert.AreEqual("Failed to parse query", ex.Message.Substring(0, 21));
- }
-
- /// <summary>
- /// Gets the person cache.
- /// </summary>
- /// <returns></returns>
- private ICache<int, Person> GetPersonCache()
- {
- return GetCacheOf<Person>();
- }
-
- /// <summary>
- /// Gets the org cache.
- /// </summary>
- /// <returns></returns>
- private ICache<int, Organization> GetOrgCache()
- {
- return GetCacheOf<Organization>();
- }
-
- /// <summary>
- /// Gets the cache.
- /// </summary>
- private ICache<int, T> GetCacheOf<T>()
- {
- return Ignition.GetIgnite()
- .GetOrCreateCache<int, T>(new CacheConfiguration(PersonOrgCacheName,
- new QueryEntity(typeof (int), typeof (Person))
- {
- Aliases = new[]
- {
- new QueryAlias("AliasTest", "Person_AliasTest"),
- new QueryAlias("Address.AliasTest", "Addr_AliasTest")
- },
- KeyFieldName = "MyKey",
- ValueFieldName = "MyValue",
- Fields =
- {
- new QueryField("MyKey", typeof(int)),
- new QueryField("MyValue", typeof(T)),
- }
- },
- new QueryEntity(typeof (int), typeof (Organization)))
- {
- CacheMode = CacheMode.Replicated,
- SqlEscapeAll = GetSqlEscapeAll()
- });
- }
-
- /// <summary>
- /// Gets the role cache.
- /// </summary>
- private ICache<RoleKey, Role> GetRoleCache()
- {
- return Ignition.GetIgnite()
- .GetOrCreateCache<RoleKey, Role>(new CacheConfiguration(RoleCacheName,
- new QueryEntity(typeof (RoleKey), typeof (Role)))
- {
- CacheMode = CacheMode.Replicated,
- SqlEscapeAll = GetSqlEscapeAll()
- });
- }
-
- /// <summary>
- /// Gets the second person cache.
- /// </summary>
- private ICache<int, Person> GetSecondPersonCache()
- {
- return Ignition.GetIgnite()
- .GetOrCreateCache<int, Person>(
- new CacheConfiguration(PersonSecondCacheName,
- new QueryEntity(typeof(int), typeof(Person))
- {
- TableName = "CustomPersons"
- })
- {
- CacheMode = CacheMode.Replicated,
- SqlEscapeAll = GetSqlEscapeAll()
- });
- }
-
- /// <summary>
- /// Checks that function maps to SQL function properly.
- /// </summary>
- private static void CheckFunc<T, TR>(Expression<Func<T, TR>> exp, IQueryable<T> query,
- Func<TR, TR> localResultFunc = null)
- {
- localResultFunc = localResultFunc ?? (x => x);
-
- // Calculate result locally, using real method invocation
- var expected = query.ToArray().AsQueryable().Select(exp).Select(localResultFunc).OrderBy(x => x).ToArray();
-
- // Perform SQL query
- var actual = query.Select(exp).ToArray().OrderBy(x => x).ToArray();
-
- // Compare results
- CollectionAssert.AreEqual(expected, actual, new NumericComparer());
-
- // Perform intermediate anonymous type conversion to check type projection
- actual = query.Select(exp).Select(x => new {Foo = x}).ToArray().Select(x => x.Foo)
- .OrderBy(x => x).ToArray();
-
- // Compare results
- CollectionAssert.AreEqual(expected, actual, new NumericComparer());
- }
-
- /// <summary>
- /// Checks that function used in Where Clause maps to SQL function properly
- /// </summary>
- private static void CheckWhereFunc<TKey, TEntry>(IQueryable<ICacheEntry<TKey,TEntry>> query,
- Expression<Func<ICacheEntry<TKey, TEntry>,bool>> whereExpression)
- {
- // Calculate result locally, using real method invocation
- var expected = query
- .ToArray()
- .AsQueryable()
- .Where(whereExpression)
- .Select(entry => entry.Key)
- .OrderBy(x => x)
- .ToArray();
-
- // Perform SQL query
- var actual = query
- .Where(whereExpression)
- .Select(entry => entry.Key)
- .ToArray()
- .OrderBy(x => x)
- .ToArray();
-
- // Compare results
- CollectionAssert.AreEqual(expected, actual, new NumericComparer());
- }
-
- /// <summary>
- /// Tests conditinal statement
- /// </summary>
- private void TestConditional<T>(T even , T odd, Func<T,T,bool> comparer = null)
- {
- var persons = GetPersonCache().AsCacheQueryable();
-
- var res = persons
- .Select(x => new {Foo = x.Key % 2 == 0 ? even : odd, x.Value})
- .ToArray();
-
- if (comparer != null)
- {
- Assert.IsTrue(comparer(even, res[0].Foo));
- Assert.IsTrue(comparer(odd, res[1].Foo));
- }
- else
- {
- Assert.AreEqual(even, res[0].Foo);
- Assert.AreEqual(odd, res[1].Foo);
- }
- }
-
- /// <summary>
- /// Tests conditinal statement for structs with default and null values
- /// </summary>
- private void TestConditionalWithNullableStructs<T>(T? defaultFalue = null) where T : struct
- {
- var def = defaultFalue ?? default(T);
- TestConditional(def, (T?) null);
- }
-
- public interface IPerson
- {
- int Age { get; set; }
- string Name { get; set; }
- }
-
- public class Person : IBinarizable, IPerson
- {
- public Person(int age, string name)
- {
- Age = age;
- Name = name;
- }
-
- [QuerySqlField(Name = "age1")] public int Age { get; set; }
-
- [QuerySqlField] public string Name { get; set; }
-
- [QuerySqlField] public Address Address { get; set; }
-
- [QuerySqlField] public int OrganizationId { get; set; }
-
- [QuerySqlField] public DateTime? Birthday { get; set; }
-
- [QuerySqlField] public int AliasTest { get; set; }
-
- public void WriteBinary(IBinaryWriter writer)
- {
- writer.WriteInt("age1", Age);
- writer.WriteString("name", Name);
- writer.WriteInt("OrganizationId", OrganizationId);
- writer.WriteObject("Address", Address);
- writer.WriteTimestamp("Birthday", Birthday);
- writer.WriteInt("AliasTest", AliasTest);
- }
-
- public void ReadBinary(IBinaryReader reader)
- {
- Age = reader.ReadInt("age1");
- Name = reader.ReadString("name");
- OrganizationId = reader.ReadInt("OrganizationId");
- Address = reader.ReadObject<Address>("Address");
- Birthday = reader.ReadTimestamp("Birthday");
- AliasTest = reader.ReadInt("AliasTest");
- }
- }
-
- public class Address
- {
- [QuerySqlField] public int Zip { get; set; }
- [QuerySqlField] public string Street { get; set; }
- [QuerySqlField] public int AliasTest { get; set; }
- }
-
- public class Organization
- {
- [QuerySqlField] public int Id { get; set; }
- [QuerySqlField] public string Name { get; set; }
- }
-
- public interface IRole
- {
- string Name { get; }
- DateTime Date { get; }
- }
-
- public class Role : IRole
- {
- [QuerySqlField] public string Name { get; set; }
- [QuerySqlField] public DateTime Date { get; set; }
- }
-
- public class Numerics
- {
- public Numerics(double val)
- {
- Double = val;
- Float = (float) val;
- Decimal = (decimal) val;
- Int = (int) val;
- Uint = (uint) val;
- Long = (long) val;
- Ulong = (ulong) val;
- Short = (short) val;
- Ushort = (ushort) val;
- Byte = (byte) val;
- Sbyte = (sbyte) val;
- }
-
- [QuerySqlField] public double Double { get; set; }
- [QuerySqlField] public float Float { get; set; }
- [QuerySqlField] public decimal Decimal { get; set; }
- [QuerySqlField] public int Int { get; set; }
- [QuerySqlField] public uint Uint { get; set; }
- [QuerySqlField] public long Long { get; set; }
- [QuerySqlField] public ulong Ulong { get; set; }
- [QuerySqlField] public short Short { get; set; }
- [QuerySqlField] public ushort Ushort { get; set; }
- [QuerySqlField] public byte Byte { get; set; }
- [QuerySqlField] public sbyte Sbyte { get; set; }
- }
-
- public struct RoleKey : IEquatable<RoleKey>
- {
- private readonly int _foo;
- private readonly long _bar;
-
- public RoleKey(int foo, long bar)
- {
- _foo = foo;
- _bar = bar;
- }
-
- [QuerySqlField(Name = "_foo")]
- public int Foo
- {
- get { return _foo; }
- }
-
- [QuerySqlField(Name = "_bar")]
- public long Bar
- {
- get { return _bar; }
- }
-
- public bool Equals(RoleKey other)
- {
- return _foo == other._foo && _bar == other._bar;
- }
-
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(null, obj)) return false;
- return obj is RoleKey && Equals((RoleKey) obj);
- }
-
- public override int GetHashCode()
- {
- unchecked
- {
- return (_foo*397) ^ _bar.GetHashCode();
- }
- }
-
- public static bool operator ==(RoleKey left, RoleKey right)
- {
- return left.Equals(right);
- }
-
- public static bool operator !=(RoleKey left, RoleKey right)
- {
- return !left.Equals(right);
- }
- }
-
- /// <summary>
- /// Epsilon comparer.
- /// </summary>
- private class NumericComparer : IComparer
- {
- /** <inheritdoc /> */
- public int Compare(object x, object y)
- {
- if (Equals(x, y))
- return 0;
-
- if (x is double)
- {
- var dx = (double) x;
- var dy = (double) y;
-
- // Epsilon is proportional to the min value, but not too small.
- const double epsilon = 2E-10d;
- var min = Math.Min(Math.Abs(dx), Math.Abs(dy));
- var relEpsilon = Math.Max(min*epsilon, epsilon);
-
- // Compare with epsilon because some funcs return slightly different results.
- return Math.Abs((double) x - (double) y) < relEpsilon ? 0 : 1;
- }
-
- return ((IComparable) x).CompareTo(y);
- }
- }
- }
-}
[2/3] ignite git commit: IGNITE-5532 .NET: Split CacheLinqTest into
partial classes
Posted by pt...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSimpleName.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSimpleName.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSimpleName.cs
deleted file mode 100644
index 9743e60..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSimpleName.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace Apache.Ignite.Core.Tests.Cache.Query
-{
- using Apache.Ignite.Core.Binary;
- using NUnit.Framework;
-
- /// <summary>
- /// LINQ test with simple name mapper.
- /// </summary>
- [TestFixture]
- public class CacheLinqTestSimpleName : CacheLinqTest
- {
- /** <inheritdoc /> */
- protected override IBinaryNameMapper GetNameMapper()
- {
- return BinaryBasicNameMapper.SimpleNameInstance;
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSqlEscapeAll.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSqlEscapeAll.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSqlEscapeAll.cs
deleted file mode 100644
index 7473be9..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTestSqlEscapeAll.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace Apache.Ignite.Core.Tests.Cache.Query
-{
- using NUnit.Framework;
-
- /// <summary>
- /// LINQ test with simple name mapper.
- /// </summary>
- [TestFixture]
- public class CacheLinqTestSqlEscapeAll : CacheLinqTest
- {
- /** <inheritdoc /> */
- protected override bool GetSqlEscapeAll()
- {
- return true;
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Aggregates.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Aggregates.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Aggregates.cs
new file mode 100644
index 0000000..b6bbb67
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Aggregates.cs
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System;
+ using System.Linq;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests aggregates.
+ /// </summary>
+ [Test]
+ public void TestAggregates()
+ {
+ var cache = GetPersonCache().AsCacheQueryable();
+
+ Assert.AreEqual(PersonCount, cache.Count());
+ Assert.AreEqual(PersonCount, cache.Select(x => x.Key).Count());
+ Assert.AreEqual(2, cache.Select(x => x.Value.OrganizationId).Distinct().Count());
+
+ // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+ Assert.Throws<NotSupportedException>(() => cache.Select(x => new { x.Key, x.Value }).Count());
+
+ // Min/max/sum/avg
+ var ints = cache.Select(x => x.Key);
+ Assert.AreEqual(0, ints.Min());
+ Assert.AreEqual(PersonCount - 1, ints.Max());
+ Assert.AreEqual(ints.ToArray().Sum(), ints.Sum());
+ Assert.AreEqual((int)ints.ToArray().Average(), (int)ints.Average());
+
+ var dupInts = ints.Select(x => x / 10); // duplicate values
+ CollectionAssert.AreEquivalent(dupInts.ToArray().Distinct().ToArray(), dupInts.Distinct().ToArray());
+ Assert.AreEqual(dupInts.ToArray().Distinct().Sum(), dupInts.Distinct().Sum());
+
+ // All/any
+ Assert.IsFalse(ints.Where(x => x > -5).Any(x => x > PersonCount && x > 0));
+ Assert.IsTrue(ints.Any(x => x < PersonCount / 2));
+
+ // Skip/take
+ var keys = cache.Select(x => x.Key).OrderBy(x => x);
+ Assert.AreEqual(new[] { 0, 1 }, keys.Take(2).ToArray());
+ Assert.AreEqual(new[] { 1, 2 }, keys.Skip(1).Take(2).ToArray());
+ Assert.AreEqual(new[] { PersonCount - 2, PersonCount - 1 }, keys.Skip(PersonCount - 2).ToArray());
+ }
+
+ /// <summary>
+ /// Tests aggregates with all clause.
+ /// </summary>
+ [Test]
+ public void TestAggregatesAll()
+ {
+ var ints = GetPersonCache().AsCacheQueryable().Select(x => x.Key);
+
+ // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+ var ex = Assert.Throws<NotSupportedException>(() => ints.Where(x => x > -10)
+ .All(x => x < PersonCount && x >= 0));
+
+ Assert.IsTrue(ex.Message.StartsWith("Operator is not supported: All"));
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
new file mode 100644
index 0000000..ae9fd5f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
@@ -0,0 +1,506 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System;
+ using System.Collections;
+ using System.Linq;
+ using System.Linq.Expressions;
+ using System.Threading;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /** Cache name. */
+ private const string PersonOrgCacheName = "person_org";
+
+ /** Cache name. */
+ private const string PersonSecondCacheName = "person_cache";
+
+ /** Role cache name. */
+ private const string RoleCacheName = "role_cache";
+
+ /** */
+ private const int RoleCount = 3;
+
+ /** */
+ private const int PersonCount = 900;
+
+ /** */
+ private bool _runDbConsole;
+
+ /** */
+ private static readonly DateTime StartDateTime = new DateTime(2000, 5, 17, 15, 4, 5, DateTimeKind.Utc);
+
+ /// <summary>
+ /// Fixture set up.
+ /// </summary>
+ [TestFixtureSetUp]
+ public void FixtureSetUp()
+ {
+ _runDbConsole = false; // set to true to open H2 console
+
+ if (_runDbConsole)
+ Environment.SetEnvironmentVariable("IGNITE_H2_DEBUG_CONSOLE", "true");
+
+ Ignition.Start(GetConfig());
+ Ignition.Start(GetConfig("grid2"));
+
+ // Populate caches
+ var cache = GetPersonCache();
+ var personCache = GetSecondPersonCache();
+
+ for (var i = 0; i < PersonCount; i++)
+ {
+ cache.Put(i, new Person(i, string.Format(" Person_{0} ", i))
+ {
+ Address = new Address {Zip = i, Street = "Street " + i, AliasTest = i},
+ OrganizationId = i%2 + 1000,
+ Birthday = StartDateTime.AddYears(i),
+ AliasTest = -i
+ });
+
+ var i2 = i + PersonCount;
+ personCache.Put(i2, new Person(i2, "Person_" + i2)
+ {
+ Address = new Address {Zip = i2, Street = "Street " + i2},
+ OrganizationId = i%2 + 1000,
+ Birthday = StartDateTime.AddYears(i)
+ });
+ }
+
+ var orgCache = GetOrgCache();
+
+ orgCache[1000] = new Organization {Id = 1000, Name = "Org_0"};
+ orgCache[1001] = new Organization {Id = 1001, Name = "Org_1"};
+ orgCache[1002] = new Organization {Id = 1002, Name = null};
+
+ var roleCache = GetRoleCache();
+
+ 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.AddHours(5432)};
+ }
+
+ /// <summary>
+ /// Gets the configuration.
+ /// </summary>
+ private IgniteConfiguration GetConfig(string gridName = null)
+ {
+ return new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ BinaryConfiguration = new BinaryConfiguration(typeof(Person),
+ typeof(Organization), typeof(Address), typeof(Role), typeof(RoleKey), typeof(Numerics))
+ {
+ NameMapper = GetNameMapper()
+ },
+ IgniteInstanceName = gridName
+ };
+ }
+
+ /// <summary>
+ /// Gets the name mapper.
+ /// </summary>
+ protected virtual IBinaryNameMapper GetNameMapper()
+ {
+ return BinaryBasicNameMapper.FullNameInstance;
+ }
+
+ /// <summary>
+ /// Gets the SqlEscapeAll setting.
+ /// </summary>
+ protected virtual bool GetSqlEscapeAll()
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// Fixture tear down.
+ /// </summary>
+ [TestFixtureTearDown]
+ public void FixtureTearDown()
+ {
+ if (_runDbConsole)
+ Thread.Sleep(Timeout.Infinite);
+ Ignition.StopAll(true);
+ }
+
+ /// <summary>
+ /// Gets the person cache.
+ /// </summary>
+ /// <returns></returns>
+ private ICache<int, Person> GetPersonCache()
+ {
+ return GetCacheOf<Person>();
+ }
+
+ /// <summary>
+ /// Gets the org cache.
+ /// </summary>
+ /// <returns></returns>
+ private ICache<int, Organization> GetOrgCache()
+ {
+ return GetCacheOf<Organization>();
+ }
+
+ /// <summary>
+ /// Gets the cache.
+ /// </summary>
+ private ICache<int, T> GetCacheOf<T>()
+ {
+ return Ignition.GetIgnite()
+ .GetOrCreateCache<int, T>(new CacheConfiguration(PersonOrgCacheName,
+ new QueryEntity(typeof (int), typeof (Person))
+ {
+ Aliases = new[]
+ {
+ new QueryAlias("AliasTest", "Person_AliasTest"),
+ new QueryAlias("Address.AliasTest", "Addr_AliasTest")
+ },
+ KeyFieldName = "MyKey",
+ ValueFieldName = "MyValue",
+ Fields =
+ {
+ new QueryField("MyKey", typeof(int)),
+ new QueryField("MyValue", typeof(T)),
+ }
+ },
+ new QueryEntity(typeof (int), typeof (Organization)))
+ {
+ CacheMode = CacheMode.Replicated,
+ SqlEscapeAll = GetSqlEscapeAll()
+ });
+ }
+
+ /// <summary>
+ /// Gets the role cache.
+ /// </summary>
+ private ICache<RoleKey, Role> GetRoleCache()
+ {
+ return Ignition.GetIgnite()
+ .GetOrCreateCache<RoleKey, Role>(new CacheConfiguration(RoleCacheName,
+ new QueryEntity(typeof (RoleKey), typeof (Role)))
+ {
+ CacheMode = CacheMode.Replicated,
+ SqlEscapeAll = GetSqlEscapeAll()
+ });
+ }
+
+ /// <summary>
+ /// Gets the second person cache.
+ /// </summary>
+ private ICache<int, Person> GetSecondPersonCache()
+ {
+ return Ignition.GetIgnite()
+ .GetOrCreateCache<int, Person>(
+ new CacheConfiguration(PersonSecondCacheName,
+ new QueryEntity(typeof(int), typeof(Person))
+ {
+ TableName = "CustomPersons"
+ })
+ {
+ CacheMode = CacheMode.Replicated,
+ SqlEscapeAll = GetSqlEscapeAll()
+ });
+ }
+
+ /// <summary>
+ /// Checks that function maps to SQL function properly.
+ /// </summary>
+ private static void CheckFunc<T, TR>(Expression<Func<T, TR>> exp, IQueryable<T> query,
+ Func<TR, TR> localResultFunc = null)
+ {
+ localResultFunc = localResultFunc ?? (x => x);
+
+ // Calculate result locally, using real method invocation
+ var expected = query.ToArray().AsQueryable().Select(exp).Select(localResultFunc).OrderBy(x => x).ToArray();
+
+ // Perform SQL query
+ var actual = query.Select(exp).ToArray().OrderBy(x => x).ToArray();
+
+ // Compare results
+ CollectionAssert.AreEqual(expected, actual, new NumericComparer());
+
+ // Perform intermediate anonymous type conversion to check type projection
+ actual = query.Select(exp).Select(x => new {Foo = x}).ToArray().Select(x => x.Foo)
+ .OrderBy(x => x).ToArray();
+
+ // Compare results
+ CollectionAssert.AreEqual(expected, actual, new NumericComparer());
+ }
+
+ /// <summary>
+ /// Checks that function used in Where Clause maps to SQL function properly
+ /// </summary>
+ private static void CheckWhereFunc<TKey, TEntry>(IQueryable<ICacheEntry<TKey,TEntry>> query,
+ Expression<Func<ICacheEntry<TKey, TEntry>,bool>> whereExpression)
+ {
+ // Calculate result locally, using real method invocation
+ var expected = query
+ .ToArray()
+ .AsQueryable()
+ .Where(whereExpression)
+ .Select(entry => entry.Key)
+ .OrderBy(x => x)
+ .ToArray();
+
+ // Perform SQL query
+ var actual = query
+ .Where(whereExpression)
+ .Select(entry => entry.Key)
+ .ToArray()
+ .OrderBy(x => x)
+ .ToArray();
+
+ // Compare results
+ CollectionAssert.AreEqual(expected, actual, new NumericComparer());
+ }
+
+ /// <summary>
+ /// Tests conditinal statement
+ /// </summary>
+ private void TestConditional<T>(T even , T odd, Func<T,T,bool> comparer = null)
+ {
+ var persons = GetPersonCache().AsCacheQueryable();
+
+ var res = persons
+ .Select(x => new {Foo = x.Key % 2 == 0 ? even : odd, x.Value})
+ .ToArray();
+
+ if (comparer != null)
+ {
+ Assert.IsTrue(comparer(even, res[0].Foo));
+ Assert.IsTrue(comparer(odd, res[1].Foo));
+ }
+ else
+ {
+ Assert.AreEqual(even, res[0].Foo);
+ Assert.AreEqual(odd, res[1].Foo);
+ }
+ }
+
+ /// <summary>
+ /// Tests conditinal statement for structs with default and null values
+ /// </summary>
+ private void TestConditionalWithNullableStructs<T>(T? defaultFalue = null) where T : struct
+ {
+ var def = defaultFalue ?? default(T);
+ TestConditional(def, (T?) null);
+ }
+
+ public interface IPerson
+ {
+ int Age { get; set; }
+ string Name { get; set; }
+ }
+
+ public class Person : IBinarizable, IPerson
+ {
+ public Person(int age, string name)
+ {
+ Age = age;
+ Name = name;
+ }
+
+ [QuerySqlField(Name = "age1")] public int Age { get; set; }
+
+ [QuerySqlField] public string Name { get; set; }
+
+ [QuerySqlField] public Address Address { get; set; }
+
+ [QuerySqlField] public int OrganizationId { get; set; }
+
+ [QuerySqlField] public DateTime? Birthday { get; set; }
+
+ [QuerySqlField] public int AliasTest { get; set; }
+
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ writer.WriteInt("age1", Age);
+ writer.WriteString("name", Name);
+ writer.WriteInt("OrganizationId", OrganizationId);
+ writer.WriteObject("Address", Address);
+ writer.WriteTimestamp("Birthday", Birthday);
+ writer.WriteInt("AliasTest", AliasTest);
+ }
+
+ public void ReadBinary(IBinaryReader reader)
+ {
+ Age = reader.ReadInt("age1");
+ Name = reader.ReadString("name");
+ OrganizationId = reader.ReadInt("OrganizationId");
+ Address = reader.ReadObject<Address>("Address");
+ Birthday = reader.ReadTimestamp("Birthday");
+ AliasTest = reader.ReadInt("AliasTest");
+ }
+ }
+
+ public class Address
+ {
+ [QuerySqlField] public int Zip { get; set; }
+ [QuerySqlField] public string Street { get; set; }
+ [QuerySqlField] public int AliasTest { get; set; }
+ }
+
+ public class Organization
+ {
+ [QuerySqlField] public int Id { get; set; }
+ [QuerySqlField] public string Name { get; set; }
+ }
+
+ public interface IRole
+ {
+ string Name { get; }
+ DateTime Date { get; }
+ }
+
+ public class Role : IRole
+ {
+ [QuerySqlField] public string Name { get; set; }
+ [QuerySqlField] public DateTime Date { get; set; }
+ }
+
+ public class Numerics
+ {
+ public Numerics(double val)
+ {
+ Double = val;
+ Float = (float) val;
+ Decimal = (decimal) val;
+ Int = (int) val;
+ Uint = (uint) val;
+ Long = (long) val;
+ Ulong = (ulong) val;
+ Short = (short) val;
+ Ushort = (ushort) val;
+ Byte = (byte) val;
+ Sbyte = (sbyte) val;
+ }
+
+ [QuerySqlField] public double Double { get; set; }
+ [QuerySqlField] public float Float { get; set; }
+ [QuerySqlField] public decimal Decimal { get; set; }
+ [QuerySqlField] public int Int { get; set; }
+ [QuerySqlField] public uint Uint { get; set; }
+ [QuerySqlField] public long Long { get; set; }
+ [QuerySqlField] public ulong Ulong { get; set; }
+ [QuerySqlField] public short Short { get; set; }
+ [QuerySqlField] public ushort Ushort { get; set; }
+ [QuerySqlField] public byte Byte { get; set; }
+ [QuerySqlField] public sbyte Sbyte { get; set; }
+ }
+
+ public struct RoleKey : IEquatable<RoleKey>
+ {
+ private readonly int _foo;
+ private readonly long _bar;
+
+ public RoleKey(int foo, long bar)
+ {
+ _foo = foo;
+ _bar = bar;
+ }
+
+ [QuerySqlField(Name = "_foo")]
+ public int Foo
+ {
+ get { return _foo; }
+ }
+
+ [QuerySqlField(Name = "_bar")]
+ public long Bar
+ {
+ get { return _bar; }
+ }
+
+ public bool Equals(RoleKey other)
+ {
+ return _foo == other._foo && _bar == other._bar;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ return obj is RoleKey && Equals((RoleKey) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (_foo*397) ^ _bar.GetHashCode();
+ }
+ }
+
+ public static bool operator ==(RoleKey left, RoleKey right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(RoleKey left, RoleKey right)
+ {
+ return !left.Equals(right);
+ }
+ }
+
+ /// <summary>
+ /// Epsilon comparer.
+ /// </summary>
+ private class NumericComparer : IComparer
+ {
+ /** <inheritdoc /> */
+ public int Compare(object x, object y)
+ {
+ if (Equals(x, y))
+ return 0;
+
+ if (x is double)
+ {
+ var dx = (double) x;
+ var dy = (double) y;
+
+ // Epsilon is proportional to the min value, but not too small.
+ const double epsilon = 2E-10d;
+ var min = Math.Min(Math.Abs(dx), Math.Abs(dy));
+ var relEpsilon = Math.Max(min*epsilon, epsilon);
+
+ // Compare with epsilon because some funcs return slightly different results.
+ return Math.Abs((double) x - (double) y) < relEpsilon ? 0 : 1;
+ }
+
+ return ((IComparable) x).CompareTo(y);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.CompiledQuery.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.CompiledQuery.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.CompiledQuery.cs
new file mode 100644
index 0000000..1cd377e
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.CompiledQuery.cs
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System.Linq;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests the compiled query with various constructs.
+ /// </summary>
+ [Test]
+ public void TestCompiledQuery()
+ {
+ var persons = GetPersonCache().AsCacheQueryable();
+ var roles = GetRoleCache().AsCacheQueryable();
+
+ // Embedded args
+ var qry0 = CompiledQuery.Compile(() => persons.Where(x => x.Key < 3 && x.Value.Name.Contains("son")));
+ Assert.AreEqual(3, qry0().Count());
+
+ // Lambda args
+ var qry1 = CompiledQuery.Compile((int minKey, int take, int skip) => persons.Where(x => x.Key > minKey)
+ .Take(take).Skip(skip));
+ Assert.AreEqual(3, qry1(-1, 3, 1).GetAll().Count);
+
+ qry1 = CompiledQuery.Compile((int skip, int take, int minKey) => persons.Where(x => x.Key > minKey)
+ .Take(take).Skip(skip));
+
+ Assert.AreEqual(5, qry1(2, 5, 20).GetAll().Count);
+
+ // Mixed args
+ var qry2 = CompiledQuery.Compile((int maxKey, int minKey) =>
+ persons.Where(x => x.Key < maxKey
+ && x.Value.Name.Contains("er")
+ && x.Value.Age < maxKey
+ && x.Key > minKey).Skip(2));
+
+ Assert.AreEqual(6, qry2(10, 1).Count());
+
+ // Join
+ var qry3 = CompiledQuery.Compile(() =>
+ roles.Join(persons, r => r.Key.Foo, p => p.Key, (r, p) => r.Value.Name));
+
+ Assert.AreEqual(RoleCount, qry3().Count());
+
+ // Join with subquery
+ var qry4 = CompiledQuery.Compile(
+ (int a, int b, string sep) =>
+ roles
+ .Where(x => x.Key.Bar > a)
+ .OrderBy(x => x.Key.Bar)
+ .Join(persons.Where(x => x.Key < b && x.Key > 0),
+ r => r.Key.Foo,
+ p => p.Value.Address.Zip,
+ (r, p) => p.Value.Name + sep + r.Value.Name + "|")
+ .Skip(a).Take(1000)
+ );
+
+ Assert.AreEqual(new[] { " Person_2 =Role_2|", " Person_3 =|" }, qry4(1, PersonCount, "=").ToArray());
+
+ // Union
+ var qry5 = CompiledQuery.Compile(() => roles.Select(x => -x.Key.Foo).Union(persons.Select(x => x.Key)));
+
+ Assert.AreEqual(RoleCount + PersonCount, qry5().Count());
+
+ // Projection
+ var qry6 = CompiledQuery.Compile((int minAge) => persons
+ .Select(x => x.Value)
+ .Where(x => x.Age >= minAge)
+ .Select(x => new { x.Name, x.Age })
+ .OrderBy(x => x.Name));
+
+ var res = qry6(PersonCount - 3).GetAll();
+
+ Assert.AreEqual(3, res.Count);
+ Assert.AreEqual(PersonCount - 3, res[0].Age);
+ }
+
+ /// <summary>
+ /// Tests the compiled query overloads.
+ /// </summary>
+ [Test]
+ public void TestCompiledQueryOverloads()
+ {
+ var cache = GetPersonCache().AsCacheQueryable();
+
+ // const args are allowed
+ Assert.AreEqual(5, CompiledQuery.Compile(() => cache.Where(x => x.Key < 5))().GetAll().Count);
+
+ // 0 arg
+ var qry0 = CompiledQuery.Compile(() => cache.Select(x => x.Value.Name));
+ Assert.AreEqual(PersonCount, qry0().ToArray().Length);
+
+ // 1 arg
+ var qry1 = CompiledQuery.Compile((int k) => cache.Where(x => x.Key < k));
+ Assert.AreEqual(3, qry1(3).ToArray().Length);
+
+ // 1 arg twice
+ var qry1T = CompiledQuery.Compile((int k) => cache.Where(x => x.Key < k && x.Value.Age < k));
+ Assert.AreEqual(3, qry1T(3).ToArray().Length);
+
+ // 2 arg
+ var qry2 =
+ CompiledQuery.Compile((int i, string s) => cache.Where(x => x.Key < i && x.Value.Name.StartsWith(s)));
+ Assert.AreEqual(5, qry2(5, " Pe").ToArray().Length);
+
+ // Changed param order
+ var qry2R =
+ CompiledQuery.Compile((string s, int i) => cache.Where(x => x.Key < i && x.Value.Name.StartsWith(s)));
+ Assert.AreEqual(5, qry2R(" Pe", 5).ToArray().Length);
+
+ // 3 arg
+ var qry3 = CompiledQuery.Compile((int i, string s, double d) =>
+ cache.Where(x => x.Value.Address.Zip > d && x.Key < i && x.Value.Name.Contains(s)));
+ Assert.AreEqual(5, qry3(5, "son", -10).ToArray().Length);
+
+ // 4 arg
+ var qry4 = CompiledQuery.Compile((int a, int b, int c, int d) =>
+ cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d));
+ Assert.AreEqual(new[] { 3, 4 }, qry4(0, 1, 2, 5).ToArray());
+
+ // 5 arg
+ var qry5 = CompiledQuery.Compile((int a, int b, int c, int d, int e) =>
+ cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e));
+ Assert.AreEqual(new[] { 3, 4 }, qry5(0, 1, 2, 5, 6).ToArray());
+
+ // 6 arg
+ var qry6 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f) =>
+ cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e && k < f));
+ Assert.AreEqual(new[] { 3, 4 }, qry6(0, 1, 2, 5, 6, 7).ToArray());
+
+ // 7 arg
+ var qry7 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f, int g) =>
+ cache.Select(x => x.Key).Where(k => k > a && k > b && k > c && k < d && k < e && k < f && k < g));
+ Assert.AreEqual(new[] { 3, 4 }, qry7(0, 1, 2, 5, 6, 7, 8).ToArray());
+
+ // 8 arg
+ var qry8 = CompiledQuery.Compile((int a, int b, int c, int d, int e, int f, int g, int h) =>
+ cache.Select(x => x.Key)
+ .Where(k => k > a && k > b && k > c && k < d && k < e && k < f && k < g && k < h));
+ Assert.AreEqual(new[] { 3, 4 }, qry8(0, 1, 2, 5, 6, 7, 8, 9).ToArray());
+ }
+
+ /// <summary>
+ /// Tests the free-form compiled query, where user provides an array of arguments.
+ /// </summary>
+ [Test]
+ public void TestCompiledQueryFreeform()
+ {
+ var cache = GetPersonCache().AsCacheQueryable();
+
+ var qry = cache.Where(x => x.Key < 5);
+
+ // Simple
+ var compiled = CompiledQuery.Compile(qry);
+
+ Assert.AreEqual(5, compiled(5).Count());
+ Assert.AreEqual(6, compiled(6).Count());
+
+ // Select
+ var compiledSelect = CompiledQuery.Compile(qry.Select(x => x.Value.Name).OrderBy(x => x));
+
+ Assert.AreEqual(3, compiledSelect(3).Count());
+ Assert.AreEqual(" Person_0 ", compiledSelect(1).Single());
+
+ // Join
+ var compiledJoin = CompiledQuery.Compile(qry.Join(
+ GetOrgCache().AsCacheQueryable().Where(x => x.Value.Name.StartsWith("Org")),
+ p => p.Value.OrganizationId, o => o.Value.Id, (p, o) => o.Key));
+
+ Assert.AreEqual(1000, compiledJoin("Org", 1).Single());
+
+ // Many parameters
+ var qry2 = cache.Where(x => x.Key < 3)
+ .Where(x => x.Key > 0)
+ .Where(x => x.Value.Name.Contains(""))
+ .Where(x => x.Value.Address.Zip > 0)
+ .Where(x => x.Value.Age == 7);
+
+ var compiled2 = CompiledQuery.Compile(qry2);
+
+ Assert.AreEqual(17, compiled2(18, 16, "ers", 13, 17).Single().Key);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Contains.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Contains.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Contains.cs
new file mode 100644
index 0000000..032c746
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Contains.cs
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests IEnumerable.Contains.
+ /// </summary>
+ [Test]
+ public void TestContains()
+ {
+ var cache = GetPersonCache().AsCacheQueryable();
+ var orgCache = GetOrgCache().AsCacheQueryable();
+
+ var keys = new[] { 1, 2, 3 };
+ var emptyKeys = new int[0];
+
+ var bigNumberOfKeys = 10000;
+ var aLotOfKeys = Enumerable.Range(-bigNumberOfKeys + 10 - PersonCount, bigNumberOfKeys + PersonCount)
+ .ToArray();
+ var hashSetKeys = new HashSet<int>(keys);
+ var defferedCollection = Enumerable.Range(1, 10)
+ .Select(i => new { Id = i })
+ .Select(arg => arg.Id);
+
+ CheckWhereFunc(cache, e => new[] { 1, 2, 3 }.Contains(e.Key));
+ CheckWhereFunc(cache, e => emptyKeys.Contains(e.Key));
+ CheckWhereFunc(cache, e => new int[0].Contains(e.Key));
+ CheckWhereFunc(cache, e => new int[0].Contains(e.Key));
+ CheckWhereFunc(cache, e => new List<int> { 1, 2, 3 }.Contains(e.Key));
+ CheckWhereFunc(cache, e => new List<int>(keys).Contains(e.Key));
+ CheckWhereFunc(cache, e => aLotOfKeys.Contains(e.Key));
+ CheckWhereFunc(cache, e => hashSetKeys.Contains(e.Key));
+ CheckWhereFunc(cache, e => !keys.Contains(e.Key));
+ CheckWhereFunc(cache, e => defferedCollection.Contains(e.Key));
+ CheckWhereFunc(orgCache, e => new[] { "Org_1", "NonExistentName", null }.Contains(e.Value.Name));
+ CheckWhereFunc(orgCache, e => !new[] { "Org_1", "NonExistentName", null }.Contains(e.Value.Name));
+ CheckWhereFunc(orgCache, e => new[] { "Org_1", null, null }.Contains(e.Value.Name));
+ CheckWhereFunc(orgCache, e => !new[] { "Org_1", null, null }.Contains(e.Value.Name));
+ CheckWhereFunc(orgCache, e => new string[] { null }.Contains(e.Value.Name));
+ CheckWhereFunc(orgCache, e => !new string[] { null }.Contains(e.Value.Name));
+ CheckWhereFunc(orgCache, e => !new string[] { null, null }.Contains(e.Value.Name));
+ CheckWhereFunc(orgCache, e => new string[] { null, null }.Contains(e.Value.Name));
+
+ //check passing a null object as collection
+ int[] nullKeys = null;
+ var nullKeysEntries = cache
+ .Where(e => nullKeys.Contains(e.Key))
+ .ToArray();
+ Assert.AreEqual(0, nullKeysEntries.Length, "Evaluating 'null.Contains' should return zero results");
+
+
+ Func<int[]> getKeysFunc = () => null;
+ var funcNullKeyEntries = cache
+ .Where(e => getKeysFunc().Contains(e.Key))
+ .ToArray();
+ Assert.AreEqual(0, funcNullKeyEntries.Length, "Evaluating 'null.Contains' should return zero results");
+
+
+ // Check subselect from other cache
+ var subSelectCount = cache
+ .Count(entry => orgCache
+ .Where(orgEntry => orgEntry.Value.Name == "Org_1")
+ .Select(orgEntry => orgEntry.Key)
+ .Contains(entry.Value.OrganizationId));
+ var orgNumberOne = orgCache
+ .Where(orgEntry => orgEntry.Value.Name == "Org_1")
+ .Select(orgEntry => orgEntry.Key)
+ .First();
+ var subSelectCheckCount = cache.Count(entry => entry.Value.OrganizationId == orgNumberOne);
+ Assert.AreEqual(subSelectCheckCount, subSelectCount, "subselecting another CacheQueryable failed");
+
+ var ex = Assert.Throws<NotSupportedException>(() =>
+ CompiledQuery.Compile((int[] k) => cache.Where(x => k.Contains(x.Key))));
+ Assert.AreEqual("'Contains' clause on compiled query parameter is not supported.", ex.Message);
+
+ // check subquery from another cache put in separate variable
+ var orgIds = orgCache
+ .Where(o => o.Value.Name == "Org_1")
+ .Select(o => o.Key);
+
+ var subQueryFromVar = cache
+ .Where(x => orgIds.Contains(x.Value.OrganizationId))
+ .ToArray();
+
+ var subQueryInline = cache
+ .Where(x => orgCache.Where(o => o.Value.Name == "Org_1")
+ .Select(o => o.Key).Contains(x.Value.OrganizationId))
+ .ToArray();
+
+ Assert.AreEqual(subQueryInline.Length, subQueryFromVar.Length);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Custom.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Custom.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Custom.cs
new file mode 100644
index 0000000..f797b4c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Custom.cs
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System;
+ using System.Linq;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Common;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests the RemoveAll extension.
+ /// </summary>
+ [Test]
+ public void TestRemoveAll()
+ {
+ // Use new cache to avoid touching static data.
+ var cache = Ignition.GetIgnite().CreateCache<int, Person>(new CacheConfiguration("deleteAllTest",
+ new QueryEntity(typeof(int), typeof(Person)))
+ {
+ SqlEscapeAll = GetSqlEscapeAll()
+ });
+
+ Enumerable.Range(1, 10).ToList().ForEach(x => cache.Put(x, new Person(x, x.ToString())));
+
+ var queryable = cache.AsCacheQueryable();
+
+ Func<int[]> getKeys = () => cache.Select(x => x.Key).OrderBy(x => x).ToArray();
+
+ // Without predicate.
+ var res = queryable.Where(x => x.Key < 3).RemoveAll();
+ Assert.AreEqual(2, res);
+ Assert.AreEqual(Enumerable.Range(3, 8), getKeys());
+
+ // With predicate.
+ res = queryable.RemoveAll(x => x.Key < 7);
+ Assert.AreEqual(4, res);
+ Assert.AreEqual(Enumerable.Range(7, 4), getKeys());
+
+ // Subquery-style join.
+ var ids = GetPersonCache().AsCacheQueryable().Where(x => x.Key == 7).Select(x => x.Key);
+
+ res = queryable.Where(x => ids.Contains(x.Key)).RemoveAll();
+ Assert.AreEqual(1, res);
+ Assert.AreEqual(Enumerable.Range(8, 3), getKeys());
+
+ // Row number limit.
+ res = queryable.Take(2).RemoveAll();
+ Assert.AreEqual(2, res);
+ Assert.AreEqual(1, getKeys().Length);
+
+ // Unconditional.
+ queryable.RemoveAll();
+ Assert.AreEqual(0, cache.GetSize());
+
+ // Skip is not supported with DELETE.
+ var nex = Assert.Throws<NotSupportedException>(() => queryable.Skip(1).RemoveAll());
+ Assert.AreEqual(
+ "RemoveAll can not be combined with result operators (other than Take): SkipResultOperator",
+ nex.Message);
+
+ // Multiple result operators are not supported with DELETE.
+ nex = Assert.Throws<NotSupportedException>(() => queryable.Skip(1).Take(1).RemoveAll());
+ Assert.AreEqual(
+ "RemoveAll can not be combined with result operators (other than Take): SkipResultOperator, " +
+ "TakeResultOperator, RemoveAllResultOperator", nex.Message);
+
+ // Joins are not supported in H2.
+ var qry = queryable
+ .Where(x => x.Key == 7)
+ .Join(GetPersonCache().AsCacheQueryable(), p => p.Key, p => p.Key, (p1, p2) => p1);
+
+ var ex = Assert.Throws<IgniteException>(() => qry.RemoveAll());
+ Assert.AreEqual("Failed to parse query", ex.Message.Substring(0, 21));
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.DateTime.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.DateTime.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.DateTime.cs
new file mode 100644
index 0000000..b869dc4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.DateTime.cs
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System;
+ using System.Linq;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests date time.
+ /// </summary>
+ [Test]
+ public void TestDateTime()
+ {
+ var roles = GetRoleCache().AsCacheQueryable();
+ var persons = GetPersonCache().AsCacheQueryable();
+
+ // Invalid dateTime
+ // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+ var ex = Assert.Throws<BinaryObjectException>(() =>
+ roles.Where(x => x.Value.Date > DateTime.Now).ToArray());
+ Assert.AreEqual("DateTime is not UTC. Only UTC DateTime can be used for interop with other platforms.",
+ ex.Message);
+
+ // Test retrieval
+ var dates = roles.OrderBy(x => x.Value.Date).Select(x => x.Value.Date);
+ var expDates = GetRoleCache().Select(x => x.Value.Date).OrderBy(x => x).ToArray();
+ Assert.AreEqual(expDates, dates.ToArray());
+
+ // Filtering
+ Assert.AreEqual(1, persons.Count(x => x.Value.Birthday == StartDateTime));
+ Assert.AreEqual(PersonCount, persons.Count(x => x.Value.Birthday >= StartDateTime));
+ Assert.Greater(persons.Count(x => x.Value.Birthday > DateTime.UtcNow), 1);
+
+ // Joins
+ var join =
+ from role in roles
+ join person in persons on role.Value.Date equals person.Value.Birthday
+ select person;
+
+ Assert.AreEqual(2, join.Count());
+
+ // Functions
+ 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());
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Functions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Functions.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Functions.cs
new file mode 100644
index 0000000..a672d5a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Functions.cs
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System.Linq;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests where clause.
+ /// </summary>
+ [Test]
+ public void TestWhere()
+ {
+ var cache = GetPersonCache().AsCacheQueryable();
+
+ // Test const and var parameters
+ const int age = 10;
+ var key = 15;
+
+ Assert.AreEqual(age, cache.Where(x => x.Value.Age < age).ToArray().Length);
+ Assert.AreEqual(age, cache.Where(x => x.Value.Address.Zip < age).ToArray().Length);
+ Assert.AreEqual(19, cache.Where(x => x.Value.Age > age && x.Value.Age < 30).ToArray().Length);
+ Assert.AreEqual(20, cache.Where(x => x.Value.Age > age).Count(x => x.Value.Age < 30 || x.Value.Age == 50));
+ Assert.AreEqual(key, cache.Where(x => x.Key < key).ToArray().Length);
+ Assert.AreEqual(key, cache.Where(x => -x.Key > -key).ToArray().Length);
+
+ Assert.AreEqual(1, GetRoleCache().AsCacheQueryable().Where(x => x.Key.Foo < 2).ToArray().Length);
+ Assert.AreEqual(2, GetRoleCache().AsCacheQueryable().Where(x => x.Key.Bar > 2 && x.Value.Name != "11")
+ .ToArray().Length);
+ }
+
+ /// <summary>
+ /// Tests the group by.
+ /// </summary>
+ [Test]
+ public void TestGroupBy()
+ {
+ var persons = GetPersonCache().AsCacheQueryable();
+ var orgs = GetOrgCache().AsCacheQueryable();
+
+ // Simple, unordered
+ CollectionAssert.AreEquivalent(new[] { 1000, 1001 },
+ persons.GroupBy(x => x.Value.OrganizationId).Select(x => x.Key).ToArray());
+
+ // Aggregate
+ Assert.AreEqual(1000,
+ persons.GroupBy(x => x.Value.OrganizationId).Select(x => x.Key).OrderBy(x => x).First());
+
+ // Ordering and count
+ var res1 =
+ from p in persons
+ orderby p.Value.Name
+ group p by p.Value.OrganizationId
+ into gs
+ orderby gs.Key
+ where gs.Count() > 10
+ select new { Count = gs.Count(), OrgId = gs.Key, AvgAge = gs.Average(x => x.Value.Age) };
+
+ var resArr = res1.ToArray();
+
+ Assert.AreEqual(new[]
+ {
+ new {Count = PersonCount/2, OrgId = 1000, AvgAge = (double) PersonCount/2 - 1},
+ new {Count = PersonCount/2, OrgId = 1001, AvgAge = (double) PersonCount/2}
+ }, resArr);
+
+ // Join and sum
+ var res2 = persons.Join(orgs.Where(o => o.Key > 10), p => p.Value.OrganizationId, o => o.Key,
+ (p, o) => new { p, o })
+ .GroupBy(x => x.o.Value.Name)
+ .Select(g => new { Org = g.Key, AgeSum = g.Select(x => x.p.Value.Age).Sum() });
+
+ var resArr2 = res2.ToArray();
+
+ Assert.AreEqual(new[]
+ {
+ new {Org = "Org_0", AgeSum = persons.Where(x => x.Value.OrganizationId == 1000).Sum(x => x.Value.Age)},
+ new {Org = "Org_1", AgeSum = persons.Where(x => x.Value.OrganizationId == 1001).Sum(x => x.Value.Age)}
+ }, resArr2);
+ }
+
+ /// <summary>
+ /// Tests the union.
+ /// </summary>
+ [Test]
+ public void TestUnion()
+ {
+ // Direct union
+ var persons = GetPersonCache().AsCacheQueryable();
+ var persons2 = GetSecondPersonCache().AsCacheQueryable();
+
+ var res = persons.Union(persons2).ToArray();
+
+ Assert.AreEqual(PersonCount * 2, res.Length);
+
+ // Subquery
+ var roles = GetRoleCache().AsCacheQueryable().Select(x => -x.Key.Foo);
+ var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Union(roles).ToArray();
+
+ Assert.AreEqual(RoleCount + PersonCount, ids.Length);
+ }
+
+ /// <summary>
+ /// Tests intersect.
+ /// </summary>
+ [Test]
+ public void TestIntersect()
+ {
+ // Direct intersect
+ var persons = GetPersonCache().AsCacheQueryable();
+ var persons2 = GetSecondPersonCache().AsCacheQueryable();
+
+ var res = persons.Intersect(persons2).ToArray();
+
+ Assert.AreEqual(0, res.Length);
+
+ // Subquery
+ var roles = GetRoleCache().AsCacheQueryable().Select(x => x.Key.Foo);
+ var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Intersect(roles).ToArray();
+
+ Assert.AreEqual(RoleCount, ids.Length);
+ }
+
+ /// <summary>
+ /// Tests except.
+ /// </summary>
+ [Test]
+ public void TestExcept()
+ {
+ // Direct except
+ var persons = GetPersonCache().AsCacheQueryable();
+ var persons2 = GetSecondPersonCache().AsCacheQueryable();
+
+ var res = persons.Except(persons2).ToArray();
+
+ Assert.AreEqual(PersonCount, res.Length);
+
+ // Subquery
+ var roles = GetRoleCache().AsCacheQueryable().Select(x => x.Key.Foo);
+ var ids = GetPersonCache().AsCacheQueryable().Select(x => x.Key).Except(roles).ToArray();
+
+ Assert.AreEqual(PersonCount - RoleCount, ids.Length);
+ }
+
+ /// <summary>
+ /// Tests ordering.
+ /// </summary>
+ [Test]
+ public void TestOrdering()
+ {
+ var persons = GetPersonCache().AsCacheQueryable()
+ .OrderByDescending(x => x.Key)
+ .ThenBy(x => x.Value.Age)
+ .ToArray();
+
+ Assert.AreEqual(Enumerable.Range(0, PersonCount).Reverse().ToArray(),
+ persons.Select(x => x.Key).ToArray());
+
+ var personsByOrg = GetPersonCache().AsCacheQueryable()
+ .Join(GetOrgCache().AsCacheQueryable(), p => p.Value.OrganizationId, o => o.Value.Id,
+ (p, o) => new
+ {
+ PersonId = p.Key,
+ PersonName = p.Value.Name.ToUpper(),
+ OrgName = o.Value.Name
+ })
+ .OrderBy(x => x.OrgName.ToLower())
+ .ThenBy(x => x.PersonName)
+ .ToArray();
+
+ var expectedIds = Enumerable.Range(0, PersonCount)
+ .OrderBy(x => (x % 2).ToString())
+ .ThenBy(x => x.ToString())
+ .ToArray();
+
+ var actualIds = personsByOrg.Select(x => x.PersonId).ToArray();
+
+ Assert.AreEqual(expectedIds, actualIds);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs
new file mode 100644
index 0000000..9430dd8
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Introspection.cs
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System;
+ using System.Linq;
+ using Apache.Ignite.Core.Cache.Query;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests the introspection.
+ /// </summary>
+ [Test]
+ public void TestIntrospection()
+ {
+ var cache = GetPersonCache();
+
+ // Check regular query
+ var query = cache.AsCacheQueryable(new QueryOptions
+ {
+ Local = true,
+ PageSize = 999,
+ EnforceJoinOrder = true,
+ Timeout = TimeSpan.FromSeconds(2.5),
+ ReplicatedOnly = true,
+ Colocated = true
+ }).Where(x => x.Key > 10).ToCacheQueryable();
+
+ Assert.AreEqual(cache.Name, query.CacheName);
+ Assert.AreEqual(cache.Ignite, query.Ignite);
+
+ var fq = query.GetFieldsQuery();
+
+ Assert.AreEqual(
+ GetSqlEscapeAll()
+ ? "select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where (_T0.\"_KEY\" > ?)"
+ : "select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where (_T0._KEY > ?)",
+ fq.Sql);
+
+ Assert.AreEqual(new[] { 10 }, fq.Arguments);
+ Assert.IsTrue(fq.Local);
+ Assert.AreEqual(PersonCount - 11, cache.QueryFields(fq).GetAll().Count);
+ Assert.AreEqual(999, fq.PageSize);
+ Assert.IsFalse(fq.EnableDistributedJoins);
+ Assert.IsTrue(fq.EnforceJoinOrder);
+ Assert.IsTrue(fq.ReplicatedOnly);
+ Assert.IsTrue(fq.Colocated);
+ Assert.AreEqual(TimeSpan.FromSeconds(2.5), fq.Timeout);
+
+ var str = query.ToString();
+ Assert.AreEqual(GetSqlEscapeAll()
+ ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+ "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
+ "(_T0.\"_KEY\" > ?), Arguments=[10], " +
+ "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
+ "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=]]"
+ : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+ "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
+ "(_T0._KEY > ?), Arguments=[10], " +
+ "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
+ "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=]]", str);
+
+ // Check fields query
+ var fieldsQuery = (ICacheQueryable)cache.AsCacheQueryable().Select(x => x.Value.Name);
+
+ Assert.AreEqual(cache.Name, fieldsQuery.CacheName);
+ Assert.AreEqual(cache.Ignite, fieldsQuery.Ignite);
+
+ fq = fieldsQuery.GetFieldsQuery();
+ Assert.AreEqual(GetSqlEscapeAll()
+ ? "select _T0.\"Name\" from \"person_org\".\"Person\" as _T0"
+ : "select _T0.NAME from \"person_org\".Person as _T0",
+ fq.Sql);
+
+ Assert.IsFalse(fq.Local);
+ Assert.AreEqual(SqlFieldsQuery.DefaultPageSize, fq.PageSize);
+ Assert.IsFalse(fq.EnableDistributedJoins);
+ Assert.IsFalse(fq.EnforceJoinOrder);
+
+ str = fieldsQuery.ToString();
+ Assert.AreEqual(GetSqlEscapeAll()
+ ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+ "[Sql=select _T0.\"Name\" from \"person_org\".\"Person\" as _T0, Arguments=[], Local=False, " +
+ "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
+ "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]"
+ : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+ "[Sql=select _T0.NAME from \"person_org\".Person as _T0, Arguments=[], Local=False, " +
+ "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
+ "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]", str);
+
+ // Check distributed joins flag propagation
+ var distrQuery = cache.AsCacheQueryable(new QueryOptions { EnableDistributedJoins = true })
+ .Where(x => x.Key > 10 && x.Value.Age > 20 && x.Value.Name.Contains("x"));
+
+ query = distrQuery.ToCacheQueryable();
+
+ Assert.IsTrue(query.GetFieldsQuery().EnableDistributedJoins);
+
+ str = distrQuery.ToString();
+ Assert.AreEqual(GetSqlEscapeAll()
+ ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+ "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
+ "(((_T0.\"_KEY\" > ?) and (_T0.\"age1\" > ?)) " +
+ "and (_T0.\"Name\" like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
+ "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
+ "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]"
+ : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
+ "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
+ "(((_T0._KEY > ?) and (_T0.AGE1 > ?)) " +
+ "and (_T0.NAME like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
+ "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
+ "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]", str);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.LocalCollection.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.LocalCollection.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.LocalCollection.cs
new file mode 100644
index 0000000..e7e05f4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.LocalCollection.cs
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests the join with local collection.
+ /// </summary>
+ [Test]
+ public void TestLocalJoin()
+ {
+ var persons = GetPersonCache().AsCacheQueryable();
+ var orgs = GetOrgCache().AsCacheQueryable();
+
+ var localOrgs = orgs
+ .Select(e => e.Value)
+ .ToArray();
+
+ var allOrganizationIds = localOrgs
+ .Select(e => e.Id)
+ .ToArray();
+
+ // Join with local collection
+ var qry1 = persons.Join(allOrganizationIds,
+ pe => pe.Value.OrganizationId,
+ i => i,
+ (pe, o) => pe
+ )
+ .ToArray();
+
+ Assert.AreEqual(PersonCount, qry1.Length);
+
+ // Join using expression in innerKeySelector
+ var qry2 = persons.Join(allOrganizationIds,
+ pe => pe.Value.OrganizationId,
+ i => i + 1 - 1,
+ (pe, o) => pe
+ )
+ .ToArray();
+
+ Assert.AreEqual(PersonCount, qry2.Length);
+
+ // Local collection subquery
+ var qry3 = persons.Join(localOrgs.Select(e => e.Id),
+ pe => pe.Value.OrganizationId,
+ i => i,
+ (pe, o) => pe
+ )
+ .ToArray();
+
+ Assert.AreEqual(PersonCount, qry3.Length);
+
+ // Compiled query
+ var qry4 = CompiledQuery.Compile(() => persons.Join(allOrganizationIds,
+ pe => pe.Value.OrganizationId,
+ i => i,
+ (pe, o) => pe
+ ));
+
+ Assert.AreEqual(PersonCount, qry4().Count());
+
+ // Compiled query with outer join
+ var qry4A = CompiledQuery.Compile(() => persons.Join(new int[] { }.DefaultIfEmpty(),
+ pe => pe.Value.OrganizationId,
+ i => i,
+ (pe, o) => pe
+ ));
+
+ Assert.AreEqual(PersonCount, qry4A().Count());
+
+ // Compiled query
+ var qry5 = CompiledQuery.Compile(() => persons.Join(new[] { -1, -2 }.DefaultIfEmpty(),
+ pe => pe.Value.OrganizationId,
+ i => i,
+ (pe, o) => pe
+ ));
+
+ Assert.AreEqual(PersonCount, qry5().Count());
+
+ // Outer join
+ var qry6 = persons.Join(new[] { -1, -2 }.DefaultIfEmpty(),
+ pe => pe.Value.OrganizationId,
+ i => i,
+ (pe, o) => pe
+ )
+ .ToArray();
+
+ Assert.AreEqual(PersonCount, qry6.Length);
+
+ // Join with local list
+ var qry7 = persons.Join(new List<int> { 1000, 1001, 1002, 1003 },
+ pe => pe.Value.OrganizationId,
+ i => i,
+ (pe, o) => pe
+ )
+ .ToArray();
+
+ Assert.AreEqual(PersonCount, qry7.Length);
+
+ // Join with local list variable
+ var list = new List<int> { 1000, 1001, 1002, 1003 };
+ var qry8 = persons.Join(list,
+ pe => pe.Value.OrganizationId,
+ i => i,
+ (pe, o) => pe
+ )
+ .ToArray();
+
+ Assert.AreEqual(PersonCount, qry8.Length);
+ }
+
+ /// <summary>
+ /// Tests the compiled query containing join with local collection passed as parameter.
+ /// </summary>
+ [Test]
+ [Ignore("IGNITE-5404")]
+ public void TestLocalJoinCompiledQueryParameter()
+ {
+ var persons = GetPersonCache().AsCacheQueryable();
+ var orgs = GetOrgCache().AsCacheQueryable();
+
+ var localOrgs = orgs
+ .Select(e => e.Value)
+ .ToArray();
+
+ var allOrganizationIds = localOrgs
+ .Select(e => e.Id)
+ .ToArray();
+
+ // Join with local collection passed as parameter
+ var qry1 = CompiledQuery.Compile((IEnumerable<int> lc) => persons.Join(lc,
+ pe => pe.Value.OrganizationId,
+ i => i,
+ (pe, o) => pe
+ ));
+
+ Assert.AreEqual(PersonCount, qry1(allOrganizationIds).Count());
+
+ //Compiled query with outer join
+ var qry2 = CompiledQuery.Compile((IEnumerable<int> lc) => persons.Join(lc.DefaultIfEmpty(),
+ pe => pe.Value.OrganizationId,
+ i => i,
+ (pe, o) => pe
+ ));
+
+ Assert.AreEqual(PersonCount, qry2(new[] { -11 }).Count());
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/84c7427a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs
new file mode 100644
index 0000000..f589329
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable SuspiciousTypeConversion.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable StringIndexOfIsCultureSpecific.1
+// ReSharper disable StringIndexOfIsCultureSpecific.2
+// ReSharper disable StringCompareToIsCultureSpecific
+// ReSharper disable StringCompareIsCultureSpecific.1
+// ReSharper disable UnusedMemberInSuper.Global
+namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
+{
+ using System;
+ using System.Linq;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests LINQ.
+ /// </summary>
+ public partial class CacheLinqTest
+ {
+ /// <summary>
+ /// Tests the same cache join.
+ /// </summary>
+ [Test]
+ public void TestSameCacheJoin()
+ {
+ // Select persons in specific organization
+ var organizations = GetOrgCache().AsCacheQueryable();
+ var persons = GetPersonCache().AsCacheQueryable();
+
+ var res = persons.Join(organizations, person => person.Value.OrganizationId + 3, org => org.Value.Id + 3,
+ (person, org) => new { Person = person.Value, Org = org.Value })
+ .Where(x => x.Org.Name == "Org_1")
+ .ToList();
+
+ Assert.AreEqual(PersonCount / 2, res.Count);
+
+ Assert.IsTrue(res.All(r => r.Person.OrganizationId == r.Org.Id));
+
+ // Test full projection (selects pair of ICacheEntry)
+ var res2 = persons.Join(organizations, person => person.Value.OrganizationId - 1, org => org.Value.Id - 1,
+ (person, org) => new { Person = person, Org = org })
+ .Where(x => x.Org.Value.Name.ToLower() == "org_0")
+ .ToList();
+
+ Assert.AreEqual(PersonCount / 2, res2.Count);
+ }
+
+ /// <summary>
+ /// Tests the multi key join.
+ /// </summary>
+ [Test]
+ public void TestMultiKeyJoin()
+ {
+ var organizations = GetOrgCache().AsCacheQueryable();
+ var persons = GetPersonCache().AsCacheQueryable();
+
+ var multiKey =
+ from person in persons
+ join org in organizations on
+ new { OrgId = person.Value.OrganizationId, person.Key } equals
+ new { OrgId = org.Value.Id, Key = org.Key - 1000 }
+ where person.Key == 1
+ select new { PersonName = person.Value.Name, OrgName = org.Value.Name };
+
+ Assert.AreEqual(" Person_1 ", multiKey.Single().PersonName);
+ }
+
+ /// <summary>
+ /// Tests the cross cache join.
+ /// </summary>
+ [Test]
+ public void TestCrossCacheJoin()
+ {
+ var persons = GetPersonCache().AsCacheQueryable();
+ var roles = GetRoleCache().AsCacheQueryable();
+
+ var res = persons.Join(roles, person => person.Key, role => role.Key.Foo, (person, role) => role)
+ .OrderBy(x => x.Key.Bar)
+ .ToArray();
+
+ Assert.AreEqual(RoleCount, res.Length);
+ Assert.AreEqual(101, res[0].Key.Bar);
+ }
+
+ /// <summary>
+ /// Tests the cross cache join.
+ /// </summary>
+ [Test]
+ public void TestCrossCacheJoinInline()
+ {
+ var res = GetPersonCache().AsCacheQueryable().Join(GetRoleCache().AsCacheQueryable(),
+ person => person.Key, role => role.Key.Foo, (person, role) => role)
+ .OrderBy(x => x.Key.Bar).ToArray();
+
+ Assert.AreEqual(RoleCount, res.Length);
+ Assert.AreEqual(101, res[0].Key.Bar);
+ }
+
+ /// <summary>
+ /// Tests the multi cache join.
+ /// </summary>
+ [Test]
+ public void TestMultiCacheJoin()
+ {
+ var organizations = GetOrgCache().AsCacheQueryable();
+ var persons = GetPersonCache().AsCacheQueryable();
+ var roles = GetRoleCache().AsCacheQueryable();
+
+ var res = roles.Join(persons, role => role.Key.Foo, person => person.Key,
+ (role, person) => new { person, role })
+ .Join(organizations, pr => pr.person.Value.OrganizationId, org => org.Value.Id,
+ (pr, org) => new { org, pr.person, pr.role }).ToArray();
+
+ Assert.AreEqual(RoleCount, res.Length);
+ }
+
+ /// <summary>
+ /// Tests the multi cache join subquery.
+ /// </summary>
+ [Test]
+ public void TestMultiCacheJoinSubquery()
+ {
+ var organizations = GetOrgCache().AsCacheQueryable().Where(x => x.Key == 1001);
+ var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key < 20);
+ var roles = GetRoleCache().AsCacheQueryable().Where(x => x.Key.Foo >= 0);
+
+ var res = roles.Join(persons, role => role.Key.Foo, person => person.Key,
+ (role, person) => new { person, role })
+ .Join(organizations, pr => pr.person.Value.OrganizationId, org => org.Value.Id,
+ (pr, org) => new { org, pr.person, pr.role }).ToArray();
+
+ Assert.AreEqual(2, res.Length);
+ }
+
+ /// <summary>
+ /// Tests the outer join.
+ /// </summary>
+ [Test]
+ public void TestOuterJoin()
+ {
+ var persons = GetPersonCache().AsCacheQueryable();
+ var roles = GetRoleCache().AsCacheQueryable();
+
+ var res = persons.Join(roles.Where(r => r.Key.Bar > 0).DefaultIfEmpty(),
+ person => person.Key, role => role.Key.Foo,
+ (person, role) => new
+ {
+ PersonName = person.Value.Name,
+ RoleName = role.Value.Name
+ })
+ .Where(x => x.PersonName != " ")
+ .ToArray();
+
+ Assert.AreEqual(PersonCount, res.Length);
+ }
+
+ /// <summary>
+ /// Tests the subquery join.
+ /// </summary>
+ [Test]
+ public void TestSubqueryJoin()
+ {
+ var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key >= 0);
+
+ var orgs = GetOrgCache().AsCacheQueryable().Where(x => x.Key > 10);
+
+ var qry1 = persons.Join(orgs,
+ p => p.Value.OrganizationId,
+ o => o.Value.Id,
+ (p, o) => p)
+ .Where(x => x.Key >= 0)
+ .ToList();
+
+ Assert.AreEqual(PersonCount, qry1.Count);
+
+ // With selector inline
+ var qry2 = persons
+ .Join(orgs.Select(orgEntry => orgEntry.Key),
+ e => e.Value.OrganizationId,
+ i => i,
+ (e, i) => e)
+ .ToList();
+
+ Assert.AreEqual(PersonCount, qry2.Count);
+
+ // With selector from variable
+ var innerSequence = orgs
+ .Select(orgEntry => orgEntry.Key);
+
+ var qry3 = persons
+ .Join(innerSequence,
+ e => e.Value.OrganizationId,
+ i => i,
+ (e, i) => e)
+ .ToList();
+
+ Assert.AreEqual(PersonCount, qry3.Count);
+ }
+
+ /// <summary>
+ /// Tests the invalid join.
+ /// </summary>
+ [Test]
+ public void TestInvalidJoin()
+ {
+ var localComplexTypeCollection = GetOrgCache().AsCacheQueryable()
+ .Select(e => e.Value)
+ .ToArray();
+
+ // Join on non-IQueryable with complex(not supported) type
+ var ex = Assert.Throws<NotSupportedException>(() =>
+ // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
+ {
+ GetPersonCache().AsCacheQueryable().Join(localComplexTypeCollection, p => p.Value.OrganizationId,
+ o => o.Id, (p, o) => p).ToList();
+ });
+
+ Assert.IsTrue(ex.Message.StartsWith("Not supported item type for Join with local collection"));
+ }
+
+ /// <summary>
+ /// Tests query with multiple from clause.
+ /// </summary>
+ [Test]
+ public void TestMultipleFrom()
+ {
+ var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key < PersonCount);
+ var roles = GetRoleCache().AsCacheQueryable().Where(x => x.Value.Name != "1");
+
+ var all = persons.SelectMany(person => roles.Select(role => new { role, person }));
+ Assert.AreEqual(RoleCount * PersonCount, all.Count());
+
+ var filtered =
+ from person in persons
+ from role in roles
+ where person.Key == role.Key.Foo
+ select new { Person = person.Value.Name, Role = role.Value.Name };
+
+ var res = filtered.ToArray();
+
+ Assert.AreEqual(RoleCount, res.Length);
+ }
+
+ /// <summary>
+ /// Tests query with multiple from clause with inline query sources.
+ /// </summary>
+ [Test]
+ public void TestMultipleFromInline()
+ {
+ var filtered =
+ from person in GetPersonCache().AsCacheQueryable()
+ from role in GetRoleCache().AsCacheQueryable()
+ where person.Key == role.Key.Foo
+ select new { Person = person.Value.Name, Role = role.Value.Name };
+
+ var res = filtered.ToArray();
+
+ Assert.AreEqual(RoleCount, res.Length);
+ }
+
+ /// <summary>
+ /// Tests the join of a table to itself.
+ /// </summary>
+ [Test]
+ public void TestSelfJoin()
+ {
+ // Different queryables
+ var p1 = GetPersonCache().AsCacheQueryable();
+ var p2 = GetPersonCache().AsCacheQueryable();
+
+ var qry = p1.Join(p2, x => x.Value.Age, x => x.Key, (x, y) => x.Key);
+ Assert.AreEqual(PersonCount, qry.ToArray().Distinct().Count());
+
+ // Same queryables
+ var qry2 = p1.Join(p1, x => x.Value.Age, x => x.Key, (x, y) => x.Key);
+ Assert.AreEqual(PersonCount, qry2.ToArray().Distinct().Count());
+ }
+
+ /// <summary>
+ /// Tests the join of a table to itself with inline queryable.
+ /// </summary>
+ [Test]
+ public void TestSelfJoinInline()
+ {
+ var qry = GetPersonCache().AsCacheQueryable().Join(GetPersonCache().AsCacheQueryable(),
+ x => x.Value.Age, x => x.Key, (x, y) => x.Key);
+
+ Assert.AreEqual(PersonCount, qry.ToArray().Distinct().Count());
+ }
+ }
+}
\ No newline at end of file