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
----------------------------------------------------------------------