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 2016/08/23 11:24:46 UTC
[1/8] ignite git commit: IGNITE-3694: IGFS: Remove invalid assertion
in IgfsImpl.newBatch() method.
Repository: ignite
Updated Branches:
refs/heads/master c763e5144 -> 94b9713fa
IGNITE-3694: IGFS: Remove invalid assertion in IgfsImpl.newBatch() method.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/5b57fc04
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/5b57fc04
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/5b57fc04
Branch: refs/heads/master
Commit: 5b57fc04866677fbf1221a253fe28905dbfc2d7d
Parents: d399db9
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Mon Aug 22 17:16:45 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Mon Aug 22 17:16:45 2016 +0300
----------------------------------------------------------------------
.../org/apache/ignite/internal/processors/igfs/IgfsImpl.java | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b57fc04/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
index 6707acc..c704e00 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
@@ -344,12 +344,8 @@ public final class IgfsImpl implements IgfsEx {
if (prevBatch == null)
break;
- else {
- assert prevBatch.finishing() :
- "File lock should prevent stream creation on a not-closed-yet file.";
-
+ else
prevBatch.await();
- }
}
return batch;
[8/8] ignite git commit: Merge remote-tracking branch
'remotes/community/ignite-1.7.2' into UPSTREAM_master
Posted by pt...@apache.org.
Merge remote-tracking branch 'remotes/community/ignite-1.7.2' into UPSTREAM_master
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/94b9713f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/94b9713f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/94b9713f
Branch: refs/heads/master
Commit: 94b9713fa32c0d45cb75c18d82cfebf736d05158
Parents: c763e51 e4344fa
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Aug 23 14:24:09 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Aug 23 14:24:09 2016 +0300
----------------------------------------------------------------------
.../ignite/internal/MarshallerContextImpl.java | 9 +-
.../continuous/CacheContinuousQueryManager.java | 2 +-
.../internal/processors/igfs/IgfsImpl.java | 6 +-
.../MarshallerContextLockingSelfTest.java | 139 ++++++++++
...eDynamicCacheStartNoExchangeTimeoutTest.java | 2 +
.../processors/igfs/IgfsAbstractSelfTest.java | 4 +-
.../ignite/testsuites/IgniteBasicTestSuite.java | 3 +
.../Cache/Query/CacheLinqTest.cs | 196 +++++++++++++-
.../Apache.Ignite.Linq.csproj | 2 +-
.../dotnet/Apache.Ignite.Linq/CompiledQuery.cs | 1 +
.../dotnet/Apache.Ignite.Linq/CompiledQuery2.cs | 257 +++++++++++++++++++
.../Impl/CacheFieldsQueryExecutor.cs | 132 ++++++++--
.../Impl/CacheQueryExpressionVisitor.cs | 15 ++
.../Impl/CacheQueryModelVisitor.cs | 15 +-
.../Impl/CacheQueryableBase.cs | 22 ++
.../Apache.Ignite.Linq/Impl/ExpressionWalker.cs | 9 +
.../Apache.Ignite.Linq/Impl/ICacheQueryProxy.cs | 40 ---
.../Impl/ICacheQueryableInternal.cs | 14 +-
.../ignite/schema/generator/CodeGenerator.java | 16 +-
19 files changed, 795 insertions(+), 89 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/94b9713f/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
----------------------------------------------------------------------
diff --cc modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
index 52b6bfd,d56c29d..939e226
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
@@@ -32,8 -32,8 +32,9 @@@ import org.apache.ignite.internal.GridR
import org.apache.ignite.internal.GridSelfTest;
import org.apache.ignite.internal.GridStartStopSelfTest;
import org.apache.ignite.internal.GridStopWithCancelSelfTest;
+import org.apache.ignite.internal.IgniteLocalNodeMapBeforeStartTest;
import org.apache.ignite.internal.IgniteSlowClientDetectionSelfTest;
+ import org.apache.ignite.internal.MarshallerContextLockingSelfTest;
import org.apache.ignite.internal.processors.affinity.GridAffinityProcessorRendezvousSelfTest;
import org.apache.ignite.internal.processors.cache.GridProjectionForCachesOnDaemonNodeSelfTest;
import org.apache.ignite.internal.processors.cache.IgniteDaemonNodeMarshallerCacheTest;
[2/8] ignite git commit: IGNITE-3693: IGFS: Fixed sporadical failures
in IgfsLocalSecondaryFileSystemDualAsyncSelfTest.testFormat. This closes
#960.
Posted by pt...@apache.org.
IGNITE-3693: IGFS: Fixed sporadical failures in IgfsLocalSecondaryFileSystemDualAsyncSelfTest.testFormat. This closes #960.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/fa138321
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/fa138321
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/fa138321
Branch: refs/heads/master
Commit: fa13832132ad71cd3b3ad259784e2e7ec5366c28
Parents: 5b57fc0
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Mon Aug 22 17:37:14 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Mon Aug 22 17:37:14 2016 +0300
----------------------------------------------------------------------
.../ignite/internal/processors/igfs/IgfsAbstractSelfTest.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/fa138321/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java
index 236a589..86c2449 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java
@@ -1071,12 +1071,14 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
os.write(new byte[10 * 1024 * 1024]);
}
+ awaitFileClose(igfs, FILE);
+
if (dual)
checkExist(igfsSecondary, DIR, SUBDIR, FILE, DIR_NEW, SUBDIR_NEW, FILE_NEW);
checkExist(igfs, DIR, SUBDIR, FILE);
- assert igfs.info(FILE).length() == 10 * 1024 * 1024;
+ assertEquals(10 * 1024 * 1024, igfs.info(FILE).length());
assert dataCache.size(new CachePeekMode[] {CachePeekMode.ALL}) > 0;
[3/8] ignite git commit: IGNITE-3197 - OverlappingFileLockException
in marshaller context
Posted by pt...@apache.org.
IGNITE-3197 - OverlappingFileLockException in marshaller context
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a0c7c44f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a0c7c44f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a0c7c44f
Branch: refs/heads/master
Commit: a0c7c44fc864aa965fd4d14e5362a4f6356c01ab
Parents: fa13832
Author: AndreVel <an...@gmail.com>
Authored: Mon Aug 22 20:50:57 2016 -0700
Committer: Valentin Kulichenko <va...@gmail.com>
Committed: Mon Aug 22 20:50:57 2016 -0700
----------------------------------------------------------------------
.../ignite/internal/MarshallerContextImpl.java | 9 +-
.../continuous/CacheContinuousQueryManager.java | 2 +-
.../MarshallerContextLockingSelfTest.java | 139 +++++++++++++++++++
.../ignite/testsuites/IgniteBasicTestSuite.java | 3 +
4 files changed, 150 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/a0c7c44f/modules/core/src/main/java/org/apache/ignite/internal/MarshallerContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/MarshallerContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/MarshallerContextImpl.java
index 504ea6e..0420e18 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/MarshallerContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/MarshallerContextImpl.java
@@ -27,6 +27,7 @@ import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
@@ -258,7 +259,7 @@ public class MarshallerContextImpl extends MarshallerContextAdapter {
/**
*/
- private static class ContinuousQueryListener implements CacheEntryUpdatedListener<Integer, String> {
+ public static class ContinuousQueryListener implements CacheEntryUpdatedListener<Integer, String> {
/** */
private final IgniteLogger log;
@@ -269,7 +270,7 @@ public class MarshallerContextImpl extends MarshallerContextAdapter {
* @param log Logger.
* @param workDir Work directory.
*/
- private ContinuousQueryListener(IgniteLogger log, File workDir) {
+ public ContinuousQueryListener(IgniteLogger log, File workDir) {
this.log = log;
this.workDir = workDir;
}
@@ -306,6 +307,10 @@ public class MarshallerContextImpl extends MarshallerContextAdapter {
U.error(log, "Failed to write class name to file [id=" + evt.getKey() +
", clsName=" + evt.getValue() + ", file=" + file.getAbsolutePath() + ']', e);
}
+ catch(OverlappingFileLockException ignored) {
+ if (log.isDebugEnabled())
+ log.debug("File already locked (will ignore): " + file.getAbsolutePath());
+ }
catch (IgniteInterruptedCheckedException e) {
U.error(log, "Interrupted while waiting for acquiring file lock: " + file, e);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a0c7c44f/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
index a8e5a6b..2863f3d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
@@ -1204,7 +1204,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
/**
*
*/
- private static class CacheEntryEventImpl extends CacheQueryEntryEvent {
+ public static class CacheEntryEventImpl extends CacheQueryEntryEvent {
/** */
private static final long serialVersionUID = 0L;
http://git-wip-us.apache.org/repos/asf/ignite/blob/a0c7c44f/modules/core/src/test/java/org/apache/ignite/internal/MarshallerContextLockingSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/MarshallerContextLockingSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/MarshallerContextLockingSelfTest.java
new file mode 100644
index 0000000..e549336
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/MarshallerContextLockingSelfTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.EventType;
+import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryManager;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.GridTestClassLoader;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.logger.GridTestLog4jLogger;
+
+/**
+ * Test marshaller context.
+ */
+public class MarshallerContextLockingSelfTest extends GridCommonAbstractTest {
+ /** Inner logger. */
+ private InnerLogger innerLog = null;
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ innerLog = new InnerLogger();
+
+ log = innerLog;
+ }
+
+ /**
+ * Mumtithread test, used custom class loader
+ */
+ public void testMultithreadedUpdate() throws Exception {
+ multithreaded(new Callable<Object>() {
+ @Override public Object call() throws Exception {
+ GridTestClassLoader classLoader = new GridTestClassLoader(
+ InternalExecutor.class.getName(),
+ MarshallerContextImpl.class.getName(),
+ MarshallerContextImpl.ContinuousQueryListener.class.getName()
+ );
+
+ Thread.currentThread().setContextClassLoader(classLoader);
+
+ Class clazz = classLoader.loadClass(InternalExecutor.class.getName());
+
+ Object internelExecutor = clazz.newInstance();
+
+ clazz.getMethod("executeTest", GridTestLog4jLogger.class).invoke(internelExecutor, log);
+
+ return null;
+ }
+ }, 4);
+
+ assertTrue(InternalExecutor.counter.get() == 0);
+
+ assertTrue(innerLog.contains("File already locked"));
+
+ assertTrue(!innerLog.contains("Exception"));
+ }
+
+ /**
+ * Internal test executor
+ */
+ public static class InternalExecutor {
+ /** Counter. */
+ public static AtomicInteger counter = new AtomicInteger();
+
+ /**
+ * Executes onUpdated
+ */
+ public void executeTest(GridTestLog4jLogger log) throws Exception {
+ counter.incrementAndGet();
+
+ File workDir = U.resolveWorkDirectory("marshaller", false);
+
+ final MarshallerContextImpl.ContinuousQueryListener queryListener = new MarshallerContextImpl.ContinuousQueryListener(log, workDir);
+
+ final ArrayList evts = new ArrayList<CacheEntryEvent<Integer, String>>();
+
+ IgniteCacheProxy cache = new IgniteCacheProxy();
+
+ evts.add(new CacheContinuousQueryManager.CacheEntryEventImpl(cache, EventType.CREATED, 1, String.class.getName()));
+
+ for (int i = 0; i < 100; i++)
+ queryListener.onUpdated(evts);
+ }
+ }
+
+ /**
+ * Internal logger
+ */
+ public static class InnerLogger extends GridTestLog4jLogger {
+ /** */
+ private Collection<String> logs = new ConcurrentLinkedDeque<>();
+
+ /**
+ * Returns true if and only if this string contains the specified
+ * sequence of char values.
+ *
+ * @param str String.
+ */
+ public boolean contains(String str) {
+ for (String text : logs)
+ if (text != null && text.contains(str))
+ return true;
+
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void debug(String msg) {
+ logs.add(msg);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isDebugEnabled() {
+ return true;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a0c7c44f/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
index 6611500..d56c29d 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
@@ -33,6 +33,7 @@ import org.apache.ignite.internal.GridSelfTest;
import org.apache.ignite.internal.GridStartStopSelfTest;
import org.apache.ignite.internal.GridStopWithCancelSelfTest;
import org.apache.ignite.internal.IgniteSlowClientDetectionSelfTest;
+import org.apache.ignite.internal.MarshallerContextLockingSelfTest;
import org.apache.ignite.internal.processors.affinity.GridAffinityProcessorRendezvousSelfTest;
import org.apache.ignite.internal.processors.cache.GridProjectionForCachesOnDaemonNodeSelfTest;
import org.apache.ignite.internal.processors.cache.IgniteDaemonNodeMarshallerCacheTest;
@@ -136,6 +137,8 @@ public class IgniteBasicTestSuite extends TestSuite {
suite.addTestSuite(ConfigVariationsTestSuiteBuilderTest.class);
suite.addTestSuite(NotStringSystemPropertyTest.class);
+ suite.addTestSuite(MarshallerContextLockingSelfTest.class);
+
return suite;
}
}
[4/8] ignite git commit: Fix for
IgniteDynamicCacheStartNoExchangeTimeoutTest.
Posted by pt...@apache.org.
Fix for IgniteDynamicCacheStartNoExchangeTimeoutTest.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/eea42827
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/eea42827
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/eea42827
Branch: refs/heads/master
Commit: eea42827738301168d66562a05d3360150e6fb89
Parents: a0c7c44
Author: sboikov <sb...@gridgain.com>
Authored: Tue Aug 23 10:47:15 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Aug 23 10:47:15 2016 +0300
----------------------------------------------------------------------
.../cache/IgniteDynamicCacheStartNoExchangeTimeoutTest.java | 2 ++
1 file changed, 2 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/eea42827/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicCacheStartNoExchangeTimeoutTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicCacheStartNoExchangeTimeoutTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicCacheStartNoExchangeTimeoutTest.java
index ac80d69..263e9ca 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicCacheStartNoExchangeTimeoutTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicCacheStartNoExchangeTimeoutTest.java
@@ -84,6 +84,8 @@ public class IgniteDynamicCacheStartNoExchangeTimeoutTest extends GridCommonAbst
super.beforeTest();
startGrids(NODES);
+
+ awaitPartitionMapExchange();
}
/**
[6/8] ignite git commit: IGNITE-3325 .NET: Improve CompiledQuery in
LINQ provider
Posted by pt...@apache.org.
IGNITE-3325 .NET: Improve CompiledQuery in LINQ provider
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/d6033712
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/d6033712
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/d6033712
Branch: refs/heads/master
Commit: d6033712425cd0157fa640a7d46ec6579fd7e74b
Parents: f925873
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Aug 23 14:10:55 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Aug 23 14:10:55 2016 +0300
----------------------------------------------------------------------
.../Cache/Query/CacheLinqTest.cs | 196 +++++++++++++-
.../Apache.Ignite.Linq.csproj | 2 +-
.../dotnet/Apache.Ignite.Linq/CompiledQuery.cs | 1 +
.../dotnet/Apache.Ignite.Linq/CompiledQuery2.cs | 257 +++++++++++++++++++
.../Impl/CacheFieldsQueryExecutor.cs | 116 ++++++++-
.../Impl/CacheQueryExpressionVisitor.cs | 15 ++
.../Impl/CacheQueryModelVisitor.cs | 15 +-
.../Impl/CacheQueryableBase.cs | 22 ++
.../Apache.Ignite.Linq/Impl/ExpressionWalker.cs | 9 +
.../Apache.Ignite.Linq/Impl/ICacheQueryProxy.cs | 40 ---
.../Impl/ICacheQueryableInternal.cs | 14 +-
11 files changed, 622 insertions(+), 65 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/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 a47f3f0..a8cc8fd 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
@@ -28,6 +28,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
{
using System;
using System.Collections;
+ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
@@ -506,9 +507,11 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
public void TestInvalidJoin()
{
// Join on non-IQueryable
- Assert.Throws<NotSupportedException>(() =>
+ var ex = Assert.Throws<NotSupportedException>(() =>
// ReSharper disable once ReturnValueOfPureMethodIsNotUsed
GetPersonCache().AsCacheQueryable().Join(GetOrgCache(), p => p.Key, o => o.Key, (p, o) => p).ToList());
+
+ Assert.IsTrue(ex.Message.StartsWith("Unexpected query source"));
}
/// <summary>
@@ -836,11 +839,187 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
}
/// <summary>
- /// Tests the compiled query.
+ /// Tests the compiled query with various constructs.
/// </summary>
[Test]
public void TestCompiledQuery()
{
+ var persons = GetPersonCache().AsCacheQueryable();
+ var roles = GetRoleCache().AsCacheQueryable();
+
+ // Embedded args
+ var qry0 = CompiledQuery2.Compile(() => persons.Where(x => x.Key < 3 && x.Value.Name.Contains("son")));
+ Assert.AreEqual(3, qry0().Count());
+
+ // Lambda args
+ var qry1 = CompiledQuery2.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 = CompiledQuery2.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 = CompiledQuery2.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 = CompiledQuery2.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 = CompiledQuery2.Compile(
+ (int a, int b, string sep) =>
+ roles
+ .Where(x => x.Key.Bar > a)
+ .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 = CompiledQuery2.Compile(() => roles.Select(x => -x.Key.Foo).Union(persons.Select(x => x.Key)));
+
+ Assert.AreEqual(RoleCount + PersonCount, qry5().Count());
+
+ // Projection
+ var qry6 = CompiledQuery2.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, CompiledQuery2.Compile(() => cache.Where(x => x.Key < 5))().GetAll().Count);
+
+ // 0 arg
+ var qry0 = CompiledQuery2.Compile(() => cache.Select(x => x.Value.Name));
+ Assert.AreEqual(PersonCount, qry0().ToArray().Length);
+
+ // 1 arg
+ var qry1 = CompiledQuery2.Compile((int k) => cache.Where(x => x.Key < k));
+ Assert.AreEqual(3, qry1(3).ToArray().Length);
+
+ // 1 arg twice
+ var qry1T = CompiledQuery2.Compile((int k) => cache.Where(x => x.Key < k && x.Value.Age < k));
+ Assert.AreEqual(3, qry1T(3).ToArray().Length);
+
+ // 2 arg
+ var qry2 =
+ CompiledQuery2.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 =
+ CompiledQuery2.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 = CompiledQuery2.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 = CompiledQuery2.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 = CompiledQuery2.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 = CompiledQuery2.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 = CompiledQuery2.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 = CompiledQuery2.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 = CompiledQuery2.Compile(qry);
+
+ Assert.AreEqual(5, compiled(5).Count());
+ Assert.AreEqual(6, compiled(6).Count());
+
+ // Select
+ var compiledSelect = CompiledQuery2.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 = CompiledQuery2.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 = CompiledQuery2.Compile(qry2);
+
+ Assert.AreEqual(17, compiled2(18, 16, "ers", 13, 17).Single().Key);
+ }
+
+#pragma warning disable 618 // obsolete class
+ /// <summary>
+ /// Tests the old, deprecated compiled query.
+ /// </summary>
+ [Test]
+ public void TestCompiledQueryOld()
+ {
var cache = GetPersonCache().AsCacheQueryable();
// const args are not allowed
@@ -865,7 +1044,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
Assert.AreEqual(5, qry2R(" Pe", 5).ToArray().Length);
// 3 arg
- var qry3 = CompiledQuery.Compile((int i, string s, double d) =>
+ 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);
@@ -873,28 +1052,29 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
var keys = cache.Select(x => x.Key);
var qry4 = CompiledQuery.Compile((int a, int b, int c, int d) =>
keys.Where(k => k > a && k > b && k > c && k < d));
- Assert.AreEqual(new[] {3, 4}, qry4(0, 1, 2, 5).ToArray());
+ 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) =>
keys.Where(k => k > a && k > b && k > c && k < d && k < e));
- Assert.AreEqual(new[] {3, 4}, qry5(0, 1, 2, 5, 6).ToArray());
+ 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) =>
keys.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());
+ 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) =>
keys.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());
+ 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) =>
keys.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());
+ Assert.AreEqual(new[] { 3, 4 }, qry8(0, 1, 2, 5, 6, 7, 8, 9).ToArray());
}
+#pragma warning restore 618
/// <summary>
/// Tests the cache of primitive types.
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj b/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
index d1dad16..d00ebea 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
@@ -52,6 +52,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CacheExtensions.cs" />
+ <Compile Include="CompiledQuery2.cs" />
<Compile Include="CompiledQuery.cs" />
<Compile Include="ICacheQueryable.cs" />
<Compile Include="Impl\AliasDictionary.cs" />
@@ -64,7 +65,6 @@
<Compile Include="Impl\CacheQueryModelVisitor.cs" />
<Compile Include="Impl\CacheQueryParser.cs" />
<Compile Include="Impl\ICacheQueryableInternal.cs" />
- <Compile Include="Impl\ICacheQueryProxy.cs" />
<Compile Include="Impl\MethodVisitor.cs" />
<Compile Include="Impl\QueryData.cs" />
<Compile Include="Impl\SqlTypes.cs" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/modules/platforms/dotnet/Apache.Ignite.Linq/CompiledQuery.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/CompiledQuery.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/CompiledQuery.cs
index 9e6c6c7..817c423 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/CompiledQuery.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/CompiledQuery.cs
@@ -28,6 +28,7 @@ namespace Apache.Ignite.Linq
/// <summary>
/// Represents a compiled cache query.
/// </summary>
+ [Obsolete("Use CompiledQuery2 class.")]
public static class CompiledQuery
{
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/modules/platforms/dotnet/Apache.Ignite.Linq/CompiledQuery2.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/CompiledQuery2.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/CompiledQuery2.cs
new file mode 100644
index 0000000..85aafd9
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/CompiledQuery2.cs
@@ -0,0 +1,257 @@
+\ufeff/*
+ * 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.Linq
+{
+ using System;
+ using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Linq;
+ using System.Linq.Expressions;
+ using Apache.Ignite.Core.Cache.Query;
+ using Apache.Ignite.Core.Impl.Common;
+ using Apache.Ignite.Linq.Impl;
+
+ /// <summary>
+ /// Represents a compiled cache query.
+ /// </summary>
+ public static class CompiledQuery2
+ {
+ /// <summary>
+ /// Delegate for compiled query with arbitrary number of arguments.
+ /// </summary>
+ /// <typeparam name="T">Result type.</typeparam>
+ /// <param name="args">The arguments.</param>
+ /// <returns>Query cursor.</returns>
+ public delegate IQueryCursor<T> CompiledQueryDelegate<T>(params object[] args);
+
+ /// <summary>
+ /// Creates a new delegate that represents the compiled cache query.
+ /// </summary>
+ /// <param name="query">The query to compile.</param>
+ /// <returns>Delegate that represents the compiled cache query.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
+ Justification = "Invalid warning, validation is present.")]
+ public static Func<IQueryCursor<T>> Compile<T>(Expression<Func<IQueryable<T>>> query)
+ {
+ IgniteArgumentCheck.NotNull(query, "query");
+
+ var compiledQuery = GetCompiledQuery<T>(query, query.Compile());
+
+ return () => compiledQuery(new object[0]);
+ }
+
+ /// <summary>
+ /// Creates a new delegate that represents the compiled cache query with any number of arguments.
+ /// <para />
+ /// This method differs from other Compile methods in that it takes in <see cref="ICacheQueryable"/> directly,
+ /// and returns a delegate that takes an array of parameters.
+ /// It is up to the user to provide query arguments in correct order.
+ /// <para />
+ /// This method also imposes no restrictions on where the query comes from (in contrary to other methods).
+ /// </summary>
+ /// <param name="query">The query to compile.</param>
+ /// <returns>Delegate that represents the compiled cache query.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
+ Justification = "Invalid warning, validation is present.")]
+ public static CompiledQueryDelegate<T> Compile<T>(IQueryable<T> query)
+ {
+ IgniteArgumentCheck.NotNull(query, "query");
+
+ var cacheQueryable = query as ICacheQueryableInternal;
+
+ if (cacheQueryable == null)
+ throw GetInvalidQueryException(query);
+
+ var compileQuery = cacheQueryable.CompileQuery<T>();
+
+ // Special delegate is required to allow params[].
+ return args => compileQuery(args);
+ }
+
+ /// <summary>
+ /// Creates a new delegate that represents the compiled cache query.
+ /// </summary>
+ /// <param name="query">The query to compile.</param>
+ /// <returns>Delegate that represents the compiled cache query.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
+ Justification = "Invalid warning, validation is present.")]
+ public static Func<T1, IQueryCursor<T>> Compile<T, T1>(Expression<Func<T1, IQueryable<T>>> query)
+ {
+ IgniteArgumentCheck.NotNull(query, "query");
+
+ var compiledQuery = GetCompiledQuery<T>(query, query.Compile());
+
+ return x => compiledQuery(new object[] {x});
+ }
+
+ /// <summary>
+ /// Creates a new delegate that represents the compiled cache query.
+ /// </summary>
+ /// <param name="query">The query to compile.</param>
+ /// <returns>Delegate that represents the compiled cache query.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
+ Justification = "Invalid warning, validation is present.")]
+ public static Func<T1, T2, IQueryCursor<T>> Compile<T, T1, T2>(Expression<Func<T1, T2,
+ IQueryable<T>>> query)
+ {
+ IgniteArgumentCheck.NotNull(query, "query");
+
+ var compiledQuery = GetCompiledQuery<T>(query, query.Compile());
+
+ return (x, y) => compiledQuery(new object[] {x, y});
+ }
+
+ /// <summary>
+ /// Creates a new delegate that represents the compiled cache query.
+ /// </summary>
+ /// <param name="query">The query to compile.</param>
+ /// <returns>Delegate that represents the compiled cache query.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
+ Justification = "Invalid warning, validation is present.")]
+ public static Func<T1, T2, T3, IQueryCursor<T>> Compile<T, T1, T2, T3>(Expression<Func<T1, T2, T3,
+ IQueryable<T>>> query)
+ {
+ IgniteArgumentCheck.NotNull(query, "query");
+
+ var compiledQuery = GetCompiledQuery<T>(query, query.Compile());
+
+ return (x, y, z) => compiledQuery(new object[] {x, y, z});
+ }
+
+ /// <summary>
+ /// Creates a new delegate that represents the compiled cache query.
+ /// </summary>
+ /// <param name="query">The query to compile.</param>
+ /// <returns>Delegate that represents the compiled cache query.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
+ Justification = "Invalid warning, validation is present.")]
+ public static Func<T1, T2, T3, T4, IQueryCursor<T>> Compile<T, T1, T2, T3, T4>(Expression<Func<T1, T2, T3, T4,
+ IQueryable<T>>> query)
+ {
+ IgniteArgumentCheck.NotNull(query, "query");
+
+ var compiledQuery = GetCompiledQuery<T>(query, query.Compile());
+
+ return (x, y, z, a) => compiledQuery(new object[] {x, y, z, a});
+ }
+
+ /// <summary>
+ /// Creates a new delegate that represents the compiled cache query.
+ /// </summary>
+ /// <param name="query">The query to compile.</param>
+ /// <returns>Delegate that represents the compiled cache query.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
+ Justification = "Invalid warning, validation is present.")]
+ public static Func<T1, T2, T3, T4, T5, IQueryCursor<T>> Compile<T, T1, T2, T3, T4, T5>(
+ Expression<Func<T1, T2, T3, T4, T5, IQueryable<T>>> query)
+ {
+ IgniteArgumentCheck.NotNull(query, "query");
+
+ var compiledQuery = GetCompiledQuery<T>(query, query.Compile());
+
+ return (x, y, z, a, b) => compiledQuery(new object[] {x, y, z, a, b});
+ }
+
+ /// <summary>
+ /// Creates a new delegate that represents the compiled cache query.
+ /// </summary>
+ /// <param name="query">The query to compile.</param>
+ /// <returns>Delegate that represents the compiled cache query.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
+ Justification = "Invalid warning, validation is present.")]
+ public static Func<T1, T2, T3, T4, T5, T6, IQueryCursor<T>> Compile<T, T1, T2, T3, T4, T5, T6>(
+ Expression<Func<T1, T2, T3, T4, T5, T6, IQueryable<T>>> query)
+ {
+ IgniteArgumentCheck.NotNull(query, "query");
+
+ var compiledQuery = GetCompiledQuery<T>(query, query.Compile());
+
+ return (x, y, z, a, b, c) => compiledQuery(new object[] {x, y, z, a, b, c});
+ }
+
+ /// <summary>
+ /// Creates a new delegate that represents the compiled cache query.
+ /// </summary>
+ /// <param name="query">The query to compile.</param>
+ /// <returns>Delegate that represents the compiled cache query.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
+ Justification = "Invalid warning, validation is present.")]
+ public static Func<T1, T2, T3, T4, T5, T6, T7, IQueryCursor<T>> Compile<T, T1, T2, T3, T4, T5, T6, T7>(
+ Expression<Func<T1, T2, T3, T4, T5, T6, T7, IQueryable<T>>> query)
+ {
+ IgniteArgumentCheck.NotNull(query, "query");
+
+ var compiledQuery = GetCompiledQuery<T>(query, query.Compile());
+
+ return (x, y, z, a, b, c, d) => compiledQuery(new object[] {x, y, z, a, b, c, d});
+ }
+
+ /// <summary>
+ /// Creates a new delegate that represents the compiled cache query.
+ /// </summary>
+ /// <param name="query">The query to compile.</param>
+ /// <returns>Delegate that represents the compiled cache query.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
+ Justification = "Invalid warning, validation is present.")]
+ public static Func<T1, T2, T3, T4, T5, T6, T7, T8, IQueryCursor<T>> Compile<T, T1, T2, T3, T4, T5, T6, T7, T8>(
+ Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, IQueryable<T>>> query)
+ {
+ IgniteArgumentCheck.NotNull(query, "query");
+
+ var compiledQuery = GetCompiledQuery<T>(query, query.Compile());
+
+ return (x, y, z, a, b, c, d, e) => compiledQuery(new object[] {x, y, z, a, b, c, d, e});
+ }
+
+ /// <summary>
+ /// Gets the compiled query.
+ /// </summary>
+ private static Func<object[], IQueryCursor<T>> GetCompiledQuery<T>(LambdaExpression expression,
+ Delegate queryCaller)
+ {
+ Debug.Assert(expression != null);
+ Debug.Assert(queryCaller != null);
+
+ // Get default parameter values.
+ var paramValues = expression.Parameters
+ .Select(x => x.Type)
+ .Select(x => x.IsValueType ? Activator.CreateInstance(x) : null)
+ .ToArray();
+
+ // Invoke the delegate to obtain the cacheQueryable.
+ var queryable = queryCaller.DynamicInvoke(paramValues);
+
+ var cacheQueryable = queryable as ICacheQueryableInternal;
+
+ if (cacheQueryable == null)
+ throw GetInvalidQueryException(queryable);
+
+ return cacheQueryable.CompileQuery<T>(expression);
+ }
+
+ /// <summary>
+ /// Gets the invalid query exception.
+ /// </summary>
+ private static ArgumentException GetInvalidQueryException(object queryable)
+ {
+ return new ArgumentException(
+ string.Format("{0} can only compile cache queries produced by AsCacheQueryable method. " +
+ "Provided query is not valid: '{1}'", typeof(CompiledQuery2).FullName, queryable));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/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..b4c3292 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
@@ -92,7 +92,7 @@ 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 = GetFieldsQuery(qryData.QueryText, qryData.Parameters.ToArray());
var selector = GetResultSelector<T>(queryModel.SelectClause.Selector);
@@ -100,7 +100,7 @@ namespace Apache.Ignite.Linq.Impl
}
/// <summary>
- /// Compiles the query.
+ /// Compiles the query (old method, does not support some scenarios).
/// </summary>
public Func<object[], IQueryCursor<T>> CompileQuery<T>(QueryModel queryModel, Delegate queryCaller)
{
@@ -132,12 +132,120 @@ 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(GetFieldsQuery(qryText, args), selector);
// Return delegate with reorder
- return args => _cache.QueryFields(new SqlFieldsQuery(qryText, _local,
+ return args => _cache.QueryFields(GetFieldsQuery(qryText,
args.Select((x, i) => args[indices[i]]).ToArray()), selector);
}
+ /// <summary>
+ /// Compiles the query without regard to number or order of arguments.
+ /// </summary>
+ public Func<object[], IQueryCursor<T>> CompileQuery<T>(QueryModel queryModel)
+ {
+ Debug.Assert(queryModel != null);
+
+ var qryText = GetQueryData(queryModel).QueryText;
+ var selector = GetResultSelector<T>(queryModel.SelectClause.Selector);
+
+ return args => _cache.QueryFields(GetFieldsQuery(qryText, args), selector);
+ }
+
+ /// <summary>
+ /// Compiles the query.
+ /// </summary>
+ /// <typeparam name="T">Result type.</typeparam>
+ /// <param name="queryModel">The query model.</param>
+ /// <param name="queryLambdaModel">The query model generated from lambda body.</param>
+ /// <param name="queryLambda">The query lambda.</param>
+ /// <returns>Compiled query func.</returns>
+ public Func<object[], IQueryCursor<T>> CompileQuery<T>(QueryModel queryModel, QueryModel queryLambdaModel,
+ LambdaExpression queryLambda)
+ {
+ Debug.Assert(queryModel != null);
+
+ // Get model from lambda to map arguments properly.
+ var qryData = GetQueryData(queryLambdaModel);
+
+ var qryText = GetQueryData(queryModel).QueryText;
+ var qryTextLambda = qryData.QueryText;
+
+ if (qryText != qryTextLambda)
+ {
+ Debug.WriteLine(qryText);
+ Debug.WriteLine(qryTextLambda);
+
+ throw new InvalidOperationException("Error compiling query: entire LINQ expression should be " +
+ "specified within lambda passed to Compile method. " +
+ "Part of the query can't be outside the Compile method call.");
+ }
+
+ var selector = GetResultSelector<T>(queryModel.SelectClause.Selector);
+
+ var qryParams = qryData.Parameters.ToArray();
+
+ // Compiled query is a delegate with query parameters
+ // Delegate parameters order and query parameters order may differ
+
+ // Simple case: lambda with no parameters. Only embedded parameters are used.
+ if (!queryLambda.Parameters.Any())
+ {
+ return argsUnused => _cache.QueryFields(GetFieldsQuery(qryText, qryParams), selector);
+ }
+
+ // These are in order of usage in query
+ var qryOrderArgs = qryParams.OfType<ParameterExpression>().Select(x => x.Name).ToArray();
+
+ // These are in order they come from user
+ var userOrderArgs = queryLambda.Parameters.Select(x => x.Name).ToList();
+
+ // Simple case: all query args directly map to the lambda args in the same order
+ if (qryOrderArgs.Length == qryParams.Length
+ && qryOrderArgs.SequenceEqual(userOrderArgs))
+ {
+ return args => _cache.QueryFields(GetFieldsQuery(qryText, args), selector);
+ }
+
+ // General case: embedded args and lambda args are mixed; same args can be used multiple times.
+ // Produce a mapping that defines where query arguments come from.
+ var mapping = qryParams.Select(x =>
+ {
+ var pe = x as ParameterExpression;
+
+ if (pe != null)
+ return userOrderArgs.IndexOf(pe.Name);
+
+ return -1;
+ }).ToArray();
+
+ return args => _cache.QueryFields(
+ GetFieldsQuery(qryText, MapQueryArgs(args, qryParams, mapping)), selector);
+ }
+
+ /// <summary>
+ /// Maps the query arguments.
+ /// </summary>
+ private static object[] MapQueryArgs(object[] userArgs, object[] embeddedArgs, int[] mapping)
+ {
+ var mappedArgs = new object[embeddedArgs.Length];
+
+ for (var i = 0; i < mappedArgs.Length; i++)
+ {
+ var map = mapping[i];
+
+ mappedArgs[i] = map < 0 ? embeddedArgs[i] : userArgs[map];
+ }
+
+ return mappedArgs;
+ }
+
+ /// <summary>
+ /// Gets the fields query.
+ /// </summary>
+ private SqlFieldsQuery GetFieldsQuery(string text, object[] args)
+ {
+ return new SqlFieldsQuery(text, _local, args);
+ }
/** <inheritdoc /> */
public static QueryData GetQueryData(QueryModel queryModel)
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
index eaca07a..2c48554 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
@@ -242,6 +242,21 @@ namespace Apache.Ignite.Linq.Impl
}
/** <inheritdoc /> */
+ public override Expression Visit(Expression expression)
+ {
+ var paramExpr = expression as ParameterExpression;
+
+ if (paramExpr != null)
+ {
+ // This happens only with compiled queries, where parameters come from enclosing lambda.
+ AppendParameter(paramExpr);
+ return expression;
+ }
+
+ return base.Visit(expression);
+ }
+
+ /** <inheritdoc /> */
protected override Expression VisitQuerySourceReference(QuerySourceReferenceExpression expression)
{
// Count, sum, max, min expect a single field or *
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
index 1888414..51297ee 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
@@ -273,6 +273,10 @@ namespace Apache.Ignite.Linq.Impl
// Workaround for unlimited offset (IGNITE-2602)
// H2 allows NULL & -1 for unlimited, but Ignite indexing does not
// Maximum limit that works is (int.MaxValue - offset)
+
+ if (offset.Count is ParameterExpression)
+ throw new NotSupportedException("Skip() without Take() is not supported in compiled queries.");
+
var offsetInt = (int) ((ConstantExpression) offset.Count).Value;
_builder.Append((int.MaxValue - offsetInt).ToString(CultureInfo.InvariantCulture));
}
@@ -424,17 +428,6 @@ namespace Apache.Ignite.Linq.Impl
}
else
{
- var innerExpr = joinClause.InnerSequence as ConstantExpression;
-
- if (innerExpr == null)
- throw new NotSupportedException("Unexpected JOIN inner sequence (subqueries are not supported): " +
- joinClause.InnerSequence);
-
- if (!(innerExpr.Value is ICacheQueryable))
- throw new NotSupportedException("Unexpected JOIN inner sequence " +
- "(only results of cache.ToQueryable() are supported): " +
- innerExpr.Value);
-
var queryable = ExpressionWalker.GetCacheQueryable(joinClause);
var tableName = ExpressionWalker.GetTableNameWithSchema(queryable);
_builder.AppendFormat("inner join {0} as {1} on (", tableName, _aliases.GetTableAlias(tableName));
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/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..ee0239c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs
@@ -89,6 +89,28 @@ namespace Apache.Ignite.Linq.Impl
return executor.CompileQuery<TQ>(GetQueryModel(), queryCaller);
}
+ /** <inheritdoc /> */
+ public Func<object[], IQueryCursor<TQ>> CompileQuery<TQ>(LambdaExpression queryExpression)
+ {
+ var executor = CacheQueryProvider.Executor;
+
+ // Generate two models: from current expression, and from provided lambda.
+ // Lambda expression provides a way to identify argument mapping.
+ // Comparing two models allows to check whether whole query is within lambda.
+ var model = GetQueryModel();
+ var lambdaModel = CacheQueryProvider.GenerateQueryModel(queryExpression.Body);
+
+ return executor.CompileQuery<TQ>(model, lambdaModel, queryExpression);
+ }
+
+ /** <inheritdoc /> */
+ public Func<object[], IQueryCursor<TQ>> CompileQuery<TQ>()
+ {
+ var executor = CacheQueryProvider.Executor;
+
+ return executor.CompileQuery<TQ>(GetQueryModel());
+ }
+
/// <summary>
/// Gets the cache query provider.
/// </summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
index 96371cc..f529da7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
@@ -118,6 +118,11 @@ namespace Apache.Ignite.Linq.Impl
/// </summary>
public static T EvaluateExpression<T>(Expression expr)
{
+ var constExpr = expr as ConstantExpression;
+
+ if (constExpr != null)
+ return (T)constExpr.Value;
+
var memberExpr = expr as MemberExpression;
if (memberExpr != null)
@@ -137,6 +142,10 @@ namespace Apache.Ignite.Linq.Impl
}
}
+ // Case for compiled queries: return unchanged.
+ if (expr is ParameterExpression)
+ return (T) (object) expr;
+
throw new NotSupportedException("Expression not supported: " + expr);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ICacheQueryProxy.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ICacheQueryProxy.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ICacheQueryProxy.cs
deleted file mode 100644
index b00937c..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ICacheQueryProxy.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-\ufeff/*
- * 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.Linq.Impl
-{
- using System;
- using Apache.Ignite.Core.Binary;
- using Apache.Ignite.Core.Cache.Query;
-
- /// <summary>
- /// Cache proxy interface that allows query execution without key/value generic arguments.
- /// </summary>
- internal interface ICacheQueryProxy
- {
- /// <summary>
- /// Queries separate entry fields.
- /// </summary>
- /// <typeparam name="T">Type of the result.</typeparam>
- /// <param name="qry">SQL fields query.</param>
- /// <param name="readerFunc">Reader function, takes raw reader and field count, returns typed result.</param>
- /// <returns>
- /// Cursor.
- /// </returns>
- IQueryCursor<T> QueryFields<T>(SqlFieldsQuery qry, Func<IBinaryRawReader, int, T> readerFunc);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/d6033712/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ICacheQueryableInternal.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ICacheQueryableInternal.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ICacheQueryableInternal.cs
index 3e252c5..ffc81b4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ICacheQueryableInternal.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ICacheQueryableInternal.cs
@@ -18,6 +18,7 @@
namespace Apache.Ignite.Linq.Impl
{
using System;
+ using System.Linq.Expressions;
using Apache.Ignite.Core.Cache.Configuration;
using Apache.Ignite.Core.Cache.Query;
using Remotion.Linq;
@@ -46,9 +47,20 @@ namespace Apache.Ignite.Linq.Impl
QueryModel GetQueryModel();
/// <summary>
- /// Compiles the query.
+ /// Compiles the query (the old way).
/// </summary>
/// <param name="queryCaller">Caller expression to examine argument order.</param>
Func<object[], IQueryCursor<T>> CompileQuery<T>(Delegate queryCaller);
+
+ /// <summary>
+ /// Compiles the query.
+ /// </summary>
+ /// <param name="queryExpression">The query expression.</param>
+ Func<object[], IQueryCursor<T>> CompileQuery<T>(LambdaExpression queryExpression);
+
+ /// <summary>
+ /// Compiles the query without regard to the order and number of arguments.
+ /// </summary>
+ Func<object[], IQueryCursor<T>> CompileQuery<T>();
}
}
\ No newline at end of file
[5/8] ignite git commit: Fixed tests.
Posted by pt...@apache.org.
Fixed tests.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f9258736
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f9258736
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f9258736
Branch: refs/heads/master
Commit: f9258736c5cfa157e138d879aa0dbacc5a7cb4b2
Parents: eea4282
Author: Alexey Kuznetsov <ak...@apache.org>
Authored: Tue Aug 23 14:59:45 2016 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Tue Aug 23 14:59:45 2016 +0700
----------------------------------------------------------------------
.../ignite/schema/generator/CodeGenerator.java | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/f9258736/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
index 59dfdc4..5cdc6c6 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
@@ -256,6 +256,17 @@ public class CodeGenerator {
}
/**
+ * Ensure that all folders for packages exist.
+ *
+ * @param pkg Packages.
+ * @throws IOException If failed to ensure.
+ */
+ private static void ensurePackages(File pkg) throws IOException {
+ if (!pkg.exists() && !pkg.mkdirs())
+ throw new IOException("Failed to create folders for package: " + pkg);
+ }
+
+ /**
* Generate java class code.
*
* @param pojo POJO descriptor.
@@ -275,8 +286,7 @@ public class CodeGenerator {
checkValidJavaIdentifier(type, false, "Type", type);
- if (!pkgFolder.exists() && !pkgFolder.mkdirs())
- throw new IOException("Failed to create folders for package: " + pkg);
+ ensurePackages(pkgFolder);
File out = new File(pkgFolder, type + ".java");
@@ -567,6 +577,8 @@ public class CodeGenerator {
boolean generateAliases, String outFolder, ConfirmCallable askOverwrite) throws IOException {
File pkgFolder = new File(outFolder, pkg.replace('.', File.separatorChar));
+ ensurePackages(pkgFolder);
+
File cacheCfg = new File(pkgFolder, "CacheConfig.java");
if (cacheCfg.exists()) {
[7/8] ignite git commit: Merge remote-tracking branch
'remotes/community/ignite-1.6.6' into ignite-1.7.2
Posted by pt...@apache.org.
Merge remote-tracking branch 'remotes/community/ignite-1.6.6' into ignite-1.7.2
# Conflicts:
# modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e4344fa8
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e4344fa8
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e4344fa8
Branch: refs/heads/master
Commit: e4344fa811c78d78d3a829ba2cf2c916a05e0ef7
Parents: 8d5b6ba d603371
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Aug 23 14:15:32 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Aug 23 14:15:32 2016 +0300
----------------------------------------------------------------------
.../ignite/internal/MarshallerContextImpl.java | 9 +-
.../continuous/CacheContinuousQueryManager.java | 2 +-
.../internal/processors/igfs/IgfsImpl.java | 6 +-
.../MarshallerContextLockingSelfTest.java | 139 ++++++++++
...eDynamicCacheStartNoExchangeTimeoutTest.java | 2 +
.../processors/igfs/IgfsAbstractSelfTest.java | 4 +-
.../ignite/testsuites/IgniteBasicTestSuite.java | 3 +
.../Cache/Query/CacheLinqTest.cs | 196 +++++++++++++-
.../Apache.Ignite.Linq.csproj | 2 +-
.../dotnet/Apache.Ignite.Linq/CompiledQuery.cs | 1 +
.../dotnet/Apache.Ignite.Linq/CompiledQuery2.cs | 257 +++++++++++++++++++
.../Impl/CacheFieldsQueryExecutor.cs | 132 ++++++++--
.../Impl/CacheQueryExpressionVisitor.cs | 15 ++
.../Impl/CacheQueryModelVisitor.cs | 15 +-
.../Impl/CacheQueryableBase.cs | 22 ++
.../Apache.Ignite.Linq/Impl/ExpressionWalker.cs | 9 +
.../Apache.Ignite.Linq/Impl/ICacheQueryProxy.cs | 40 ---
.../Impl/ICacheQueryableInternal.cs | 14 +-
.../ignite/schema/generator/CodeGenerator.java | 16 +-
19 files changed, 795 insertions(+), 89 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/e4344fa8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/e4344fa8/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/e4344fa8/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
----------------------------------------------------------------------
diff --cc modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
index 7464a03,b4c3292..3d48f41
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
@@@ -60,11 -51,7 +60,11 @@@ namespace Apache.Ignite.Linq.Imp
/// </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,
++ public CacheFieldsQueryExecutor(ICacheInternal cache, bool local, int pageSize, bool enableDistributedJoins,
+ bool enforceJoinOrder)
{
Debug.Assert(cache != null);
@@@ -177,21 -132,119 +172,124 @@@
// 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)
- {
- EnableDistributedJoins = _enableDistributedJoins,
- PageSize = _pageSize,
- EnforceJoinOrder = _enforceJoinOrder
- }, selector);
+ return args => _cache.QueryFields(GetFieldsQuery(qryText, args), selector);
// Return delegate with reorder
- return args => _cache.QueryFields(new SqlFieldsQuery(qryText, _local,
- args.Select((x, i) => args[indices[i]]).ToArray())
+ return args => _cache.QueryFields(GetFieldsQuery(qryText,
+ args.Select((x, i) => args[indices[i]]).ToArray()), selector);
+ }
+ /// <summary>
+ /// Compiles the query without regard to number or order of arguments.
+ /// </summary>
+ public Func<object[], IQueryCursor<T>> CompileQuery<T>(QueryModel queryModel)
+ {
+ Debug.Assert(queryModel != null);
+
+ var qryText = GetQueryData(queryModel).QueryText;
+ var selector = GetResultSelector<T>(queryModel.SelectClause.Selector);
+
+ return args => _cache.QueryFields(GetFieldsQuery(qryText, args), selector);
+ }
+
+ /// <summary>
+ /// Compiles the query.
+ /// </summary>
+ /// <typeparam name="T">Result type.</typeparam>
+ /// <param name="queryModel">The query model.</param>
+ /// <param name="queryLambdaModel">The query model generated from lambda body.</param>
+ /// <param name="queryLambda">The query lambda.</param>
+ /// <returns>Compiled query func.</returns>
+ public Func<object[], IQueryCursor<T>> CompileQuery<T>(QueryModel queryModel, QueryModel queryLambdaModel,
+ LambdaExpression queryLambda)
+ {
+ Debug.Assert(queryModel != null);
+
+ // Get model from lambda to map arguments properly.
+ var qryData = GetQueryData(queryLambdaModel);
+
+ var qryText = GetQueryData(queryModel).QueryText;
+ var qryTextLambda = qryData.QueryText;
+
+ if (qryText != qryTextLambda)
+ {
+ Debug.WriteLine(qryText);
+ Debug.WriteLine(qryTextLambda);
+
+ throw new InvalidOperationException("Error compiling query: entire LINQ expression should be " +
+ "specified within lambda passed to Compile method. " +
+ "Part of the query can't be outside the Compile method call.");
+ }
+
+ var selector = GetResultSelector<T>(queryModel.SelectClause.Selector);
+
+ var qryParams = qryData.Parameters.ToArray();
+
+ // Compiled query is a delegate with query parameters
+ // Delegate parameters order and query parameters order may differ
+
+ // Simple case: lambda with no parameters. Only embedded parameters are used.
+ if (!queryLambda.Parameters.Any())
+ {
+ return argsUnused => _cache.QueryFields(GetFieldsQuery(qryText, qryParams), selector);
+ }
+
+ // These are in order of usage in query
+ var qryOrderArgs = qryParams.OfType<ParameterExpression>().Select(x => x.Name).ToArray();
+
+ // These are in order they come from user
+ var userOrderArgs = queryLambda.Parameters.Select(x => x.Name).ToList();
+
+ // Simple case: all query args directly map to the lambda args in the same order
+ if (qryOrderArgs.Length == qryParams.Length
+ && qryOrderArgs.SequenceEqual(userOrderArgs))
+ {
+ return args => _cache.QueryFields(GetFieldsQuery(qryText, args), selector);
+ }
+
+ // General case: embedded args and lambda args are mixed; same args can be used multiple times.
+ // Produce a mapping that defines where query arguments come from.
+ var mapping = qryParams.Select(x =>
+ {
+ var pe = x as ParameterExpression;
+
+ if (pe != null)
+ return userOrderArgs.IndexOf(pe.Name);
+
+ return -1;
+ }).ToArray();
+
+ return args => _cache.QueryFields(
+ GetFieldsQuery(qryText, MapQueryArgs(args, qryParams, mapping)), selector);
+ }
+
+ /// <summary>
+ /// Maps the query arguments.
+ /// </summary>
+ private static object[] MapQueryArgs(object[] userArgs, object[] embeddedArgs, int[] mapping)
+ {
+ var mappedArgs = new object[embeddedArgs.Length];
+
+ for (var i = 0; i < mappedArgs.Length; i++)
+ {
+ var map = mapping[i];
+
+ mappedArgs[i] = map < 0 ? embeddedArgs[i] : userArgs[map];
+ }
+
+ return mappedArgs;
+ }
+
+ /// <summary>
+ /// Gets the fields query.
+ /// </summary>
+ private SqlFieldsQuery GetFieldsQuery(string text, object[] args)
+ {
- return new SqlFieldsQuery(text, _local, args);
++ return new SqlFieldsQuery(text, _local, args)
+ {
+ EnableDistributedJoins = _enableDistributedJoins,
+ PageSize = _pageSize,
+ EnforceJoinOrder = _enforceJoinOrder
- }, selector);
++ };
}
/** <inheritdoc /> */
http://git-wip-us.apache.org/repos/asf/ignite/blob/e4344fa8/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/e4344fa8/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
----------------------------------------------------------------------
diff --cc modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
index a8c4c67,51297ee..ae94cfb
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
@@@ -423,21 -428,9 +427,10 @@@ namespace Apache.Ignite.Linq.Imp
}
else
{
- var innerExpr = joinClause.InnerSequence as ConstantExpression;
-
- if (innerExpr == null)
- throw new NotSupportedException("Unexpected JOIN inner sequence (subqueries are not supported): " +
- joinClause.InnerSequence);
-
- if (!(innerExpr.Value is ICacheQueryable))
- throw new NotSupportedException("Unexpected JOIN inner sequence " +
- "(only results of cache.ToQueryable() are supported): " +
- innerExpr.Value);
-
var queryable = ExpressionWalker.GetCacheQueryable(joinClause);
var tableName = ExpressionWalker.GetTableNameWithSchema(queryable);
- _builder.AppendFormat("inner join {0} as {1} on (", tableName, _aliases.GetTableAlias(tableName));
+ var alias = _aliases.GetTableAlias(joinClause);
+ _builder.AppendFormat("inner join {0} as {1} on (", tableName, alias);
}
BuildJoinCondition(joinClause.InnerKeySelector, joinClause.OuterKeySelector);
http://git-wip-us.apache.org/repos/asf/ignite/blob/e4344fa8/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/e4344fa8/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
----------------------------------------------------------------------