Repository: ignite Updated Branches: refs/heads/ignite-3560 3180190e4 -> 8d55120cb
IGNITE-3561 .NET: DistributedJoins property in SqlQuery & SqlFieldsQuery Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/856b536d Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/856b536d Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/856b536d Branch: refs/heads/ignite-3560 Commit: 856b536db66edf9e7e6fc1b96da55a0e846c70c3 Parents: 37195a0 Author: Pavel Tupitsyn <ptupit...@apache.org> Authored: Mon Jul 25 18:54:11 2016 +0300 Committer: Pavel Tupitsyn <ptupit...@apache.org> Committed: Mon Jul 25 18:54:11 2016 +0300 ---------------------------------------------------------------------- .../org/apache/ignite/cache/query/SqlQuery.java | 3 + .../platform/cache/PlatformCache.java | 10 +- .../core/include/ignite/cache/query/query_sql.h | 2 + .../ignite/cache/query/query_sql_fields.h | 3 + .../Cache/Query/CacheLinqTest.cs | 20 +- .../Cache/Query/CacheQueriesTest.cs | 252 +++++-------------- .../Cache/Query/SqlFieldsQuery.cs | 27 +- .../Apache.Ignite.Core/Cache/Query/SqlQuery.cs | 13 + .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs | 3 + .../Apache.Ignite.Linq/CacheExtensions.cs | 39 ++- .../Impl/CacheFieldsQueryExecutor.cs | 63 ++++- .../Apache.Ignite.Linq/Impl/CacheQueryable.cs | 11 +- .../Impl/CacheQueryableBase.cs | 7 +- 13 files changed, 257 insertions(+), 196 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java b/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java index e05ff13..f809b8d 100644 --- a/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java +++ b/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java @@ -154,6 +154,9 @@ public final class SqlQuery<K, V> extends Query<Cache.Entry<K, V>> { /** * Specify if distributed joins are enabled for this query. * + * When disabled, join results will only contain colocated data (joins work locally). + * When enabled, joins work as expected, no matter how the data is distributed. + * * @param distributedJoins Distributed joins enabled. * @return {@code this} For chaining. */ http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java index 9bf330c..d572e8b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java @@ -943,7 +943,9 @@ public class PlatformCache extends PlatformAbstractTarget { Object[] args = readQueryArgs(reader); - return new SqlQuery(typ, sql).setPageSize(pageSize).setArgs(args).setLocal(loc); + boolean distrJoins = reader.readBoolean(); + + return new SqlQuery(typ, sql).setPageSize(pageSize).setArgs(args).setLocal(loc).setDistributedJoins(distrJoins); } /** @@ -956,7 +958,11 @@ public class PlatformCache extends PlatformAbstractTarget { Object[] args = readQueryArgs(reader); - return new SqlFieldsQuery(sql).setPageSize(pageSize).setArgs(args).setLocal(loc); + boolean distrJoins = reader.readBoolean(); + boolean enforceJoinOrder = reader.readBoolean(); + + return new SqlFieldsQuery(sql).setPageSize(pageSize).setArgs(args).setLocal(loc) + .setDistributedJoins(distrJoins).setEnforceJoinOrder(enforceJoinOrder); } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h index f7a00fa..cb7a739 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h +++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h @@ -228,6 +228,8 @@ namespace ignite for (std::vector<QueryArgumentBase*>::const_iterator it = args.begin(); it != args.end(); ++it) (*it)->Write(writer); + + writer.WriteBool(false); // distributed joins } private: http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h index e21fc93..1c8570b 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h +++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h @@ -200,6 +200,9 @@ namespace ignite for (std::vector<QueryArgumentBase*>::const_iterator it = args.begin(); it != args.end(); ++it) (*it)->Write(writer); + + writer.WriteBool(false); // distributed joins + writer.WriteBool(false); // enforce join order } private: http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs index 08a4bdc..f76a74c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs @@ -35,6 +35,8 @@ namespace Apache.Ignite.Core.Tests.Cache.Query 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; @@ -953,7 +955,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query var cache = GetPersonCache(); // Check regular query - var query = (ICacheQueryable) cache.AsCacheQueryable(true).Where(x => x.Key > 10); + var query = (ICacheQueryable) cache.AsCacheQueryable(true, null, 999, false, true).Where(x => x.Key > 10); Assert.AreEqual(cache.Name, query.CacheName); Assert.AreEqual(cache.Ignite, query.Ignite); @@ -963,6 +965,9 @@ namespace Apache.Ignite.Core.Tests.Cache.Query 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); // Check fields query var fieldsQuery = (ICacheQueryable) cache.AsCacheQueryable().Select(x => x.Value.Name); @@ -973,6 +978,19 @@ namespace Apache.Ignite.Core.Tests.Cache.Query fq = fieldsQuery.GetFieldsQuery(); Assert.AreEqual("select _T0.Name from \"\".Person as _T0", fq.Sql); Assert.IsFalse(fq.Local); + Assert.AreEqual(SqlFieldsQuery.DfltPageSize, fq.PageSize); + Assert.IsFalse(fq.EnableDistributedJoins); + Assert.IsFalse(fq.EnforceJoinOrder); + + // Check distributed joins flag propagation + var distrQuery = cache.AsCacheQueryable(true, null, 999, true, true).Where(x => x.Key > 10); + query = (ICacheQueryable) distrQuery; + Assert.IsTrue(query.GetFieldsQuery().EnableDistributedJoins); + + // Easy check that EnableDistributedJoins is propagated to Java: it throws an error on replicated cache + var ex = Assert.Throws<IgniteException>(() => Assert.AreEqual(0, distrQuery.ToArray().Length)); + Assert.AreEqual("Queries using distributed JOINs have to be run on partitioned cache, not on replicated.", + ex.Message); } /// <summary> http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs index 6ed76678..7bfd202 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs @@ -25,6 +25,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query using System.Text; 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.Core.Impl.Binary; @@ -33,7 +34,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// <summary> /// Queries tests. /// </summary> - public class CacheQueriesTest + public sealed class CacheQueriesTest { /** Grid count. */ private const int GridCnt = 2; @@ -51,7 +52,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// /// </summary> [TestFixtureSetUp] - public virtual void StartGrids() + public void StartGrids() { TestUtils.JvmDebug = true; TestUtils.KillProcesses(); @@ -84,7 +85,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// /// </summary> [TestFixtureTearDown] - public virtual void StopGrids() + public void StopGrids() { for (int i = 0; i < GridCnt; i++) Ignition.Stop("grid-" + i, true); @@ -94,7 +95,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// /// </summary> [SetUp] - public virtual void BeforeTest() + public void BeforeTest() { Console.WriteLine("Test started: " + TestContext.CurrentContext.Test.Name); } @@ -103,7 +104,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// /// </summary> [TearDown] - public virtual void AfterTest() + public void AfterTest() { var cache = Cache(); @@ -126,7 +127,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// </summary> /// <param name="idx"></param> /// <returns></returns> - public IIgnite GetIgnite(int idx) + private IIgnite GetIgnite(int idx) { return Ignition.GetIgnite("grid-" + idx); } @@ -136,7 +137,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// </summary> /// <param name="idx"></param> /// <returns></returns> - public ICache<int, QueryPerson> Cache(int idx) + private ICache<int, QueryPerson> Cache(int idx) { return GetIgnite(idx).GetCache<int, QueryPerson>(CacheName); } @@ -145,7 +146,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// /// </summary> /// <returns></returns> - public ICache<int, QueryPerson> Cache() + private ICache<int, QueryPerson> Cache() { return Cache(0); } @@ -270,6 +271,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// <summary> /// Test SQL query arguments passing. /// </summary> + [Test] public void TestSqlQueryArguments() { Cache().Put(1, new QueryPerson("Ivanov", 30)); @@ -289,6 +291,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// <summary> /// Test SQL fields query arguments passing. /// </summary> + [Test] public void TestSqlFieldsQueryArguments() { Cache().Put(1, new QueryPerson("Ivanov", 30)); @@ -352,53 +355,19 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// Check SQL query. /// </summary> [Test] - public void TestSqlQuery() - { - CheckSqlQuery(MaxItemCnt, false, false); - } - - /// <summary> - /// Check SQL query in binary mode. - /// </summary> - [Test] - public void TestSqlQueryBinary() - { - CheckSqlQuery(MaxItemCnt, false, true); - } - - /// <summary> - /// Check local SQL query. - /// </summary> - [Test] - public void TestSqlQueryLocal() - { - CheckSqlQuery(MaxItemCnt, true, false); - } - - /// <summary> - /// Check local SQL query in binary mode. - /// </summary> - [Test] - public void TestSqlQueryLocalBinary() - { - CheckSqlQuery(MaxItemCnt, true, true); - } - - /// <summary> - /// Check SQL query. - /// </summary> - /// <param name="cnt">Amount of cache entries to create.</param> - /// <param name="loc">Local query flag.</param> - /// <param name="keepBinary">Keep binary flag.</param> - private void CheckSqlQuery(int cnt, bool loc, bool keepBinary) + public void TestSqlQuery([Values(true, false)] bool loc, [Values(true, false)] bool keepBinary, + [Values(true, false)] bool distrJoin) { var cache = Cache(); // 1. Populate cache with data, calculating expected count in parallel. - var exp = PopulateCache(cache, loc, cnt, x => x < 50); + var exp = PopulateCache(cache, loc, MaxItemCnt, x => x < 50); // 2. Validate results. - var qry = new SqlQuery(typeof(QueryPerson), "age < 50", loc); + var qry = new SqlQuery(typeof(QueryPerson), "age < 50", loc) + { + EnableDistributedJoins = distrJoin + }; ValidateQueryResults(cache, qry, exp, keepBinary); } @@ -407,35 +376,22 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// Check SQL fields query. /// </summary> [Test] - public void TestSqlFieldsQuery() + public void TestSqlFieldsQuery([Values(true, false)] bool loc, [Values(true, false)] bool distrJoin, + [Values(true, false)] bool enforceJoinOrder) { - CheckSqlFieldsQuery(MaxItemCnt, false); - } + int cnt = MaxItemCnt; - /// <summary> - /// Check local SQL fields query. - /// </summary> - [Test] - public void TestSqlFieldsQueryLocal() - { - CheckSqlFieldsQuery(MaxItemCnt, true); - } - - /// <summary> - /// Check SQL fields query. - /// </summary> - /// <param name="cnt">Amount of cache entries to create.</param> - /// <param name="loc">Local query flag.</param> - private void CheckSqlFieldsQuery(int cnt, bool loc) - { var cache = Cache(); // 1. Populate cache with data, calculating expected count in parallel. var exp = PopulateCache(cache, loc, cnt, x => x < 50); - // 2. Vlaidate results. - SqlFieldsQuery qry = loc ? new SqlFieldsQuery("SELECT name, age FROM QueryPerson WHERE age < 50", true) : - new SqlFieldsQuery("SELECT name, age FROM QueryPerson WHERE age < 50"); + // 2. Validate results. + var qry = new SqlFieldsQuery("SELECT name, age FROM QueryPerson WHERE age < 50", loc) + { + EnableDistributedJoins = distrJoin, + EnforceJoinOrder = enforceJoinOrder + }; using (IQueryCursor<IList> cursor = cache.QueryFields(qry)) { @@ -471,113 +427,20 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// Check text query. /// </summary> [Test] - public void TestTextQuery() - { - CheckTextQuery(MaxItemCnt, false, false); - } - - /// <summary> - /// Check SQL query in binary mode. - /// </summary> - [Test] - public void TestTextQueryBinary() - { - CheckTextQuery(MaxItemCnt, false, true); - } - - /// <summary> - /// Check local SQL query. - /// </summary> - [Test] - public void TestTextQueryLocal() - { - CheckTextQuery(MaxItemCnt, true, false); - } - - /// <summary> - /// Check local SQL query in binary mode. - /// </summary> - [Test] - public void TestTextQueryLocalBinary() - { - CheckTextQuery(MaxItemCnt, true, true); - } - - /// <summary> - /// Check text query. - /// </summary> - /// <param name="cnt">Amount of cache entries to create.</param> - /// <param name="loc">Local query flag.</param> - /// <param name="keepBinary">Keep binary flag.</param> - private void CheckTextQuery(int cnt, bool loc, bool keepBinary) + public void TestTextQuery([Values(true, false)] bool loc, [Values(true, false)] bool keepBinary) { var cache = Cache(); // 1. Populate cache with data, calculating expected count in parallel. - var exp = PopulateCache(cache, loc, cnt, x => x.ToString().StartsWith("1")); + var exp = PopulateCache(cache, loc, MaxItemCnt, x => x.ToString().StartsWith("1")); // 2. Validate results. - TextQuery qry = loc ? new TextQuery(typeof(QueryPerson), "1*", true) : - new TextQuery(typeof(QueryPerson), "1*"); + var qry = new TextQuery(typeof(QueryPerson), "1*", loc); ValidateQueryResults(cache, qry, exp, keepBinary); } /// <summary> - /// Check scan query. - /// </summary> - [Test] - public void TestScanQuery() - { - CheckScanQuery<QueryPerson>(MaxItemCnt, false, false); - } - - /// <summary> - /// Check scan query in binary mode. - /// </summary> - [Test] - public void TestScanQueryBinary() - { - CheckScanQuery<BinaryObject>(MaxItemCnt, false, true); - } - - /// <summary> - /// Check local scan query. - /// </summary> - [Test] - public void TestScanQueryLocal() - { - CheckScanQuery<QueryPerson>(MaxItemCnt, true, false); - } - - /// <summary> - /// Check local scan query in binary mode. - /// </summary> - [Test] - public void TestScanQueryLocalBinary() - { - CheckScanQuery<BinaryObject>(MaxItemCnt, true, true); - } - - /// <summary> - /// Check scan query with partitions. - /// </summary> - [Test] - public void TestScanQueryPartitions([Values(true, false)] bool loc) - { - CheckScanQueryPartitions<QueryPerson>(MaxItemCnt, loc, false); - } - - /// <summary> - /// Check scan query with partitions in binary mode. - /// </summary> - [Test] - public void TestScanQueryPartitionsBinary([Values(true, false)] bool loc) - { - CheckScanQueryPartitions<BinaryObject>(MaxItemCnt, loc, true); - } - - /// <summary> /// Tests that query attempt on non-indexed cache causes an exception. /// </summary> [Test] @@ -603,12 +466,11 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// <summary> /// Check scan query. /// </summary> - /// <param name="cnt">Amount of cache entries to create.</param> - /// <param name="loc">Local query flag.</param> - /// <param name="keepBinary">Keep binary flag.</param> - private void CheckScanQuery<TV>(int cnt, bool loc, bool keepBinary) + [Test] + public void TestScanQuery<TV>([Values(true, false)] bool loc, [Values(true, false)] bool keepBinary) { var cache = Cache(); + var cnt = MaxItemCnt; // No predicate var exp = PopulateCache(cache, loc, cnt, x => true); @@ -641,15 +503,14 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// <summary> /// Checks scan query with partitions. /// </summary> - /// <param name="cnt">Amount of cache entries to create.</param> - /// <param name="loc">Local query flag.</param> - /// <param name="keepBinary">Keep binary flag.</param> - private void CheckScanQueryPartitions<TV>(int cnt, bool loc, bool keepBinary) + [Test] + public void TestScanQueryPartitions<TV>([Values(true, false)] bool loc, [Values(true, false)] bool keepBinary) { StopGrids(); StartGrids(); var cache = Cache(); + var cnt = MaxItemCnt; var aff = cache.Ignite.GetAffinity(CacheName); var exp = PopulateCache(cache, loc, cnt, x => true); // populate outside the loop (slow) @@ -686,6 +547,39 @@ namespace Apache.Ignite.Core.Tests.Cache.Query } /// <summary> + /// Tests the distributed joins flag. + /// </summary> + [Test] + public void TestDistributedJoins() + { + // Easy check that EnableDistributedJoins is propagated to Java: it throws an error on replicated cache + var cache = GetIgnite(0).GetOrCreateCache<int, QueryPerson>( + new CacheConfiguration("replicatedCache") + { + CacheMode = CacheMode.Replicated, + QueryEntities = new[] + { + new QueryEntity(typeof(QueryPerson)) + { + Fields = new[] {new QueryField("age", typeof(int))} + } + } + }); + + cache[1] = new QueryPerson("Test", 150); + + // Distributed joins disabled: query works + var qry = new SqlQuery(typeof(QueryPerson), "age < 50"); + Assert.AreEqual(0, cache.Query(qry).GetAll().Count); + + // Distributed joins enabled: query fails + qry.EnableDistributedJoins = true; + var ex = Assert.Throws<IgniteException>(() => Assert.AreEqual(0, cache.Query(qry).GetAll().Count)); + Assert.AreEqual("Queries using distributed JOINs have to be run on partitioned cache, not on replicated.", + ex.Message); + } + + /// <summary> /// Validates the query results. /// </summary> /// <param name="cache">Cache.</param> @@ -853,14 +747,6 @@ namespace Apache.Ignite.Core.Tests.Cache.Query /// <summary> /// Constructor. /// </summary> - public QueryPerson() - { - // No-op. - } - - /// <summary> - /// Constructor. - /// </summary> /// <param name="name">Name.</param> /// <param name="age">Age.</param> public QueryPerson(string name, int age) http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs index 1753a8b..ed9d0eb 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs @@ -74,8 +74,33 @@ namespace Apache.Ignite.Core.Cache.Query /// <summary> /// Optional page size. /// <para /> - /// Defautls to <see cref="DfltPageSize"/>. + /// Defaults to <see cref="DfltPageSize"/>. /// </summary> public int PageSize { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether distributed joins should be enabled for this query. + /// <para /> + /// When disabled, join results will only contain colocated data (joins work locally). + /// When enabled, joins work as expected, no matter how the data is distributed. + /// </summary> + /// <value> + /// <c>true</c> if enable distributed joins should be enabled; otherwise, <c>false</c>. + /// </value> + public bool EnableDistributedJoins { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether join order of tables should be enforced. + /// <para /> + /// When true, query optimizer will not reorder tables in join. + /// <para /> + /// It is not recommended to enable this property until you are sure that your indexes + /// and the query itself are correct and tuned as much as possible but + /// query optimizer still produces wrong join order. + /// </summary> + /// <value> + /// <c>true</c> if join order should be enforced; otherwise, <c>false</c>. + /// </value> + public bool EnforceJoinOrder { get; set; } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlQuery.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlQuery.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlQuery.cs index 0e3c887..70e08b2 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlQuery.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlQuery.cs @@ -97,6 +97,17 @@ namespace Apache.Ignite.Core.Cache.Query [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public object[] Arguments { get; set; } + /// <summary> + /// Gets or sets a value indicating whether distributed joins should be enabled for this query. + /// <para /> + /// When disabled, join results will only contain colocated data (joins work locally). + /// When enabled, joins work as expected, no matter how the data is distributed. + /// </summary> + /// <value> + /// <c>true</c> if enable distributed joins should be enabled; otherwise, <c>false</c>. + /// </value> + public bool EnableDistributedJoins { get; set; } + /** <inheritDoc /> */ internal override void Write(BinaryWriter writer, bool keepBinary) { @@ -113,6 +124,8 @@ namespace Apache.Ignite.Core.Cache.Query writer.WriteInt(PageSize); WriteQueryArgs(writer, Arguments); + + writer.WriteBoolean(EnableDistributedJoins); } /** <inheritDoc /> */ http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs index 6afbc67..32c59de 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs @@ -977,6 +977,9 @@ namespace Apache.Ignite.Core.Impl.Cache WriteQueryArgs(writer, qry.Arguments); + writer.WriteBoolean(qry.EnableDistributedJoins); + writer.WriteBoolean(qry.EnforceJoinOrder); + FinishMarshal(writer); cursor = UU.CacheOutOpQueryCursor(Target, (int) CacheOp.QrySqlFields, stream.SynchronizeOutput()); http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs index ecea4ed..e6d585c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs @@ -20,6 +20,7 @@ namespace Apache.Ignite.Linq using System.Linq; using Apache.Ignite.Core.Cache; using Apache.Ignite.Core.Cache.Configuration; + using Apache.Ignite.Core.Cache.Query; using Apache.Ignite.Linq.Impl; /// <summary> @@ -92,7 +93,43 @@ namespace Apache.Ignite.Linq public static IQueryable<ICacheEntry<TKey, TValue>> AsCacheQueryable<TKey, TValue>( this ICache<TKey, TValue> cache, bool local, string tableName) { - return new CacheQueryable<TKey, TValue>(cache, local, tableName); + return cache.AsCacheQueryable(local, tableName, SqlFieldsQuery.DfltPageSize, false, false); + } + + /// <summary> + /// Gets an <see cref="IQueryable{T}" /> instance over this cache. + /// <para /> + /// Resulting query will be translated to cache SQL query and executed over the cache instance + /// via either <see cref="ICache{TK,TV}.Query" /> or <see cref="ICache{TK,TV}.QueryFields" />, + /// depending on requested result. + /// <para /> + /// Result of this method (and subsequent query) can be cast to <see cref="ICacheQueryable" /> for introspection. + /// </summary> + /// <typeparam name="TKey">The type of the key.</typeparam> + /// <typeparam name="TValue">The type of the value.</typeparam> + /// <param name="cache">The cache.</param> + /// <param name="local">Local flag. When set query will be executed only on local node, so only local + /// entries will be returned as query result.</param> + /// <param name="tableName">Name of the table. + /// <para /> + /// Table name is equal to short class name of a cache value. + /// When a cache has only one type of values, or only one <see cref="QueryEntity" /> defined, + /// table name will be inferred and can be omitted.</param> + /// <param name="pageSize">Query cursor page size. + /// Defaults to <see cref="SqlFieldsQuery.DfltPageSize"/>.</param> + /// <param name="enableDistributedJoins">Distributed joins option, see + /// <see cref="SqlFieldsQuery.EnableDistributedJoins" />.</param> + /// <param name="enforceJoinOrder">Enforce join order flag, + /// see <see cref="SqlFieldsQuery.EnforceJoinOrder" />.</param> + /// <returns> + /// <see cref="IQueryable{T}" /> instance over this cache. + /// </returns> + public static IQueryable<ICacheEntry<TKey, TValue>> AsCacheQueryable<TKey, TValue>( + this ICache<TKey, TValue> cache, bool local, string tableName, int pageSize, + bool enableDistributedJoins, bool enforceJoinOrder) + { + return new CacheQueryable<TKey, TValue>(cache, local, tableName, pageSize, enableDistributedJoins, + enforceJoinOrder); } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs index c715e4c..7464a03 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs @@ -46,17 +46,33 @@ namespace Apache.Ignite.Linq.Impl /** */ private readonly bool _local; + /** */ + private readonly int _pageSize; + + /** */ + private readonly bool _enableDistributedJoins; + + /** */ + private readonly bool _enforceJoinOrder; + /// <summary> /// Initializes a new instance of the <see cref="CacheFieldsQueryExecutor" /> class. /// </summary> /// <param name="cache">The executor function.</param> /// <param name="local">Local flag.</param> - public CacheFieldsQueryExecutor(ICacheInternal cache, bool local) + /// <param name="pageSize">Size of the page.</param> + /// <param name="enableDistributedJoins">Distributed joins flag.</param> + /// <param name="enforceJoinOrder">Enforce join order flag.</param> + public CacheFieldsQueryExecutor(ICacheInternal cache, bool local, int pageSize, bool enableDistributedJoins, + bool enforceJoinOrder) { Debug.Assert(cache != null); _cache = cache; _local = local; + _pageSize = pageSize; + _enableDistributedJoins = enableDistributedJoins; + _enforceJoinOrder = enforceJoinOrder; } /// <summary> @@ -67,6 +83,30 @@ namespace Apache.Ignite.Linq.Impl get { return _local; } } + /// <summary> + /// Gets the size of the page. + /// </summary> + public int PageSize + { + get { return _pageSize; } + } + + /// <summary> + /// Gets a value indicating whether distributed joins are enabled. + /// </summary> + public bool EnableDistributedJoins + { + get { return _enableDistributedJoins; } + } + + /// <summary> + /// Gets a value indicating whether join order should be enforced. + /// </summary> + public bool EnforceJoinOrder + { + get { return _enforceJoinOrder; } + } + /** <inheritdoc /> */ public T ExecuteScalar<T>(QueryModel queryModel) { @@ -92,7 +132,12 @@ namespace Apache.Ignite.Linq.Impl Debug.WriteLine("\nFields Query: {0} | {1}", qryData.QueryText, string.Join(", ", qryData.Parameters.Select(x => x == null ? "null" : x.ToString()))); - var qry = new SqlFieldsQuery(qryData.QueryText, _local, qryData.Parameters.ToArray()); + var qry = new SqlFieldsQuery(qryData.QueryText, _local, qryData.Parameters.ToArray()) + { + EnableDistributedJoins = _enableDistributedJoins, + PageSize = _pageSize, + EnforceJoinOrder = _enforceJoinOrder + }; var selector = GetResultSelector<T>(queryModel.SelectClause.Selector); @@ -132,11 +177,21 @@ namespace Apache.Ignite.Linq.Impl // Check if user param order is already correct if (indices.SequenceEqual(Enumerable.Range(0, indices.Length))) - return args => _cache.QueryFields(new SqlFieldsQuery(qryText, _local, args), selector); + return args => _cache.QueryFields(new SqlFieldsQuery(qryText, _local, args) + { + EnableDistributedJoins = _enableDistributedJoins, + PageSize = _pageSize, + EnforceJoinOrder = _enforceJoinOrder + }, selector); // Return delegate with reorder return args => _cache.QueryFields(new SqlFieldsQuery(qryText, _local, - args.Select((x, i) => args[indices[i]]).ToArray()), selector); + args.Select((x, i) => args[indices[i]]).ToArray()) + { + EnableDistributedJoins = _enableDistributedJoins, + PageSize = _pageSize, + EnforceJoinOrder = _enforceJoinOrder + }, selector); } /** <inheritdoc /> */ http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs index 959cc4b..7ade159 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs @@ -32,10 +32,15 @@ namespace Apache.Ignite.Linq.Impl /// <param name="cache">The cache.</param> /// <param name="local">Local flag.</param> /// <param name="tableName">Name of the table.</param> - public CacheQueryable(ICache<TKey, TValue> cache, bool local, string tableName) + /// <param name="pageSize">Size of the page.</param> + /// <param name="enableDistributedJoins">Distributed joins flag.</param> + /// <param name="enforceJoinOrder">Enforce join order flag.</param> + public CacheQueryable(ICache<TKey, TValue> cache, bool local, string tableName, int pageSize, + bool enableDistributedJoins, + bool enforceJoinOrder) : base(new CacheFieldsQueryProvider(CacheQueryParser.Instance, - new CacheFieldsQueryExecutor((ICacheInternal) cache, local), - cache.Ignite, cache.GetConfiguration(), tableName, typeof(TValue))) + new CacheFieldsQueryExecutor((ICacheInternal) cache, local, pageSize, enableDistributedJoins, + enforceJoinOrder), cache.Ignite, cache.GetConfiguration(), tableName, typeof(TValue))) { // No-op. } http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs index d3115be..4b461bf 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs @@ -66,7 +66,12 @@ namespace Apache.Ignite.Linq.Impl var data = GetQueryData(); var executor = CacheQueryProvider.Executor; - return new SqlFieldsQuery(data.QueryText, executor.Local, data.Parameters.ToArray()); + return new SqlFieldsQuery(data.QueryText, executor.Local, data.Parameters.ToArray()) + { + EnableDistributedJoins = executor.EnableDistributedJoins, + EnforceJoinOrder = executor.EnforceJoinOrder, + PageSize = executor.PageSize + }; } /** <inheritdoc /> */