You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/06/06 08:59:19 UTC

[01/50] [abbrv] ignite git commit: IGNITE-5391: CREATE INDEX and DROP INDEX are now allowed on non-sql caches again :-)

Repository: ignite
Updated Branches:
  refs/heads/ignite-5075 54b693585 -> a7cd1b637


IGNITE-5391: CREATE INDEX and DROP INDEX are now allowed on non-sql caches again :-)


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c7638bc4
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c7638bc4
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c7638bc4

Branch: refs/heads/ignite-5075
Commit: c7638bc46c32234eb3a37c81a30f1cd1e5d9c984
Parents: fbcd474
Author: devozerov <vo...@gridgain.com>
Authored: Fri Jun 2 12:43:59 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 12:43:59 2017 +0300

----------------------------------------------------------------------
 .../processors/query/GridQueryProcessor.java    | 10 --------
 .../query/h2/ddl/DdlStatementsProcessor.java    | 26 +-------------------
 .../DynamicIndexAbstractBasicSelfTest.java      | 22 +++++------------
 3 files changed, 7 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c7638bc4/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index bfbfb6c..fef7d4c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -358,14 +358,6 @@ public class GridQueryProcessor extends GridProcessorAdapter {
 
                 msg.onError(new SchemaOperationException(SchemaOperationException.CODE_CACHE_NOT_FOUND, cacheName));
             }
-            else if (!cacheDesc.sql()) {
-                if (log.isDebugEnabled())
-                    log.debug("Received schema propose discovery message, but cache was not created through " +
-                        "CREATE TABLE command (will report error) [opId=" + opId + ", msg=" + msg + ']');;
-
-                msg.onError(new SchemaOperationException("CREATE INDEX and DROP INDEX operations are only allowed on " +
-                    "caches created with CREATE TABLE command [cacheName=" + cacheName + ']'));
-            }
             else {
                 CacheConfiguration ccfg = cacheDesc.cacheConfiguration();
 
@@ -601,8 +593,6 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         boolean nop = false;
 
         if (cacheExists) {
-            assert cacheDesc.sql();
-
             if (cacheRegistered) {
                 // If cache is started, we perform validation against real schema.
                 T3<QueryTypeDescriptorImpl, Boolean, SchemaOperationException> res = prepareChangeOnStartedCache(op);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c7638bc4/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
index 7051f09..04a0c62 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
@@ -28,8 +28,6 @@ import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.cache.query.FieldsQueryCursor;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.IgniteInternalFuture;
-import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
-import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
 import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
 import org.apache.ignite.internal.processors.query.GridQueryProperty;
@@ -46,7 +44,6 @@ import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser;
 import org.apache.ignite.internal.processors.query.h2.sql.GridSqlStatement;
 import org.apache.ignite.internal.processors.query.schema.SchemaOperationException;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
-import org.apache.ignite.internal.util.typedef.internal.A;
 import org.h2.command.Prepared;
 import org.h2.command.ddl.CreateIndex;
 import org.h2.command.ddl.CreateTable;
@@ -104,8 +101,6 @@ public class DdlStatementsProcessor {
                 if (tbl == null)
                     throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_NOT_FOUND, cmd.tableName());
 
-                checkSqlCache(tbl.cache());
-
                 assert tbl.rowDescriptor() != null;
 
                 QueryIndex newIdx = new QueryIndex();
@@ -134,13 +129,11 @@ public class DdlStatementsProcessor {
                     newIdx, cmd.ifNotExists());
             }
             else if (stmt0 instanceof GridSqlDropIndex) {
-                GridSqlDropIndex cmd = (GridSqlDropIndex)stmt0;
+                GridSqlDropIndex cmd = (GridSqlDropIndex) stmt0;
 
                 GridH2Table tbl = idx.dataTableForIndex(cmd.schemaName(), cmd.indexName());
 
                 if (tbl != null) {
-                    checkSqlCache(tbl.cache());
-
                     fut = ctx.query().dynamicIndexDrop(tbl.cacheName(), cmd.schemaName(), cmd.indexName(),
                         cmd.ifExists());
                 }
@@ -280,23 +273,6 @@ public class DdlStatementsProcessor {
     }
 
     /**
-     * Check that given context corresponds to an SQL cache.
-     * @param cctx Cache context.
-     * @throws SchemaOperationException if given context does not correspond to an SQL cache.
-     */
-    private static void checkSqlCache(GridCacheContext cctx) throws SchemaOperationException {
-        A.notNull(cctx, "cctx");
-
-        DynamicCacheDescriptor desc = cctx.grid().context().cache().cacheDescriptor(cctx.cacheId());
-
-        assert desc != null;
-
-        if (!desc.sql())
-            throw new SchemaOperationException("CREATE INDEX and DROP INDEX operations are only allowed on caches " +
-                "created with CREATE TABLE command [cacheName=" + cctx.name() + ']');
-    }
-
-    /**
      * @param cmd Statement.
      * @return Whether {@code cmd} is a DDL statement we're able to handle.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/c7638bc4/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
index cf83319..0b6b0ca 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
@@ -897,28 +897,18 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
     }
 
     /**
-     * Test that operations fail on statically configured cache.
+     * Test that operations work on statically configured cache.
      *
      * @throws Exception If failed.
      */
-    public void testFailOnNonSqlCache() throws Exception {
+    public void testNonSqlCache() throws Exception {
         final QueryIndex idx = index(IDX_NAME_2, field(FIELD_NAME_1));
 
-        assertSchemaException(new RunnableX() {
-            @Override public void run() throws Exception {
-                dynamicIndexCreate(STATIC_CACHE_NAME, TBL_NAME, idx, true);
-            }
-        }, "CREATE INDEX and DROP INDEX operations are only allowed on caches created with CREATE TABLE command " +
-            "[cacheName=cache_static]", IgniteQueryErrorCode.UNKNOWN);
-
-        assertNoIndex(STATIC_CACHE_NAME, TBL_NAME, IDX_NAME_2);
+        dynamicIndexCreate(STATIC_CACHE_NAME, TBL_NAME, idx, true);
+        assertIndex(STATIC_CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
 
-        assertSchemaException(new RunnableX() {
-            @Override public void run() throws Exception {
-                dynamicIndexDrop(STATIC_CACHE_NAME, IDX_NAME_1, true);
-            }
-        }, "CREATE INDEX and DROP INDEX operations are only allowed on caches created with CREATE TABLE command " +
-            "[cacheName=cache_static]", IgniteQueryErrorCode.UNKNOWN);
+        dynamicIndexDrop(STATIC_CACHE_NAME, IDX_NAME_1, true);
+        assertNoIndex(STATIC_CACHE_NAME, TBL_NAME, IDX_NAME_1);
     }
 
     /**


[37/50] [abbrv] ignite git commit: .NET: Fix build script to copy jars even if Java build is skipped

Posted by sb...@apache.org.
.NET: Fix build script to copy jars even if Java build is skipped


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/da377204
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/da377204
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/da377204

Branch: refs/heads/ignite-5075
Commit: da37720449cff2cc5c2e1dd8c0015aab6ac6d5c6
Parents: 1ed088c
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Mon Jun 5 16:06:10 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Mon Jun 5 16:06:10 2017 +0300

----------------------------------------------------------------------
 modules/platforms/dotnet/build.ps1 | 36 ++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/da377204/modules/platforms/dotnet/build.ps1
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/build.ps1 b/modules/platforms/dotnet/build.ps1
index 692959f..d9757ed 100644
--- a/modules/platforms/dotnet/build.ps1
+++ b/modules/platforms/dotnet/build.ps1
@@ -74,15 +74,15 @@ param (
  )
 
 # 1) Build Java (Maven)
-if (!$skipJava) {
-    # Detect Ignite root directory
-    cd $PSScriptRoot\..
+# Detect Ignite root directory
+cd $PSScriptRoot\..
 
-    while (!((Test-Path bin) -and (Test-Path examples) -and ((Test-Path modules) -or (Test-Path platforms))))
-    { cd .. }
+while (!((Test-Path bin) -and (Test-Path examples) -and ((Test-Path modules) -or (Test-Path platforms))))
+{ cd .. }
 
-    echo "Ignite home detected at '$pwd'."
+echo "Ignite home detected at '$pwd'."
 
+if (!$skipJava) {
     # Detect Maven
     $mv = "mvn"
     if ((Get-Command $mv -ErrorAction SilentlyContinue) -eq $null) { 
@@ -107,23 +107,23 @@ if (!$skipJava) {
     if ($LastExitCode -ne 0) {
         echo "Java (Maven) build failed."; exit -1
     }
-
-    # Copy (relevant) jars
-    $libsDir = "$PSScriptRoot\bin\Libs"
-    mkdir -Force $libsDir; del -Force $libsDir\*.*
-    
-    ls modules\indexing\target,modules\core\target,modules\spring\target *.jar -recurse `
-	   -include "ignite-core*","ignite-indexing*","ignite-shmem*","ignite-spring*","lucene*","h2*","cache-api*","commons-*","spring*" `
-	   -exclude "*-sources*","*-javadoc*","*-tests*" `
-	   | % { copy -Force $_ $libsDir }
-
-    # Restore directory
-    cd $PSScriptRoot
 }
 else {
     echo "Java (Maven) build skipped."
 }
 
+# Copy (relevant) jars
+$libsDir = "$PSScriptRoot\bin\Libs"
+mkdir -Force $libsDir; del -Force $libsDir\*.*
+
+ls modules\indexing\target,modules\core\target,modules\spring\target *.jar -recurse `
+   -include "ignite-core*","ignite-indexing*","ignite-shmem*","ignite-spring*","lucene*","h2*","cache-api*","commons-*","spring*" `
+   -exclude "*-sources*","*-javadoc*","*-tests*" `
+   | % { copy -Force $_ $libsDir }
+
+# Restore directory
+cd $PSScriptRoot
+
 
 # 2) Build .NET
 # Detect MSBuild 4.0+


[03/50] [abbrv] ignite git commit: IGNITE-5356 .NET: Fix runtime dependency loading with peer deployment

Posted by sb...@apache.org.
IGNITE-5356 .NET: Fix runtime dependency loading with peer deployment

This closes #2063


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/79d45e34
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/79d45e34
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/79d45e34

Branch: refs/heads/ignite-5075
Commit: 79d45e34335d2286bf382d7a8a49a71661f26f79
Parents: 34409fd
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Jun 2 12:59:58 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Jun 2 12:59:58 2017 +0300

----------------------------------------------------------------------
 .../Apache.Ignite.Core.Tests.TestDll.csproj     |  1 +
 .../TestExtensions.cs                           | 35 ++++++++++++++++++++
 .../Apache.Ignite.Core.Tests.csproj             |  1 +
 .../Deployment/PeerAssemblyLoadingTest.cs       | 13 ++++++++
 .../Deployment/RuntimeDependencyFunc.cs         | 34 +++++++++++++++++++
 .../Impl/Compute/ComputeJobHolder.cs            |  6 +++-
 .../Impl/Deployment/GetAssemblyFunc.cs          | 28 ++++++++++++++++
 .../Impl/Deployment/PeerAssemblyResolver.cs     | 26 ++++++++++++++-
 .../Apache.Ignite.Core/Impl/ExceptionUtils.cs   |  1 +
 9 files changed, 143 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/79d45e34/modules/platforms/dotnet/Apache.Ignite.Core.Tests.TestDll/Apache.Ignite.Core.Tests.TestDll.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.TestDll/Apache.Ignite.Core.Tests.TestDll.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.TestDll/Apache.Ignite.Core.Tests.TestDll.csproj
index db7a4d1..0f9e13b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.TestDll/Apache.Ignite.Core.Tests.TestDll.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.TestDll/Apache.Ignite.Core.Tests.TestDll.csproj
@@ -42,6 +42,7 @@
   <ItemGroup>
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="TestClass.cs" />
+    <Compile Include="TestExtensions.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="Apache.Ignite.Core.Tests.TestDll.snk" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/79d45e34/modules/platforms/dotnet/Apache.Ignite.Core.Tests.TestDll/TestExtensions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.TestDll/TestExtensions.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.TestDll/TestExtensions.cs
new file mode 100644
index 0000000..65a1484
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.TestDll/TestExtensions.cs
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Tests.TestDll
+{
+    using System.Linq;
+
+    /// <summary>
+    /// Extension methods for tests.
+    /// </summary>
+    public static class TestExtensions
+    {
+        /// <summary>
+        /// Reverses the string.
+        /// </summary>
+        public static string ReverseString(this string str)
+        {
+            return new string(str.Reverse().ToArray());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/79d45e34/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index d459d2a..12b0b6a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -120,6 +120,7 @@
     <Compile Include="Collections\ReadOnlyCollectionTest.cs" />
     <Compile Include="Collections\ReadOnlyDictionaryTest.cs" />
     <Compile Include="Common\IgniteGuidTest.cs" />
+    <Compile Include="Deployment\RuntimeDependencyFunc.cs" />
     <Compile Include="Log\ConcurrentMemoryTarget.cs" />
     <Compile Include="Log\DefaultLoggerTest.cs" />
     <Compile Include="Log\Log4NetLoggerTest.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/79d45e34/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingTest.cs
index 27a2d65..8245333 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingTest.cs
@@ -118,6 +118,19 @@ namespace Apache.Ignite.Core.Tests.Deployment
         }
 
         /// <summary>
+        /// Tests the runtime dependency: AssemblyResolve event fires during job execution,
+        /// not during deserialization. This happens with static classes, for example.
+        /// </summary>
+        [Test]
+        public void TestRuntimeDependency()
+        {
+            TestDeployment(remoteCompute =>
+            {
+                Assert.AreEqual("dcba", remoteCompute.Apply(new RuntimeDependencyFunc(), "abcd"));
+            });
+        }
+
+        /// <summary>
         /// Tests the peer deployment.
         /// </summary>
         public static void TestDeployment(Action<ICompute> test, bool enablePeerDeployment = true)

http://git-wip-us.apache.org/repos/asf/ignite/blob/79d45e34/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/RuntimeDependencyFunc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/RuntimeDependencyFunc.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/RuntimeDependencyFunc.cs
new file mode 100644
index 0000000..5b076a9
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/RuntimeDependencyFunc.cs
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Tests.Deployment
+{
+    using Apache.Ignite.Core.Compute;
+    using Apache.Ignite.Core.Tests.TestDll;
+
+    /// <summary>
+    /// Func with runtime dependency via extension method.
+    /// </summary>
+    public class RuntimeDependencyFunc : IComputeFunc<string, string>
+    {
+        /** <inheritdoc /> */
+        public string Invoke(string arg)
+        {
+            return arg.ReverseString();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/79d45e34/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeJobHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeJobHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeJobHolder.cs
index 314814d..120d074 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeJobHolder.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeJobHolder.cs
@@ -26,6 +26,7 @@ namespace Apache.Ignite.Core.Impl.Compute
     using Apache.Ignite.Core.Impl.Binary.IO;
     using Apache.Ignite.Core.Impl.Cluster;
     using Apache.Ignite.Core.Impl.Compute.Closure;
+    using Apache.Ignite.Core.Impl.Deployment;
     using Apache.Ignite.Core.Impl.Memory;
     using Apache.Ignite.Core.Impl.Resource;
 
@@ -102,7 +103,10 @@ namespace Apache.Ignite.Core.Impl.Compute
             object res;
             bool success;
 
-            Execute0(cancel, out res, out success);
+            using (PeerAssemblyResolver.GetInstance(_ignite, Guid.Empty))
+            {
+                Execute0(cancel, out res, out success);
+            }
 
             // 2. Try writing result to the stream.
             ClusterGroupImpl prj = _ignite.ClusterGroup;

http://git-wip-us.apache.org/repos/asf/ignite/blob/79d45e34/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/GetAssemblyFunc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/GetAssemblyFunc.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/GetAssemblyFunc.cs
index 6d54dbf..8f0c266 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/GetAssemblyFunc.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/GetAssemblyFunc.cs
@@ -17,7 +17,10 @@
  
 namespace Apache.Ignite.Core.Impl.Deployment
 {
+    using System;
     using System.Diagnostics;
+    using System.IO;
+    using System.Reflection;
     using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Compute;
@@ -58,6 +61,7 @@ namespace Apache.Ignite.Core.Impl.Deployment
                 return new AssemblyRequestResult(AssemblyLoader.GetAssemblyBytes(asm), null);
             }
 
+            // Try cached assemblies.
             var bytes = AssemblyLoader.GetAssemblyBytes(arg.AssemblyName);
 
             if (bytes != null)
@@ -65,6 +69,30 @@ namespace Apache.Ignite.Core.Impl.Deployment
                 return new AssemblyRequestResult(bytes, null);
             }
 
+            // Assembly may be present but not loaded - attempt to load into main context.
+            try
+            {
+                asm = Assembly.Load(arg.AssemblyName);
+
+                if (asm != null)
+                {
+                    return new AssemblyRequestResult(AssemblyLoader.GetAssemblyBytes(asm), null);
+                }
+            }
+            catch (FileNotFoundException)
+            {
+                return null;
+            }
+            catch (FileLoadException ex)
+            {
+                return new AssemblyRequestResult(null, string.Format("Failed to load assembly: {0} ({1})", asm, ex));
+            }
+
+            catch (BadImageFormatException ex)
+            {
+                return new AssemblyRequestResult(null, string.Format("Failed to load assembly: {0} ({1})", asm, ex));
+            }
+
             return null;
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/79d45e34/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerAssemblyResolver.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerAssemblyResolver.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerAssemblyResolver.cs
index 607ca57..b81bbbc 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerAssemblyResolver.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerAssemblyResolver.cs
@@ -45,6 +45,8 @@ namespace Apache.Ignite.Core.Impl.Deployment
 
             _handler = (sender, args) => GetAssembly(ignite, args.Name, originNodeId);
 
+            // AssemblyResolve handler is called only when aseembly can't be found via normal lookup,
+            // so we won't end up loading assemblies that are already present.
             AppDomain.CurrentDomain.AssemblyResolve += _handler;
         }
 
@@ -55,6 +57,19 @@ namespace Apache.Ignite.Core.Impl.Deployment
         }
 
         /// <summary>
+        /// Gets an instance of <see cref="PeerAssemblyResolver"/> when peer loading is enabled; otherwise null.
+        /// </summary>
+        public static PeerAssemblyResolver GetInstance(Ignite ignite, Guid originNodeId)
+        {
+            if (ignite == null || ignite.Configuration.PeerAssemblyLoadingMode == PeerAssemblyLoadingMode.Disabled)
+            {
+                return null;
+            }
+
+            return new PeerAssemblyResolver(ignite, originNodeId);
+        }
+
+        /// <summary>
         /// Gets the assembly from remote nodes.
         /// </summary>
         /// <param name="typeName">Assembly-qualified type name.</param>
@@ -158,7 +173,10 @@ namespace Apache.Ignite.Core.Impl.Deployment
         /// </summary>
         private static IEnumerable<Guid> GetDotNetNodes(IIgnite ignite, Guid originNodeId)
         {
-            yield return originNodeId;
+            if (originNodeId != Guid.Empty)
+            {
+                yield return originNodeId;
+            }
 
             foreach (var node in ignite.GetCluster().ForDotNet().ForRemotes().GetNodes())
             {
@@ -184,6 +202,12 @@ namespace Apache.Ignite.Core.Impl.Deployment
                 // Normal situation: node has left.
                 return null;
             }
+            catch (AggregateException aex)
+            {
+                // Normal situation: node has left.
+                aex.Handle(e => e is ClusterGroupEmptyException);
+                return null;
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/79d45e34/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs
index e2d61d7..dd70f5a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs
@@ -75,6 +75,7 @@ namespace Apache.Ignite.Core.Impl
 
             // Cluster exceptions.
             Exs["org.apache.ignite.cluster.ClusterGroupEmptyException"] = (c, m, e, i) => new ClusterGroupEmptyException(m, e);
+            Exs["org.apache.ignite.internal.cluster.ClusterGroupEmptyCheckedException"] = (c, m, e, i) => new ClusterGroupEmptyException(m, e);
             Exs["org.apache.ignite.cluster.ClusterTopologyException"] = (c, m, e, i) => new ClusterTopologyException(m, e);
 
             // Compute exceptions.


[16/50] [abbrv] ignite git commit: ignite-4496 Review all logging for sensitive data leak

Posted by sb...@apache.org.
ignite-4496 Review all logging for sensitive data leak


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/b7d8d1b3
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/b7d8d1b3
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/b7d8d1b3

Branch: refs/heads/ignite-5075
Commit: b7d8d1b3f1376c6f83a60f73a90d47817cb159cc
Parents: bfb2781
Author: Alexandr Kuramshin <ak...@gridgain.com>
Authored: Fri Jun 2 16:24:24 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jun 2 16:24:24 2017 +0300

----------------------------------------------------------------------
 .../cache/store/jdbc/CacheJdbcBlobStore.java    |   5 +-
 .../ignite/internal/binary/BinaryTypeProxy.java |   3 +
 .../stream/v2/DirectByteBufferStreamImplV2.java |   1 +
 .../checkpoint/GridCheckpointManager.java       |  45 +-
 .../checkpoint/GridCheckpointRequest.java       |   2 +
 .../processors/cache/GridCacheAdapter.java      |  51 +-
 .../cache/GridCacheDeploymentManager.java       |  12 +-
 .../distributed/dht/GridDhtCacheAdapter.java    |   6 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java |   9 +-
 ...arOptimisticSerializableTxPrepareFuture.java |   6 +-
 .../query/GridCacheQueryFutureAdapter.java      |  18 +-
 .../store/GridCacheStoreManagerAdapter.java     |   4 +-
 .../cache/store/GridCacheWriteBehindStore.java  |  13 +-
 .../cache/transactions/TxDeadlock.java          |  11 +-
 .../resource/GridResourceProcessor.java         |   9 +-
 .../processors/task/GridTaskWorker.java         |   4 +-
 .../util/tostring/GridToStringBuilder.java      | 419 ++++++++++++++++
 .../util/tostring/GridToStringThreadLocal.java  |   6 +-
 .../internal/SensitiveInfoTestLoggerProxy.java  | 493 +++++++++++++++++++
 .../SensitiveInfoTestLoggerProxy_Exclude.txt    |  20 +
 .../SensitiveInfoTestLoggerProxy_Include.txt    |  18 +
 .../tostring/IncludeSensitiveAtomicTest.java    |  29 ++
 .../util/tostring/IncludeSensitiveTest.java     | 149 ++++++
 .../IncludeSensitiveTransactionalTest.java      |  43 ++
 .../junits/IgniteTestResources.java             |  11 +-
 25 files changed, 1321 insertions(+), 66 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcBlobStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcBlobStore.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcBlobStore.java
index 2739865..88849f7 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcBlobStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcBlobStore.java
@@ -252,7 +252,10 @@ public class CacheJdbcBlobStore<K, V> extends CacheStoreAdapter<K, V> {
         V val = entry.getValue();
 
         if (log.isDebugEnabled())
-            log.debug("Store put [key=" + key + ", val=" + val + ", tx=" + tx + ']');
+            log.debug(S.toString("Store put",
+                "key", key, true,
+                "val", val, true,
+                "tx", tx, false));
 
         Connection conn = null;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeProxy.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeProxy.java
index 3a51050..57201e6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeProxy.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeProxy.java
@@ -22,6 +22,7 @@ import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.binary.BinaryType;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.internal.S;
 
 import java.util.Collection;
@@ -36,9 +37,11 @@ public class BinaryTypeProxy implements BinaryType {
     private final BinaryContext ctx;
 
     /** Type ID. */
+    @GridToStringInclude(sensitive = true)
     private int typeId;
 
     /** Raw data. */
+    @GridToStringInclude(sensitive = true)
     private final String clsName;
 
     /** Target type. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/direct/stream/v2/DirectByteBufferStreamImplV2.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/direct/stream/v2/DirectByteBufferStreamImplV2.java b/modules/core/src/main/java/org/apache/ignite/internal/direct/stream/v2/DirectByteBufferStreamImplV2.java
index c92c470..9901b73 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/direct/stream/v2/DirectByteBufferStreamImplV2.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/direct/stream/v2/DirectByteBufferStreamImplV2.java
@@ -214,6 +214,7 @@ public class DirectByteBufferStreamImplV2 implements DirectByteBufferStream {
     private final MessageFactory msgFactory;
 
     /** */
+    @GridToStringExclude
     private ByteBuffer buf;
 
     /** */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointManager.java
index aee958a..782ee5e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointManager.java
@@ -185,16 +185,20 @@ public class GridCheckpointManager extends GridManagerAdapter<CheckpointSpi> {
 
                 case SESSION_SCOPE: {
                     if (closedSess.contains(ses.getId())) {
-                        U.warn(log, "Checkpoint will not be saved due to session invalidation [key=" + key +
-                            ", val=" + state + ", ses=" + ses + ']',
+                        U.warn(log, S.toString("Checkpoint will not be saved due to session invalidation",
+                            "key", key, true,
+                            "val", state, true,
+                            "ses", ses, false),
                             "Checkpoint will not be saved due to session invalidation.");
 
                         break;
                     }
 
                     if (now > ses.getEndTime()) {
-                        U.warn(log, "Checkpoint will not be saved due to session timeout [key=" + key +
-                            ", val=" + state + ", ses=" + ses + ']',
+                        U.warn(log, S.toString("Checkpoint will not be saved due to session timeout",
+                            "key", key, true,
+                            "val", state, true,
+                            "ses", ses, false),
                             "Checkpoint will not be saved due to session timeout.");
 
                         break;
@@ -217,8 +221,10 @@ public class GridCheckpointManager extends GridManagerAdapter<CheckpointSpi> {
 
                         // Double check.
                         if (closedSess.contains(ses.getId())) {
-                            U.warn(log, "Checkpoint will not be saved due to session invalidation [key=" + key +
-                                ", val=" + state + ", ses=" + ses + ']',
+                            U.warn(log, S.toString("Checkpoint will not be saved due to session invalidation",
+                                "key", key, true,
+                                "val", state, true,
+                                "ses", ses, false),
                                 "Checkpoint will not be saved due to session invalidation.");
 
                             keyMap.remove(ses.getId(), keys);
@@ -228,8 +234,10 @@ public class GridCheckpointManager extends GridManagerAdapter<CheckpointSpi> {
                     }
 
                     if (log.isDebugEnabled())
-                        log.debug("Resolved keys for session [keys=" + keys + ", ses=" + ses +
-                            ", keyMap=" + keyMap + ']');
+                        log.debug(S.toString("Resolved keys for session",
+                            "keys", keys, true,
+                            "ses", ses, false,
+                            "keyMap", keyMap, false));
 
                     // Note: Check that keys exists because session may be invalidated during saving
                     // checkpoint from GridFuture.
@@ -263,8 +271,11 @@ public class GridCheckpointManager extends GridManagerAdapter<CheckpointSpi> {
             }
         }
         catch (IgniteSpiException e) {
-            throw new IgniteCheckedException("Failed to save checkpoint [key=" + key + ", val=" + state + ", scope=" +
-                scope + ", timeout=" + timeout + ']', e);
+            throw new IgniteCheckedException(S.toString("Failed to save checkpoint",
+                "key", key, true,
+                "val", state, true,
+                "scope", scope, false,
+                "timeout", timeout, false), e);
         }
 
         return saved;
@@ -313,7 +324,8 @@ public class GridCheckpointManager extends GridManagerAdapter<CheckpointSpi> {
             rmv = getSpi(ses.getCheckpointSpi()).removeCheckpoint(key);
         }
         else if (log.isDebugEnabled())
-            log.debug("Checkpoint will not be removed (key map not found) [key=" + key + ", ses=" + ses + ']');
+            log.debug(S.toString("Checkpoint will not be removed (key map not found)",
+                "key", key, true, "ses", ses, false));
 
         return rmv;
     }
@@ -345,7 +357,8 @@ public class GridCheckpointManager extends GridManagerAdapter<CheckpointSpi> {
             return state;
         }
         catch (IgniteSpiException e) {
-            throw new IgniteCheckedException("Failed to load checkpoint: " + key, e);
+            throw new IgniteCheckedException(S.INCLUDE_SENSITIVE ?
+                ("Failed to load checkpoint: " + key) : "Failed to load checkpoint", e);
         }
     }
 
@@ -389,14 +402,16 @@ public class GridCheckpointManager extends GridManagerAdapter<CheckpointSpi> {
             String msg;
 
             if (type == EVT_CHECKPOINT_SAVED)
-                msg = "Checkpoint saved: " + key;
+                msg = "Checkpoint saved";
             else if (type == EVT_CHECKPOINT_LOADED)
-                msg = "Checkpoint loaded: " + key;
+                msg = "Checkpoint loaded";
             else {
                 assert type == EVT_CHECKPOINT_REMOVED : "Invalid event type: " + type;
 
-                msg = "Checkpoint removed: " + key;
+                msg = "Checkpoint removed";
             }
+            if (S.INCLUDE_SENSITIVE)
+                msg += ": " + key;
 
             ctx.event().record(new CheckpointEvent(ctx.discovery().localNode(), msg, type, key));
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointRequest.java
index ddb4f26..8b21ff2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointRequest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.managers.checkpoint;
 
 import java.io.Externalizable;
 import java.nio.ByteBuffer;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.plugin.extensions.communication.Message;
@@ -36,6 +37,7 @@ public class GridCheckpointRequest implements Message {
     private IgniteUuid sesId;
 
     /** */
+    @GridToStringInclude(sensitive = true)
     private String key;
 
     /** */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
index ff25dd9..cd781aa 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
@@ -2240,7 +2240,10 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "put [key=" + key + ", val=" + val + ", filter=" + filter + ']';
+                return S.toString("put",
+                    "key", key, true,
+                    "val", val, true,
+                    "filter", filter, false);
             }
         });
     }
@@ -2290,7 +2293,10 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "putAsync [key=" + key + ", val=" + val + ", filter=" + filter + ']';
+                return S.toString("putAsync",
+                    "key", key, true,
+                    "val", val, true,
+                    "filter", filter, false);
             }
         });
     }
@@ -2345,7 +2351,10 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "putx [key=" + key + ", val=" + val + ", filter=" + filter + ']';
+                return S.toString("putx",
+                    "key", key, true,
+                    "val", val, true,
+                    "filter", filter, false);
             }
         });
 
@@ -2503,7 +2512,9 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "invokeAsync [key=" + key + ", entryProcessor=" + entryProcessor + ']';
+                return S.toString("invokeAsync",
+                    "key", key, true,
+                    "entryProcessor", entryProcessor, false);
             }
         });
 
@@ -2550,7 +2561,9 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "invokeAllAsync [keys=" + keys + ", entryProcessor=" + entryProcessor + ']';
+                return S.toString("invokeAllAsync",
+                    "keys", keys, true,
+                    "entryProcessor", entryProcessor, false);
             }
         });
 
@@ -2588,7 +2601,8 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "invokeAllAsync [map=" + map + ']';
+                return S.toString("invokeAllAsync",
+                    "map", map, true);
             }
         });
 
@@ -2768,7 +2782,8 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "putAll [map=" + m + ']';
+                return S.toString("putAll",
+                    "map", m, true);
             }
         });
     }
@@ -2798,7 +2813,8 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "putAllAsync [map=" + m + ']';
+                return S.toString("putAllAsync",
+                    "map", m, true);
             }
         });
     }
@@ -2851,7 +2867,8 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "remove [key=" + key + ']';
+                return S.toString("remove",
+                    "key", key, true);
             }
         });
     }
@@ -2892,7 +2909,8 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "removeAsync [key=" + key + ']';
+                return S.toString("removeAsync",
+                    "key", key, true);
             }
         });
     }
@@ -2954,7 +2972,8 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "removeAll [keys=" + keys + ']';
+                return S.toString("removeAll",
+                    "keys", keys, true);
             }
         });
     }
@@ -2995,7 +3014,8 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "removeAllAsync [keys=" + keys + ']';
+                return S.toString("removeAllAsync",
+                    "keys", keys, true);
             }
         });
     }
@@ -3047,7 +3067,8 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "removex [key=" + key + ']';
+                return S.toString("removex",
+                    "key", key, true);
             }
         });
 
@@ -3104,7 +3125,9 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             }
 
             @Override public String toString() {
-                return "removeAsync [key=" + key + ", filter=" + filter + ']';
+                return S.toString("removeAsync",
+                    "key", key, true,
+                    "filter", filter, false);
             }
         });
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDeploymentManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDeploymentManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDeploymentManager.java
index 55e8669..a1eb706 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDeploymentManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDeploymentManager.java
@@ -351,10 +351,14 @@ public class GridCacheDeploymentManager<K, V> extends GridCacheSharedManagerAdap
         boolean res = F.eq(ldr, keyLdr) || F.eq(ldr, valLdr);
 
         if (log.isDebugEnabled())
-            log.debug("Finished examining entry [entryCls=" + e.getClass() +
-                ", key=" + key0 + ", keyCls=" + key0.getClass() +
-                ", valCls=" + (val0 != null ? val0.getClass() : "null") +
-                ", keyLdr=" + keyLdr + ", valLdr=" + valLdr + ", res=" + res + ']');
+            log.debug(S.toString("Finished examining entry",
+                "entryCls", e.getClass(), true,
+                "key", key0, true,
+                "keyCls", key0.getClass(), true,
+                "valCls", (val0 != null ? val0.getClass() : "null"), true,
+                "keyLdr", keyLdr, false,
+                "valLdr", valLdr, false,
+                "res", res, false));
 
         return res;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java
index 10caf07..c3d5f88 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java
@@ -561,8 +561,10 @@ public abstract class GridDhtCacheAdapter<K, V> extends GridDistributedCacheAdap
         }
         catch (GridDhtInvalidPartitionException e) {
             if (log.isDebugEnabled())
-                log.debug("Ignoring entry for partition that does not belong [key=" + key + ", val=" + val +
-                    ", err=" + e + ']');
+                log.debug(S.toString("Ignoring entry for partition that does not belong",
+                    "key", key, true,
+                    "val", val, true,
+                    "err", e, false));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
index e2b7803..8a674fb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
@@ -1141,7 +1141,8 @@ public final class GridDhtTxPrepareFuture extends GridCacheCompoundFuture<Ignite
 
             assert key != null : entry.key();
 
-            msg.append("key=").append(key.toString()).append(", keyCls=").append(key.getClass().getName());
+            if (S.INCLUDE_SENSITIVE)
+                msg.append("key=").append(key.toString()).append(", keyCls=").append(key.getClass().getName());
         }
         catch (Exception e) {
             msg.append("key=<failed to get key: ").append(e.toString()).append(">");
@@ -1154,8 +1155,10 @@ public final class GridDhtTxPrepareFuture extends GridCacheCompoundFuture<Ignite
 
             Object val = cacheVal != null ? cctx.unwrapBinaryIfNeeded(cacheVal, entry.keepBinary(), false) : null;
 
-            if (val != null)
-                msg.append(", val=").append(val.toString()).append(", valCls=").append(val.getClass().getName());
+            if (val != null) {
+                if (S.INCLUDE_SENSITIVE)
+                    msg.append(", val=").append(val.toString()).append(", valCls=").append(val.getClass().getName());
+            }
             else
                 msg.append(", val=null");
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
index 6060729..72ddc67 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
@@ -114,8 +114,10 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
                                     Object key = entry.key().value(ctx.cacheObjectContext(), false);
 
                                     IgniteTxOptimisticCheckedException err0 =
-                                        new IgniteTxOptimisticCheckedException("Failed to prepare transaction, " +
-                                            "read/write conflict [key=" + key + ", cache=" + ctx.name() + ']');
+                                        new IgniteTxOptimisticCheckedException(S.toString(
+                                            "Failed to prepare transaction, read/write conflict",
+                                            "key", key, true,
+                                            "cache", ctx.name(), false));
 
                                     ERR_UPD.compareAndSet(this, null, err0);
                                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryFutureAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryFutureAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryFutureAdapter.java
index 7ad7c31..c418ca2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryFutureAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryFutureAdapter.java
@@ -369,18 +369,24 @@ public abstract class GridCacheQueryFutureAdapter<K, V, R> extends GridFutureAda
             return;
 
         if (log.isDebugEnabled())
-            log.debug("Received query result page [nodeId=" + nodeId + ", data=" + data +
-                ", err=" + err + ", finished=" + finished + "]");
+            log.debug(S.toString("Received query result page",
+                "nodeId", nodeId, false,
+                "data", data, true,
+                "err", err, false,
+                "finished", finished, false));
 
         try {
             if (err != null)
                 synchronized (this) {
                     enqueue(Collections.emptyList());
 
-                    onDone(nodeId != null ?
-                        new IgniteCheckedException("Failed to execute query on node [query=" + qry +
-                            ", nodeId=" + nodeId + "]", err) :
-                        new IgniteCheckedException("Failed to execute query locally: " + qry, err));
+                    onDone(new IgniteCheckedException(nodeId != null ?
+                        S.toString("Failed to execute query on node",
+                            "query", qry, true,
+                            "nodeId", nodeId, false) :
+                        S.toString("Failed to execute query locally",
+                            "query", qry, true),
+                        err));
 
                     onPage(nodeId, true);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
index cf11a28..62ead23 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
@@ -331,7 +331,9 @@ public abstract class GridCacheStoreManagerAdapter extends GridCacheManagerAdapt
             }
 
             if (log.isDebugEnabled())
-                log.debug("Loaded value from store [key=" + key + ", val=" + val + ']');
+                log.debug(S.toString("Loaded value from store",
+                    "key", key, true,
+                    "val", val, true));
 
             if (convert) {
                 val = convert(val);

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheWriteBehindStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheWriteBehindStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheWriteBehindStore.java
index 64238ab..831b1b0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheWriteBehindStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheWriteBehindStore.java
@@ -419,7 +419,8 @@ public class GridCacheWriteBehindStore<K, V> implements CacheStore<K, V>, Lifecy
     /** {@inheritDoc} */
     @Override public Map<K, V> loadAll(Iterable<? extends K> keys) {
         if (log.isDebugEnabled())
-            log.debug("Store load all [keys=" + keys + ']');
+            log.debug(S.toString("Store load all",
+                "keys", keys, true));
 
         Map<K, V> loaded = new HashMap<>();
 
@@ -468,7 +469,8 @@ public class GridCacheWriteBehindStore<K, V> implements CacheStore<K, V>, Lifecy
     /** {@inheritDoc} */
     @Override public V load(K key) {
         if (log.isDebugEnabled())
-            log.debug("Store load [key=" + key + ']');
+            log.debug(S.toString("Store load",
+                "key", key, true));
 
         StatefulValue<K, V> val;
 
@@ -510,7 +512,9 @@ public class GridCacheWriteBehindStore<K, V> implements CacheStore<K, V>, Lifecy
     @Override public void write(Entry<? extends K, ? extends V> entry) {
         try {
             if (log.isDebugEnabled())
-                log.debug("Store put [key=" + entry.getKey() + ", val=" + entry.getValue() + ']');
+                log.debug(S.toString("Store put",
+                    "key", entry.getKey(), true,
+                    "val", entry.getValue(), true));
 
             updateCache(entry.getKey(), entry, StoreOperation.PUT);
         }
@@ -530,7 +534,8 @@ public class GridCacheWriteBehindStore<K, V> implements CacheStore<K, V>, Lifecy
     @Override public void delete(Object key) {
         try {
             if (log.isDebugEnabled())
-                log.debug("Store remove [key=" + key + ']');
+                log.debug(S.toString("Store remove",
+                    "key", key, true));
 
             updateCache((K)key, null, StoreOperation.RMV);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxDeadlock.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxDeadlock.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxDeadlock.java
index a613184..54fc9b3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxDeadlock.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxDeadlock.java
@@ -21,11 +21,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
-import org.apache.ignite.internal.processors.cache.CacheObjectContext;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 
 /**
@@ -139,9 +139,12 @@ public class TxDeadlock {
                 Object val = txKey.key().value(cctx.cacheObjectContext(), true);
 
                 sb.append(e.getValue())
-                    .append(" [key=")
-                    .append(val)
-                    .append(", cache=")
+                    .append(" [");
+                if (S.INCLUDE_SENSITIVE)
+                    sb.append("key=")
+                        .append(val)
+                        .append(", ");
+                sb.append("cache=")
                     .append(cctx.name())
                     .append("]\n");
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceProcessor.java
index 1303f72..345bf34 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceProcessor.java
@@ -36,6 +36,7 @@ import org.apache.ignite.internal.GridTaskSessionImpl;
 import org.apache.ignite.internal.managers.deployment.GridDeployment;
 import org.apache.ignite.internal.processors.GridProcessorAdapter;
 import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.lifecycle.LifecycleBean;
 import org.apache.ignite.services.Service;
 import org.apache.ignite.spi.IgniteSpi;
@@ -153,7 +154,7 @@ public class GridResourceProcessor extends GridProcessorAdapter {
         assert target != null;
 
         if (log.isDebugEnabled())
-            log.debug("Injecting resources: " + target);
+            log.debug(S.toString("Injecting resources", "target", target, true));
 
         // Unwrap Proxy object.
         target = unwrapTarget(target);
@@ -239,7 +240,7 @@ public class GridResourceProcessor extends GridProcessorAdapter {
         assert obj != null;
 
         if (log.isDebugEnabled())
-            log.debug("Injecting resources: " + obj);
+            log.debug(S.toString("Injecting resources", "obj", obj, true));
 
         // Unwrap Proxy object.
         obj = unwrapTarget(obj);
@@ -388,7 +389,7 @@ public class GridResourceProcessor extends GridProcessorAdapter {
     public void inject(GridDeployment dep, Class<?> taskCls, ComputeJob job, ComputeTaskSession ses,
         GridJobContextImpl jobCtx) throws IgniteCheckedException {
         if (log.isDebugEnabled())
-            log.debug("Injecting resources: " + job);
+            log.debug(S.toString("Injecting resources", "job", job, true));
 
         // Unwrap Proxy object.
         Object obj = unwrapTarget(job);
@@ -432,7 +433,7 @@ public class GridResourceProcessor extends GridProcessorAdapter {
     public void inject(GridDeployment dep, ComputeTask<?, ?> task, GridTaskSessionImpl ses,
         ComputeLoadBalancer balancer, ComputeTaskContinuousMapper mapper) throws IgniteCheckedException {
         if (log.isDebugEnabled())
-            log.debug("Injecting resources: " + task);
+            log.debug(S.toString("Injecting resources", "task", task, true));
 
         // Unwrap Proxy object.
         Object obj = unwrapTarget(task);

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java
index 62224f0..5a1bfdb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java
@@ -1123,7 +1123,9 @@ class GridTaskWorker<T, R> extends GridWorker implements GridTimeoutObject {
             }
 
             if (log.isDebugEnabled())
-                log.debug("Reduced job responses [reduceRes=" + reduceRes + ", ses=" + ses + ']');
+                log.debug(S.toString("Reduced job responses",
+                    "reduceRes", reduceRes, true,
+                    "ses", ses, false));
 
             recordTaskEvent(EVT_TASK_REDUCED, "Task reduced.");
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java
index cffac65..0c49b51 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java
@@ -153,6 +153,89 @@ public class GridToStringBuilder {
      * @param val3 Additional parameter value.
      * @param name4 Additional parameter name.
      * @param val4 Additional parameter value.
+     * @param name5 Additional parameter name.
+     * @param val5 Additional parameter value.
+     * @return String presentation of the given object.
+     */
+    public static <T> String toString(Class<T> cls, T obj,
+        String name0, Object val0,
+        String name1, Object val1,
+        String name2, Object val2,
+        String name3, Object val3,
+        String name4, Object val4,
+        String name5, Object val5) {
+        return toString(cls,
+            obj,
+            name0, val0, false,
+            name1, val1, false,
+            name2, val2, false,
+            name3, val3, false,
+            name4, val4, false,
+            name5, val5, false);
+    }
+
+    /**
+     * Produces auto-generated output of string presentation for given object and its declaration class.
+     *
+     * @param <T> Type of the object.
+     * @param cls Declaration class of the object. Note that this should not be a runtime class.
+     * @param obj Object to get a string presentation for.
+     * @param name0 Additional parameter name.
+     * @param val0 Additional parameter value.
+     * @param name1 Additional parameter name.
+     * @param val1 Additional parameter value.
+     * @param name2 Additional parameter name.
+     * @param val2 Additional parameter value.
+     * @param name3 Additional parameter name.
+     * @param val3 Additional parameter value.
+     * @param name4 Additional parameter name.
+     * @param val4 Additional parameter value.
+     * @param name5 Additional parameter name.
+     * @param val5 Additional parameter value.
+     * @param name6 Additional parameter name.
+     * @param val6 Additional parameter value.
+     * @return String presentation of the given object.
+     */
+    public static <T> String toString(Class<T> cls, T obj,
+        String name0, Object val0,
+        String name1, Object val1,
+        String name2, Object val2,
+        String name3, Object val3,
+        String name4, Object val4,
+        String name5, Object val5,
+        String name6, Object val6) {
+        return toString(cls,
+            obj,
+            name0, val0, false,
+            name1, val1, false,
+            name2, val2, false,
+            name3, val3, false,
+            name4, val4, false,
+            name5, val5, false,
+            name6, val6, false);
+    }
+
+    /**
+     * Produces auto-generated output of string presentation for given object and its declaration class.
+     *
+     * @param <T> Type of the object.
+     * @param cls Declaration class of the object. Note that this should not be a runtime class.
+     * @param obj Object to get a string presentation for.
+     * @param name0 Additional parameter name.
+     * @param val0 Additional parameter value.
+     * @param sens0 Property sensitive flag.
+     * @param name1 Additional parameter name.
+     * @param val1 Additional parameter value.
+     * @param sens1 Property sensitive flag.
+     * @param name2 Additional parameter name.
+     * @param val2 Additional parameter value.
+     * @param sens2 Property sensitive flag.
+     * @param name3 Additional parameter name.
+     * @param val3 Additional parameter value.
+     * @param sens3 Property sensitive flag.
+     * @param name4 Additional parameter name.
+     * @param val4 Additional parameter value.
+     * @param sens4 Property sensitive flag.
      * @return String presentation of the given object.
      */
     public static <T> String toString(Class<T> cls, T obj,
@@ -214,6 +297,178 @@ public class GridToStringBuilder {
      * @param obj Object to get a string presentation for.
      * @param name0 Additional parameter name.
      * @param val0 Additional parameter value.
+     * @param sens0 Property sensitive flag.
+     * @param name1 Additional parameter name.
+     * @param val1 Additional parameter value.
+     * @param sens1 Property sensitive flag.
+     * @param name2 Additional parameter name.
+     * @param val2 Additional parameter value.
+     * @param sens2 Property sensitive flag.
+     * @param name3 Additional parameter name.
+     * @param val3 Additional parameter value.
+     * @param sens3 Property sensitive flag.
+     * @param name4 Additional parameter name.
+     * @param val4 Additional parameter value.
+     * @param sens4 Property sensitive flag.
+     * @param name5 Additional parameter name.
+     * @param val5 Additional parameter value.
+     * @param sens5 Property sensitive flag.
+     * @return String presentation of the given object.
+     */
+    public static <T> String toString(Class<T> cls, T obj,
+        String name0, Object val0, boolean sens0,
+        String name1, Object val1, boolean sens1,
+        String name2, Object val2, boolean sens2,
+        String name3, Object val3, boolean sens3,
+        String name4, Object val4, boolean sens4,
+        String name5, Object val5, boolean sens5) {
+        assert cls != null;
+        assert obj != null;
+        assert name0 != null;
+        assert name1 != null;
+        assert name2 != null;
+        assert name3 != null;
+        assert name4 != null;
+        assert name5 != null;
+
+        Queue<GridToStringThreadLocal> queue = threadCache.get();
+
+        assert queue != null;
+
+        // Since string() methods can be chain-called from the same thread we
+        // have to keep a list of thread-local objects and remove/add them
+        // in each string() apply.
+        GridToStringThreadLocal tmp = queue.isEmpty() ? new GridToStringThreadLocal() : queue.remove();
+
+        Object[] addNames = tmp.getAdditionalNames();
+        Object[] addVals = tmp.getAdditionalValues();
+        boolean[] addSens = tmp.getAdditionalSensitives();
+
+        addNames[0] = name0;
+        addVals[0] = val0;
+        addSens[0] = sens0;
+        addNames[1] = name1;
+        addVals[1] = val1;
+        addSens[1] = sens1;
+        addNames[2] = name2;
+        addVals[2] = val2;
+        addSens[2] = sens2;
+        addNames[3] = name3;
+        addVals[3] = val3;
+        addSens[3] = sens3;
+        addNames[4] = name4;
+        addVals[4] = val4;
+        addSens[4] = sens4;
+        addNames[5] = name5;
+        addVals[5] = val5;
+        addSens[5] = sens5;
+
+        try {
+            return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 6);
+        }
+        finally {
+            queue.offer(tmp);
+        }
+    }
+
+    /**
+     * Produces auto-generated output of string presentation for given object and its declaration class.
+     *
+     * @param <T> Type of the object.
+     * @param cls Declaration class of the object. Note that this should not be a runtime class.
+     * @param obj Object to get a string presentation for.
+     * @param name0 Additional parameter name.
+     * @param val0 Additional parameter value.
+     * @param sens0 Property sensitive flag.
+     * @param name1 Additional parameter name.
+     * @param val1 Additional parameter value.
+     * @param sens1 Property sensitive flag.
+     * @param name2 Additional parameter name.
+     * @param val2 Additional parameter value.
+     * @param sens2 Property sensitive flag.
+     * @param name3 Additional parameter name.
+     * @param val3 Additional parameter value.
+     * @param sens3 Property sensitive flag.
+     * @param name4 Additional parameter name.
+     * @param val4 Additional parameter value.
+     * @param sens4 Property sensitive flag.
+     * @param name5 Additional parameter name.
+     * @param val5 Additional parameter value.
+     * @param sens5 Property sensitive flag.
+     * @param name6 Additional parameter name.
+     * @param val6 Additional parameter value.
+     * @param sens6 Property sensitive flag.
+     * @return String presentation of the given object.
+     */
+    public static <T> String toString(Class<T> cls, T obj,
+        String name0, Object val0, boolean sens0,
+        String name1, Object val1, boolean sens1,
+        String name2, Object val2, boolean sens2,
+        String name3, Object val3, boolean sens3,
+        String name4, Object val4, boolean sens4,
+        String name5, Object val5, boolean sens5,
+        String name6, Object val6, boolean sens6) {
+        assert cls != null;
+        assert obj != null;
+        assert name0 != null;
+        assert name1 != null;
+        assert name2 != null;
+        assert name3 != null;
+        assert name4 != null;
+        assert name5 != null;
+        assert name6 != null;
+
+        Queue<GridToStringThreadLocal> queue = threadCache.get();
+
+        assert queue != null;
+
+        // Since string() methods can be chain-called from the same thread we
+        // have to keep a list of thread-local objects and remove/add them
+        // in each string() apply.
+        GridToStringThreadLocal tmp = queue.isEmpty() ? new GridToStringThreadLocal() : queue.remove();
+
+        Object[] addNames = tmp.getAdditionalNames();
+        Object[] addVals = tmp.getAdditionalValues();
+        boolean[] addSens = tmp.getAdditionalSensitives();
+
+        addNames[0] = name0;
+        addVals[0] = val0;
+        addSens[0] = sens0;
+        addNames[1] = name1;
+        addVals[1] = val1;
+        addSens[1] = sens1;
+        addNames[2] = name2;
+        addVals[2] = val2;
+        addSens[2] = sens2;
+        addNames[3] = name3;
+        addVals[3] = val3;
+        addSens[3] = sens3;
+        addNames[4] = name4;
+        addVals[4] = val4;
+        addSens[4] = sens4;
+        addNames[5] = name5;
+        addVals[5] = val5;
+        addSens[5] = sens5;
+        addNames[6] = name6;
+        addVals[6] = val6;
+        addSens[6] = sens6;
+
+        try {
+            return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 7);
+        }
+        finally {
+            queue.offer(tmp);
+        }
+    }
+
+    /**
+     * Produces auto-generated output of string presentation for given object and its declaration class.
+     *
+     * @param <T> Type of the object.
+     * @param cls Declaration class of the object. Note that this should not be a runtime class.
+     * @param obj Object to get a string presentation for.
+     * @param name0 Additional parameter name.
+     * @param val0 Additional parameter value.
      * @param name1 Additional parameter name.
      * @param val1 Additional parameter value.
      * @param name2 Additional parameter name.
@@ -977,6 +1232,170 @@ public class GridToStringBuilder {
     }
 
     /**
+     * Produces uniformed output of string with context properties
+     *
+     * @param str Output prefix or {@code null} if empty.
+     * @param name0 Property name.
+     * @param val0 Property value.
+     * @param sens0 Property sensitive flag.
+     * @param name1 Property name.
+     * @param val1 Property value.
+     * @param sens1 Property sensitive flag.
+     * @param name2 Property name.
+     * @param val2 Property value.
+     * @param sens2 Property sensitive flag.
+     * @param name3 Property name.
+     * @param val3 Property value.
+     * @param sens3 Property sensitive flag.
+     * @param name4 Property name.
+     * @param val4 Property value.
+     * @param sens4 Property sensitive flag.
+     * @param name5 Property name.
+     * @param val5 Property value.
+     * @param sens5 Property sensitive flag.
+     * @return String presentation.
+     */
+    public static String toString(String str,
+        String name0, @Nullable Object val0, boolean sens0,
+        String name1, @Nullable Object val1, boolean sens1,
+        String name2, @Nullable Object val2, boolean sens2,
+        String name3, @Nullable Object val3, boolean sens3,
+        String name4, @Nullable Object val4, boolean sens4,
+        String name5, @Nullable Object val5, boolean sens5) {
+        assert name0 != null;
+        assert name1 != null;
+        assert name2 != null;
+        assert name3 != null;
+        assert name4 != null;
+        assert name5 != null;
+
+        Queue<GridToStringThreadLocal> queue = threadCache.get();
+
+        assert queue != null;
+
+        // Since string() methods can be chain-called from the same thread we
+        // have to keep a list of thread-local objects and remove/add them
+        // in each string() apply.
+        GridToStringThreadLocal tmp = queue.isEmpty() ? new GridToStringThreadLocal() : queue.remove();
+
+        Object[] propNames = tmp.getAdditionalNames();
+        Object[] propVals = tmp.getAdditionalValues();
+        boolean[] propSens = tmp.getAdditionalSensitives();
+
+        propNames[0] = name0;
+        propVals[0] = val0;
+        propSens[0] = sens0;
+        propNames[1] = name1;
+        propVals[1] = val1;
+        propSens[1] = sens1;
+        propNames[2] = name2;
+        propVals[2] = val2;
+        propSens[2] = sens2;
+        propNames[3] = name3;
+        propVals[3] = val3;
+        propSens[3] = sens3;
+        propNames[4] = name4;
+        propVals[4] = val4;
+        propSens[4] = sens4;
+        propNames[5] = name5;
+        propVals[5] = val5;
+        propSens[5] = sens5;
+
+        try {
+            return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 6);
+        }
+        finally {
+            queue.offer(tmp);
+        }
+    }
+
+    /**
+     * Produces uniformed output of string with context properties
+     *
+     * @param str Output prefix or {@code null} if empty.
+     * @param name0 Property name.
+     * @param val0 Property value.
+     * @param sens0 Property sensitive flag.
+     * @param name1 Property name.
+     * @param val1 Property value.
+     * @param sens1 Property sensitive flag.
+     * @param name2 Property name.
+     * @param val2 Property value.
+     * @param sens2 Property sensitive flag.
+     * @param name3 Property name.
+     * @param val3 Property value.
+     * @param sens3 Property sensitive flag.
+     * @param name4 Property name.
+     * @param val4 Property value.
+     * @param sens4 Property sensitive flag.
+     * @param name5 Property name.
+     * @param val5 Property value.
+     * @param sens5 Property sensitive flag.
+     * @param name6 Property name.
+     * @param val6 Property value.
+     * @param sens6 Property sensitive flag.
+     * @return String presentation.
+     */
+    public static String toString(String str,
+        String name0, @Nullable Object val0, boolean sens0,
+        String name1, @Nullable Object val1, boolean sens1,
+        String name2, @Nullable Object val2, boolean sens2,
+        String name3, @Nullable Object val3, boolean sens3,
+        String name4, @Nullable Object val4, boolean sens4,
+        String name5, @Nullable Object val5, boolean sens5,
+        String name6, @Nullable Object val6, boolean sens6) {
+        assert name0 != null;
+        assert name1 != null;
+        assert name2 != null;
+        assert name3 != null;
+        assert name4 != null;
+        assert name5 != null;
+        assert name6 != null;
+
+        Queue<GridToStringThreadLocal> queue = threadCache.get();
+
+        assert queue != null;
+
+        // Since string() methods can be chain-called from the same thread we
+        // have to keep a list of thread-local objects and remove/add them
+        // in each string() apply.
+        GridToStringThreadLocal tmp = queue.isEmpty() ? new GridToStringThreadLocal() : queue.remove();
+
+        Object[] propNames = tmp.getAdditionalNames();
+        Object[] propVals = tmp.getAdditionalValues();
+        boolean[] propSens = tmp.getAdditionalSensitives();
+
+        propNames[0] = name0;
+        propVals[0] = val0;
+        propSens[0] = sens0;
+        propNames[1] = name1;
+        propVals[1] = val1;
+        propSens[1] = sens1;
+        propNames[2] = name2;
+        propVals[2] = val2;
+        propSens[2] = sens2;
+        propNames[3] = name3;
+        propVals[3] = val3;
+        propSens[3] = sens3;
+        propNames[4] = name4;
+        propVals[4] = val4;
+        propSens[4] = sens4;
+        propNames[5] = name5;
+        propVals[5] = val5;
+        propSens[5] = sens5;
+        propNames[6] = name6;
+        propVals[6] = val6;
+        propSens[6] = sens6;
+
+        try {
+            return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 7);
+        }
+        finally {
+            queue.offer(tmp);
+        }
+    }
+
+    /**
      * Creates an uniformed string presentation for the binary-like object.
      *
      * @param str Output prefix or {@code null} if empty.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java
index 33fc6a0..8ffacb3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java
@@ -27,13 +27,13 @@ class GridToStringThreadLocal {
     private SB sb = new SB(256);
 
     /** */
-    private Object[] addNames = new Object[5];
+    private Object[] addNames = new Object[7];
 
     /** */
-    private Object[] addVals = new Object[5];
+    private Object[] addVals = new Object[7];
 
     /** */
-    private boolean[] addSens = new boolean[5];
+    private boolean[] addSens = new boolean[7];
 
     /**
      * @return String builder.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy.java b/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy.java
new file mode 100644
index 0000000..89d3ce0
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy.java
@@ -0,0 +1,493 @@
+/*
+ * 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.BufferedReader;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.InvalidObjectException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.ObjectStreamException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.IgniteSystemProperties;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.apache.ignite.lifecycle.LifecycleAware;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_LOG_GRID_NAME;
+
+/**
+ *
+ */
+public class SensitiveInfoTestLoggerProxy implements IgniteLogger, LifecycleAware, Externalizable {
+    /**
+     * If this system property is present the Ignite will test all strings passed into log.
+     * It's a special mode for testing purposes. All debug information will be generated,
+     * but only suspicious will be written into log with "error" level and special prefix SENSITIVE>
+     */
+    public static final String IGNITE_LOG_TEST_SENSITIVE = "IGNITE_LOG_TEST_SENSITIVE";
+
+    /** Unique number for key. */
+    public static final long SENSITIVE_KEY_MARKER = UUID.randomUUID().getLeastSignificantBits() | (1L << 63) & ~(0xFFL);
+
+    /** Unique string sequence for value. */
+    public static final String SENSITIVE_VAL_MARKER = UUID.randomUUID().toString();
+
+    /** String prefix of unique number for key. */
+    private static final String SENSITIVE_KEY_MARKER_PREFIX;
+
+    /** Indicating whether sensitive marker assertions enabled. */
+    private static final AtomicBoolean ENABLE_SENSITIVE_MARKER_ASSERTIONS = new AtomicBoolean();
+
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Whether or not to log grid name. */
+    private static final boolean logGridName = System.getProperty(IGNITE_LOG_GRID_NAME) != null;
+
+    /** Test sensitive mode. */
+    public static final boolean TEST_SENSITIVE = true;//System.getProperty(IGNITE_LOG_TEST_SENSITIVE) != null;
+
+    /** Prefix for all suspicious sensitive data. */
+    private static final String SENSITIVE_PREFIX = "SENSITIVE> ";
+
+    /** Sensitive patterns: excluding. */
+    private static final Pattern[] EXCLUDE_PATTERNS;
+
+    /** Sensitive patterns: including. */
+    private static final Pattern[] INCLUDE_PATTERNS;
+
+    /** Excluding logger categories */
+    private static final Pattern EXCLUDE_CATEGORY_P = Pattern.compile("Test(Task|Job)?($|\\$)|\\.tests?\\.");
+
+    /** */
+    private static ThreadLocal<IgniteBiTuple<String, Object>> stash = new ThreadLocal<IgniteBiTuple<String, Object>>() {
+        @Override protected IgniteBiTuple<String, Object> initialValue() {
+            return new IgniteBiTuple<>();
+        }
+    };
+
+    /** */
+    private static ThreadLocal<StringBuilder> sbLoc = new ThreadLocal<StringBuilder>() {
+        @Override protected StringBuilder initialValue() {
+            return new StringBuilder(SENSITIVE_PREFIX);
+        }
+    };
+
+    static {
+        String prefix = Long.toString(SENSITIVE_KEY_MARKER);
+        SENSITIVE_KEY_MARKER_PREFIX = prefix.substring(0, prefix.length() - 3);
+    }
+
+    static {
+        EXCLUDE_PATTERNS = readFromResource("_Exclude.txt");
+        INCLUDE_PATTERNS = readFromResource("_Include.txt");
+    }
+
+    /** */
+    @GridToStringInclude
+    private IgniteLogger impl;
+    /** */
+    private String gridName;
+    /** */
+    private String id8;
+    /** */
+    @GridToStringInclude
+    private Object ctgr;
+
+    /** Whether testing sensitive is enabled for the logger */
+    private boolean testSensitive;
+    /**
+     * No-arg constructor is required by externalization.
+     */
+    public SensitiveInfoTestLoggerProxy() {
+        // No-op.
+    }
+
+    /**
+     * @param impl Logger implementation to proxy to.
+     * @param ctgr Optional logger category.
+     * @param gridName Grid name (can be {@code null} for default grid).
+     * @param id8 Node ID.
+     */
+    @SuppressWarnings({"IfMayBeConditional", "SimplifiableIfStatement"})
+    public SensitiveInfoTestLoggerProxy(IgniteLogger impl,
+        @Nullable Object ctgr,
+        @Nullable String gridName,
+        String id8) {
+        assert impl != null;
+
+        this.impl = impl;
+        this.ctgr = ctgr;
+        this.gridName = gridName;
+        this.id8 = id8;
+        this.testSensitive = TEST_SENSITIVE && (ctgr == null || !EXCLUDE_CATEGORY_P.matcher(ctgr.toString()).find());
+
+        if (TEST_SENSITIVE && ctgr == null && gridName == null && id8 == null)
+            impl.warning("Test sensitive mode is enabled");
+    }
+
+    /**
+     * Sets sensitive marker assertions flag.
+     *
+     * @param enable Flag value.
+     */
+    public static void enableSensitiveMarkerAssertions(boolean enable) {
+        ENABLE_SENSITIVE_MARKER_ASSERTIONS.set(enable);
+    }
+
+    /**
+     * Reads sensitive patterns from resource.
+     *
+     * @param suffix File name suffix.
+     * @return Read patterns.
+     */
+    private static Pattern[] readFromResource(String suffix) {
+        ArrayList<Pattern> lst = new ArrayList<>();
+
+        final Class<SensitiveInfoTestLoggerProxy> cls = SensitiveInfoTestLoggerProxy.class;
+
+        String resPath = cls.getSimpleName() + suffix;
+
+        try (InputStream inStr = cls.getResourceAsStream(resPath);
+             BufferedReader rdr = new BufferedReader(new InputStreamReader(inStr))) {
+            String ln;
+            boolean skipComment = false;
+
+            while ((ln = rdr.readLine()) != null) {
+                ln = ln.trim();
+
+                if (ln.isEmpty())
+                    continue;
+
+                if (ln.startsWith("/*")) {
+                    skipComment = true;
+                    continue;
+                }
+
+                if (ln.endsWith("*/")) {
+                    skipComment = false;
+                    continue;
+                }
+
+                if (skipComment)
+                    continue;
+
+                lst.add(Pattern.compile(ln));
+            }
+        }
+        catch (Exception ex) {
+            System.err.println("Error loading sensitive patterns from resource " + resPath + ": " + ex);
+
+            ex.printStackTrace();
+        }
+
+        return lst.toArray(new Pattern[lst.size()]);
+    }
+
+    /**
+     * @return Whether testing sensitive is enabled for the logger.
+     */
+    private boolean testSensitiveEnabled() {
+        return testSensitive || ENABLE_SENSITIVE_MARKER_ASSERTIONS.get();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void start() {
+        if (impl instanceof LifecycleAware)
+            ((LifecycleAware)impl).start();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void stop() {
+        U.stopLifecycleAware(this, Collections.singleton(impl));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteLogger getLogger(Object ctgr) {
+        assert ctgr != null;
+
+        return new SensitiveInfoTestLoggerProxy(impl.getLogger(ctgr), ctgr, gridName, id8);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public String fileName() {
+        return impl.fileName();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void trace(String msg) {
+        if (testSensitiveEnabled()) {
+            testSensitive(msg);
+
+            if (impl.isTraceEnabled())
+                impl.trace(enrich(msg));
+        }
+        else
+            impl.trace(enrich(msg));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void debug(String msg) {
+        if (testSensitiveEnabled()) {
+            testSensitive(msg);
+
+            if (impl.isDebugEnabled())
+                impl.debug(enrich(msg));
+        }
+        else
+            impl.debug(enrich(msg));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void info(String msg) {
+        if (testSensitiveEnabled()) {
+            testSensitive(msg);
+
+            if (impl.isInfoEnabled())
+                impl.info(enrich(msg));
+        }
+        else
+            impl.info(enrich(msg));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void warning(String msg) {
+        if (testSensitiveEnabled())
+            testSensitive(msg);
+
+        impl.warning(enrich(msg));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void warning(String msg, Throwable e) {
+        if (testSensitiveEnabled())
+            testSensitive(msg, e);
+
+        impl.warning(enrich(msg), e);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void error(String msg) {
+        if (testSensitiveEnabled())
+            testSensitive(msg);
+
+        impl.error(enrich(msg));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void error(String msg, Throwable e) {
+        if (testSensitiveEnabled())
+            testSensitive(msg, e);
+
+        impl.error(enrich(msg), e);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isTraceEnabled() {
+        return testSensitiveEnabled() || impl.isTraceEnabled();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDebugEnabled() {
+        return testSensitiveEnabled() || impl.isDebugEnabled();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isInfoEnabled() {
+        return testSensitiveEnabled() || impl.isInfoEnabled();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isQuiet() {
+        return !testSensitiveEnabled() && impl.isQuiet();
+    }
+
+    /**
+     * Enriches the log message with grid name if {@link IgniteSystemProperties#IGNITE_LOG_GRID_NAME}
+     * system property is set.
+     *
+     * @param m Message to enrich.
+     * @return Enriched message or the original one.
+     */
+    private String enrich(@Nullable String m) {
+        return logGridName && m != null ? "<" + gridName + '-' + id8 + "> " + m : m;
+    }
+
+    /**
+     * Testing the message by sensitive patterns.<br>
+     * All sensitive data will be logged with {@link #SENSITIVE_PREFIX}
+     *
+     * @param m Log message.
+     */
+    private void testSensitive(String m) {
+        String f = findSensitive(m);
+
+        if (f != null)
+            logSensitive(f, m);
+    }
+
+    /**
+     * Testing the message and exceptions chain by sensitive patterns.<br>
+     * All sensitive data will be logged with {@link #SENSITIVE_PREFIX}
+     *
+     * @param m Log message.
+     * @param e Log error.
+     */
+    private void testSensitive(String m, Throwable e) {
+        String f = findSensitive(m);
+
+        if (f != null)
+            logSensitive(f, m, e);
+
+        while (e != null) {
+            f = findSensitive(e.getMessage());
+
+            if (f != null)
+                logSensitive(f, m, e);
+
+            e = e.getCause();
+        }
+    }
+
+    /**
+     * Check the message by sensitive patterns
+     *
+     * @param msg Log message.
+     * @return Matching string was found or {@code null} if not match.
+     */
+    private String findSensitive(String msg) {
+        if (msg == null || msg.isEmpty())
+            return null;
+
+        if (ENABLE_SENSITIVE_MARKER_ASSERTIONS.get() &&
+            msg.contains(SENSITIVE_KEY_MARKER_PREFIX) || msg.contains(SENSITIVE_VAL_MARKER)) {
+
+            logSensitive("<MARKER>", msg);
+
+            msg = msg.replace(SENSITIVE_KEY_MARKER_PREFIX, "<SENSITIVE_KEY_MARKER>").
+                replace(SENSITIVE_VAL_MARKER, "<SENSITIVE_VAL_MARKER>");
+
+            throw new AssertionError("Found sensitive marker: " + msg);
+        }
+
+        for (Pattern p : EXCLUDE_PATTERNS) {
+            Matcher m = p.matcher(msg);
+
+            if (m.find())
+                return null;
+        }
+
+        for (Pattern p : INCLUDE_PATTERNS) {
+            Matcher m = p.matcher(msg);
+
+            if (m.find())
+                return m.group();
+        }
+
+        return null;
+    }
+
+    /**
+     * Logging the message with {@link #SENSITIVE_PREFIX}.
+     *
+     * @param f Found problem message.
+     * @param m Logged message.
+     */
+    private void logSensitive(String f, String m) {
+        logSensitive(f, m, null);
+    }
+
+    /**
+     * Logging the message and the exception with {@link #SENSITIVE_PREFIX}.
+     *
+     * @param f Found problem message.
+     * @param m Logged message.
+     * @param e Logged exception.
+     */
+    private void logSensitive(String f, String m, Throwable e) {
+        StringBuilder sb = sbLoc.get();
+
+        sb.setLength(SENSITIVE_PREFIX.length());
+
+        sb.append("Found: ").append(f).
+            append(", category = ").append(ctgr).
+            append(", message:\n").append(m);
+
+        if (e != null)
+            sb.append("exception:\n").append(e.getClass()).append(": ").append(e.getMessage());
+
+        impl.error(sb.toString());
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        U.writeString(out, gridName);
+        out.writeObject(ctgr);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        IgniteBiTuple<String, Object> t = stash.get();
+
+        t.set1(U.readString(in));
+        t.set2(in.readObject());
+    }
+
+    /**
+     * Reconstructs object on unmarshalling.
+     *
+     * @return Reconstructed object.
+     * @throws ObjectStreamException Thrown in case of unmarshalling error.
+     */
+    protected Object readResolve() throws ObjectStreamException {
+        try {
+            IgniteBiTuple<String, Object> t = stash.get();
+
+            Object ctgrR = t.get2();
+
+            IgniteLogger log = IgnitionEx.localIgnite().log();
+
+            return ctgrR != null ? log.getLogger(ctgrR) : log;
+        }
+        catch (IllegalStateException e) {
+            throw U.withCause(new InvalidObjectException(e.getMessage()), e);
+        }
+        finally {
+            stash.remove();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(SensitiveInfoTestLoggerProxy.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy_Exclude.txt
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy_Exclude.txt b/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy_Exclude.txt
new file mode 100644
index 0000000..1672ab1
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy_Exclude.txt
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+^Received response to join request \[addr=
+\[(msg(Id)?|job)=.+,\s*res=\d+\]$
+GC server mode is not enabled, this could lead to less than optimal performance on multi-core machines

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy_Include.txt
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy_Include.txt b/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy_Include.txt
new file mode 100644
index 0000000..842efdb
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy_Include.txt
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+(^|[^\.-])\b(k|keys?|v|vals?|(new|old|merge|loc)Vals?|rows?|fields?|params?|args?|items?|elements?|data|obj|res|result|clause|query|qry|sqlQry|ordinal|entrySet|keys?Set|vals?Set)\b\s*=\s*(?!\{?[\w-\.\$]*\s*[\[@])(?!null\b|true\b|false\b|BinaryEnum\b|class\s|\?\s).+?($|[,\[\]])
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveAtomicTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveAtomicTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveAtomicTest.java
new file mode 100644
index 0000000..145c923
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveAtomicTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.util.tostring;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+
+/**
+ *
+ */
+public class IncludeSensitiveAtomicTest extends IncludeSensitiveTest {
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicityMode atomicityMode() {
+        return CacheAtomicityMode.ATOMIC;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveTest.java
new file mode 100644
index 0000000..7328350
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.util.tostring;
+
+import javax.cache.processor.MutableEntry;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteSystemProperties;
+import org.apache.ignite.cache.CacheEntryProcessor;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.SensitiveInfoTestLoggerProxy;
+import org.apache.ignite.internal.processors.cache.GridCacheAbstractSelfTest;
+
+/**
+ * Tests for property {@link IgniteSystemProperties#IGNITE_TO_STRING_INCLUDE_SENSITIVE}.
+ */
+public abstract class IncludeSensitiveTest extends GridCacheAbstractSelfTest {
+    /** Number of test entries */
+    private static final int ENTRY_CNT = 10;
+
+    /**
+     * @param i Index.
+     * @return Marked key by index.
+     */
+    private static Long key(int i) {
+        return SensitiveInfoTestLoggerProxy.SENSITIVE_KEY_MARKER + i;
+    }
+
+    /**
+     * @param i Index.
+     * @return Marked value by index.
+     */
+    private static String value(int i) {
+        return SensitiveInfoTestLoggerProxy.SENSITIVE_VAL_MARKER + i;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected int gridCount() {
+        return 3;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheConfiguration cacheConfiguration(IgniteConfiguration cfg, String cacheName) {
+        CacheConfiguration ccfg = super.cacheConfiguration(cfg, cacheName);
+
+        ccfg.setBackups(1);
+
+        return ccfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        System.setProperty(IgniteSystemProperties.IGNITE_TO_STRING_INCLUDE_SENSITIVE, "false");
+
+        SensitiveInfoTestLoggerProxy.enableSensitiveMarkerAssertions(true);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        System.clearProperty(IgniteSystemProperties.IGNITE_TO_STRING_INCLUDE_SENSITIVE);
+
+        SensitiveInfoTestLoggerProxy.enableSensitiveMarkerAssertions(false);
+
+        super.afterTestsStopped();
+    }
+
+    /** Start transaction. */
+    protected void startTx() {
+        // No-op.
+    }
+
+    /** Commit transaction. */
+    protected void commitTx() {
+        // No-op.
+    }
+
+    /**
+     * Tests basic cache operations.
+     *
+     * @throws Exception If failed.
+     */
+    public void test() throws Exception {
+        IgniteCache<Long, String> cache = grid(0).cache(DEFAULT_CACHE_NAME);
+
+        startTx();
+
+        for (int i = 1; i < ENTRY_CNT; ++i)
+            cache.put(key(i), value(i));
+
+        commitTx();
+
+        cache.get(key(ENTRY_CNT / 2));
+
+        for (int i = 1; i < ENTRY_CNT; ++i)
+            cache.invoke(key(i), new TestEntryProcessor());
+
+        stopGrid(1);
+
+        cache.rebalance().get();
+
+        for (int i = 0; i < ENTRY_CNT; ++i)
+            cache.get(key(i));
+
+        startGrid(1);
+
+        cache.rebalance().get();
+
+        startTx();
+
+        for (int i = 1; i < ENTRY_CNT; ++i)
+            cache.remove(key(i));
+
+        commitTx();
+    }
+
+    /**
+     *
+     */
+    static class TestEntryProcessor implements CacheEntryProcessor<Long, String, Object> {
+        /** {@inheritDoc} */
+        @Override public Object process(MutableEntry<Long, String> entry, Object... args) {
+            long key = entry.getKey();
+
+            if (key % 2 == 0)
+                entry.remove();
+            else
+                entry.setValue(entry.getValue() + "-");
+
+            return null;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveTransactionalTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveTransactionalTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveTransactionalTest.java
new file mode 100644
index 0000000..0327171
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/IncludeSensitiveTransactionalTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.util.tostring;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.transactions.Transaction;
+
+/**
+ *
+ */
+public class IncludeSensitiveTransactionalTest extends IncludeSensitiveTest {
+    /** Active transaction. */
+    private Transaction tx;
+
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicityMode atomicityMode() {
+        return CacheAtomicityMode.TRANSACTIONAL;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void startTx() {
+        tx = grid(0).transactions().txStart();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void commitTx() {
+        tx.commit();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b7d8d1b3/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java
index 2c7d597..2222274 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java
@@ -27,6 +27,7 @@ import javax.management.MBeanServer;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.SensitiveInfoTestLoggerProxy;
 import org.apache.ignite.internal.binary.BinaryCachingMetadataHandler;
 import org.apache.ignite.internal.binary.BinaryContext;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
@@ -74,9 +75,15 @@ public class IgniteTestResources {
     /** */
     private GridResourceProcessor rsrcProc;
 
-    /** */
+    /**
+     * @throws IgniteCheckedException If failed.
+     */
     public IgniteTestResources() throws IgniteCheckedException {
-        log = rootLog.getLogger(getClass());
+        if (SensitiveInfoTestLoggerProxy.TEST_SENSITIVE)
+            log = new SensitiveInfoTestLoggerProxy(rootLog.getLogger(getClass()), null, null, null);
+        else
+            log = rootLog.getLogger(getClass());
+
         nodeId = UUID.randomUUID();
         jmx = ManagementFactory.getPlatformMBeanServer();
         home = U.getIgniteHome();


[29/50] [abbrv] ignite git commit: IGNITE-5388 Added support to configuration of Ignite 2.x and Ignite 1.x.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/caches/memory.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/memory.pug b/modules/web-console/frontend/app/modules/states/configuration/caches/memory.pug
index 4ea9160..8264731 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/memory.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/memory.pug
@@ -23,23 +23,108 @@ include /app/helpers/jade/mixins
     .panel-heading(bs-collapse-toggle='' ng-click=`ui.loadPanel('${form}')`)
         ignite-form-panel-chevron
         label Memory
-        ignite-form-field-tooltip.tipLabel
+        ignite-form-field-tooltip.tipLabel(ng-show='$ctrl.available(["1.0.0", "2.0.0"])')
             | Cache memory settings#[br]
-            | #[a(href="https://apacheignite.readme.io/docs/off-heap-memory" target="_blank") More info]
+            | #[a(href="https://apacheignite.readme.io/v1.9/off-heap-memory" target="_blank") More info]
+        ignite-form-field-tooltip.tipLabel(ng-show='$ctrl.available("2.0.0")')
+            | Cache memory settings#[br]
+            | #[a(href="https://apacheignite.readme.io/docs/evictions" target="_blank") More info]
         ignite-form-revert
     .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
         .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
             .col-sm-6
+                //- Since ignite 2.0
+                div(ng-if='$ctrl.available("2.0.0")')
+                    .settings-row
+                        +checkbox('Onheap cache enabled', model + '.onheapCacheEnabled', '"OnheapCacheEnabled"', 'Checks if the on-heap cache is enabled for the off-heap based page memory')
+                    .settings-row
+                        +text('Memory policy name:', model + '.memoryPolicyName', '"MemoryPolicyName"', 'false', 'default',
+                            'Name of memory policy configuration for this cache')
+
+                //- Removed in ignite 2.0
+                div(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    .settings-row
+                        +dropdown('Mode:', `${model}.memoryMode`, '"memoryMode"', 'true', 'ONHEAP_TIERED',
+                            '[\
+                                {value: "ONHEAP_TIERED", label: "ONHEAP_TIERED"},\
+                                {value: "OFFHEAP_TIERED", label: "OFFHEAP_TIERED"},\
+                                {value: "OFFHEAP_VALUES", label: "OFFHEAP_VALUES"}\
+                            ]',
+                            'Memory modes control whether value is stored in on-heap memory, off-heap memory, or swap space\
+                            <ul>\
+                                <li>\
+                                    ONHEAP_TIERED - entries are cached on heap memory first<br/>\
+                                    <ul>\
+                                        <li>\
+                                            If offheap memory is enabled and eviction policy evicts an entry from heap memory, entry will be moved to offheap memory<br/>\
+                                            If offheap memory is disabled, then entry is simply discarded\
+                                        </li>\
+                                        <li>\
+                                            If swap space is enabled and offheap memory fills up, then entry will be evicted into swap space<br/>\
+                                            If swap space is disabled, then entry will be discarded. If swap is enabled and offheap memory is disabled, then entry will be evicted directly from heap memory into swap\
+                                        </li>\
+                                    </ul>\
+                                </li>\
+                                <li>\
+                                    OFFHEAP_TIERED - works the same as ONHEAP_TIERED, except that entries never end up in heap memory and get stored in offheap memory right away<br/>\
+                                    Entries get cached in offheap memory first and then get evicted to swap, if one is configured\
+                                </li>\
+                                <li>\
+                                    OFFHEAP_VALUES - entry keys will be stored on heap memory, and values will be stored in offheap memory<br/>\
+                                    Note that in this mode entries can be evicted only to swap\
+                                </li>\
+                            </ul>')
+                    .settings-row(ng-show=`${model}.memoryMode !== 'OFFHEAP_VALUES'`)
+                        +dropdown-required('Off-heap memory:', `${model}.offHeapMode`, '"offHeapMode"', 'true', `${model}.memoryMode === 'OFFHEAP_TIERED'`,
+                            'Disabled',
+                            '[\
+                                {value: -1, label: "Disabled"},\
+                                {value: 1, label: "Limited"},\
+                                {value: 0, label: "Unlimited"}\
+                            ]',
+                            'Off-heap storage mode\
+                            <ul>\
+                                <li>Disabled - Off-heap storage is disabled</li>\
+                                <li>Limited - Off-heap storage has limited size</li>\
+                                <li>Unlimited - Off-heap storage grow infinitely (it is up to user to properly add and remove entries from cache to ensure that off-heap storage does not grow infinitely)</li>\
+                            </ul>')
+                    .settings-row(ng-if=`${model}.offHeapMode === 1 && ${model}.memoryMode !== 'OFFHEAP_VALUES'`)
+                        +number-required('Off-heap memory max size:', `${model}.offHeapMaxMemory`, '"offHeapMaxMemory"', 'true',
+                            `${model}.offHeapMode === 1`, 'Enter off-heap memory size', '1',
+                            'Maximum amount of memory available to off-heap storage in bytes')
+
                 .settings-row
-                    +checkbox('On-heap cache enabled', `${model}.onheapCacheEnabled`, '"onheapCacheEnabled"', 'On-heap cache enabled flag')
-                .settings-row(ng-show=`${model}.onheapCacheEnabled`)
-                    +evictionPolicy(`${model}.evictionPolicy`, '"evictionPolicy"', 'true', 'false',
-                        'Cache eviction policy<br/>\
-                        Must be set for entries to be evicted to off-heap\
+                    -var onHeapTired = model + '.memoryMode === "ONHEAP_TIERED"'
+                    -var swapEnabled = model + '.swapEnabled'
+                    -var offHeapMaxMemory = model + '.offHeapMaxMemory'
+
+                    +evictionPolicy(`${model}.evictionPolicy`, '"evictionPolicy"', 'true',
+                        onHeapTired  + ' && (' + swapEnabled + '|| _.isNumber(' + offHeapMaxMemory + ') &&' + offHeapMaxMemory + ' >= 0)',
+                        'Optional cache eviction policy<br/>\
+                        Must be set for entries to be evicted from on-heap to off-heap or swap\
                         <ul>\
                             <li>Least Recently Used(LRU) - Eviction policy based on LRU algorithm and supports batch eviction</li>\
                             <li>First In First Out (FIFO) - Eviction policy based on FIFO algorithm and supports batch eviction</li>\
                             <li>SORTED - Eviction policy which will select the minimum cache entry for eviction</li>\
                         </ul>')
+
+                //- Since ignite 2.0
+                .settings-row(ng-if='$ctrl.available("2.0.0")')
+                    +java-class('Eviction filter:', model + '.evictionFilter', '"EvictionFilter"', 'true', 'false', 'Eviction filter to specify which entries should not be evicted')
+
+                //- Removed in ignite 2.0
+                div(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    .settings-row
+                        +number('Start size:', `${model}.startSize`, '"startSize"', 'true', '1500000', '0',
+                            'In terms of size and capacity, Ignite internal cache map acts exactly like a normal Java HashMap: it has some initial capacity\
+                            (which is pretty small by default), which doubles as data arrives. The process of internal cache map resizing is CPU-intensive\
+                            and time-consuming, and if you load a huge dataset into cache (which is a normal use case), the map will have to resize a lot of times.\
+                            To avoid that, you can specify the initial cache map capacity, comparable to the expected size of your dataset.\
+                            This will save a lot of CPU resources during the load time, because the map would not have to resize.\
+                            For example, if you expect to load 10 million entries into cache, you can set this property to 10 000 000.\
+                            This will save you from cache internal map resizes.')
+                    .settings-row
+                        +checkbox('Swap enabled', `${model}.swapEnabled`, '"swapEnabled"', 'Flag indicating whether swap storage is enabled or not for this cache')
+
             .col-sm-6
                 +preview-xml-java(model, 'cacheMemory')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/caches/node-filter.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/node-filter.pug b/modules/web-console/frontend/app/modules/states/configuration/caches/node-filter.pug
index 6715dcd..1b34b60 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/node-filter.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/node-filter.pug
@@ -18,6 +18,10 @@ include /app/helpers/jade/mixins
 
 -var form = 'nodeFilter'
 -var model = 'backupItem'
+-var nodeFilter = model + '.nodeFilter';
+-var nodeFilterKind = nodeFilter + '.kind';
+-var igfsFilter = nodeFilterKind + ' === "IGFS"'
+-var customFilter = nodeFilterKind + ' === "Custom"'
 
 .panel.panel-default(ng-form=form novalidate)
     .panel-heading(bs-collapse-toggle='' ng-click=`ui.loadPanel('${form}')`)
@@ -30,9 +34,6 @@ include /app/helpers/jade/mixins
         .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
             .col-sm-6
                 .settings-row
-                    -var nodeFilter = model + '.nodeFilter';
-                    -var nodeFilterKind = nodeFilter + '.kind';
-
                     +dropdown('Node filter:', nodeFilterKind, '"nodeFilter"', 'true', 'Not set',
                         '[\
                             {value: "IGFS", label: "IGFS nodes"},\
@@ -41,19 +42,11 @@ include /app/helpers/jade/mixins
                         ]',
                         'Node filter variant'
                     )
-                .settings-row(ng-show=nodeFilterKind)
-                    div(ng-show=`${nodeFilterKind} === 'IGFS'`)
-                        -var igfsNodeFilter = `${nodeFilter}.IGFS`
-                        -var required = `${nodeFilterKind} === 'IGFS'`
-
-                        //(lbl, model, name, enabled, required, placeholder, options, tip)
-                        +dropdown-required-empty('IGFS:', `${igfsNodeFilter}.igfs`, '"igfsNodeFilter"', 'true', required,
-                            'Choose IGFS', 'No IGFS configured', 'igfss', 'Select IGFS to filter nodes')
-                    div(ng-show=`${nodeFilterKind} === 'Custom'`)
-                        -var customNodeFilter = `${nodeFilter}.Custom`
-                        -var required = `${nodeFilterKind} === 'Custom'`
-
-                        +java-class('Class name:', `${customNodeFilter}.className`, '"customNodeFilter"',
-                            'true', required, 'Class name of custom node filter implementation', required)
+                .settings-row(ng-show=igfsFilter)
+                    +dropdown-required-empty('IGFS:', `${nodeFilter}.IGFS.igfs`, '"igfsNodeFilter"', 'true', igfsFilter,
+                        'Choose IGFS', 'No IGFS configured', 'igfss', 'Select IGFS to filter nodes')
+                .settings-row(ng-show=customFilter)
+                    +java-class('Class name:', `${nodeFilter}.Custom.className`, '"customNodeFilter"',
+                        'true', customFilter, 'Class name of custom node filter implementation', customFilter)
             .col-sm-6
                 +preview-xml-java(model, 'cacheNodeFilter', 'igfss')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/caches/query.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/query.pug b/modules/web-console/frontend/app/modules/states/configuration/caches/query.pug
index b3650e2..480b0a5 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/query.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/query.pug
@@ -46,6 +46,12 @@ include /app/helpers/jade/mixins
                                 SELECT * FROM Persons.Person p INNER JOIN Organizations.Organization o on p.org = o.id\
                             </li>\
                         </ul>')
+
+                //- Removed in ignite 2.0
+                .settings-row(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    +number('On-heap cache for off-heap indexes:', `${model}.sqlOnheapRowCacheSize`, '"sqlOnheapRowCacheSize"', 'true', '10240', '1',
+                        'Number of SQL rows which will be cached onheap to avoid deserialization on each SQL index access')
+
                 .settings-row
                     +number('Long query timeout:', `${model}.longQueryWarningTimeout`, '"longQueryWarningTimeout"', 'true', '3000', '0',
                         'Timeout in milliseconds after which long query warning will be printed')
@@ -53,9 +59,6 @@ include /app/helpers/jade/mixins
                     +number('History size:', `${model}.queryDetailMetricsSize`, '"queryDetailMetricsSize"', 'true', '0', '0',
                         'Size of queries detail metrics that will be stored in memory for monitoring purposes')
                 .settings-row
-                    +number('Parallelism:', `${model}.queryParallelism`, '"queryParallelism"', 'true', '1', '1',
-                        'Defines a hint to query execution engine on desired degree of parallelism within a single node.')
-                .settings-row
                     -var form = 'querySqlFunctionClasses';
                     -var sqlFunctionClasses = `${model}.sqlFunctionClasses`;
 
@@ -102,10 +105,26 @@ include /app/helpers/jade/mixins
 
                         .group-content-empty(ng-if=`!(${sqlFunctionClasses}.length) && !group.add.length`)
                             | Not defined
+
+                //- Removed in ignite 2.0
+                .settings-row(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    +checkbox('Snapshotable index', `${model}.snapshotableIndex`, '"snapshotableIndex"',
+                        'Flag indicating whether SQL indexes should support snapshots')
+
                 .settings-row
                     +checkbox('Escape table and filed names', `${model}.sqlEscapeAll`, '"sqlEscapeAll"',
                         'If enabled than all schema, table and field names will be escaped with double quotes (for example: "tableName"."fieldName").<br/>\
                         This enforces case sensitivity for field names and also allows having special characters in table and field names.<br/>\
                         Escaped names will be used for creation internal structures in Ignite SQL engine.')
+
+                //- Since ignite 2.0
+                div(ng-if='$ctrl.available("2.0.0")')
+                    .settings-row
+                        +number('Query parallelism', model + '.queryParallelism', '"queryParallelism"', 'true', '1', '1',
+                            'A hint to query execution engine on desired degree of parallelism within a single node')
+                    .settings-row
+                        +number('SQL index max inline size:', model + '.sqlIndexMaxInlineSize', '"sqlIndexMaxInlineSize"', 'true', '-1', '0',
+                            'Maximum inline size for sql indexes')
+
             .col-sm-6
                 +preview-xml-java(model, 'cacheQuery', 'domains')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/caches/store.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/store.pug b/modules/web-console/frontend/app/modules/states/configuration/caches/store.pug
index f09bc0b..3af24df 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/store.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/store.pug
@@ -246,5 +246,10 @@ mixin hibernateField(name, model, items, valid, save, newItem)
                             .details-row
                                 +number('Flush threads count:', `${model}.writeBehindFlushThreadCount`, '"writeBehindFlushThreadCount"', enabled, '1', '1',
                                     'Number of threads that will perform cache flushing')
+
+                            //- Since ignite 2.0
+                            .details-row(ng-if='$ctrl.available("2.0.0")')
+                                +checkbox-enabled('Write coalescing', model + '.writeBehindCoalescing', '"WriteBehindCoalescing"', enabled, 'Write coalescing flag for write-behind cache store')
+
             .col-sm-6
                 +preview-xml-java(model, 'cacheStore', 'domains')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/deployment.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/deployment.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/deployment.pug
index 2021c1c..25ee62a 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/clusters/deployment.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/deployment.pug
@@ -115,6 +115,12 @@ include /app/helpers/jade/mixins
 
                         .group-content-empty(ng-if=`!(${exclude}.length) && !group.add.length`)
                             | Not defined
+
+                //- Since ignite 2.0
+                .settings-row(ng-if='$ctrl.available("2.0.0")')
+                    +java-class('Class loader:', model + '.classLoader', '"classLoader"', 'true', 'false',
+                        'Loader which will be used for instantiating execution context')
+
                 .settings-row
                     +dropdown('Deployment variant:', modelDeployment + '.kind', '"deploymentKind"', 'true', 'Default',
                         '[\
@@ -214,7 +220,7 @@ include /app/helpers/jade/mixins
 
                                 div(type='internal' name='Scanner')
                                     label.col-xs-12.col-sm-12.col-md-12
-                                        // (lbl, name, model, items, valid, save, newItem)
+                                        //- (lbl, name, model, items, valid, save, newItem)
                                         +table-java-class-field('Scanner:', name, model, scannerModel, valid, save, true)
                                             +table-save-button(valid, save, true)
                                             +unique-feedback(name, uniqueTip)

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/discovery.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/discovery.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/discovery.pug
index 71d9974..5718755 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/clusters/discovery.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/discovery.pug
@@ -55,8 +55,18 @@ include /app/helpers/jade/mixins
                         '0 means wait forever')
                 .settings-row
                     +number('Thread priority:', `${model}.threadPriority`, '"threadPriority"', 'true', '10', '1', 'Thread priority for all threads started by SPI')
-                .settings-row
-                    +number('Metrics update frequency:', `${model}.metricsUpdateFrequency`, '"metricsUpdateFrequency"', 'true', '2000', '1', 'Metrics update messages issuing frequency')
+
+                //- Removed in ignite 2.0
+                div(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    .settings-row
+                        +number('Heartbeat frequency:', `${model}.heartbeatFrequency`, '"heartbeatFrequency"', 'true', '2000', '1', 'Heartbeat messages issuing frequency')
+                    .settings-row
+                        +number('Max heartbeats miss w/o init:', `${model}.maxMissedHeartbeats`, '"maxMissedHeartbeats"', 'true', '1', '1',
+                            'Max heartbeats count node can miss without initiating status check')
+                    .settings-row
+                        +number('Max missed client heartbeats:', `${model}.maxMissedClientHeartbeats`, '"maxMissedClientHeartbeats"', 'true', '5', '1',
+                            'Max heartbeats count node can miss without failing client node')
+
                 .settings-row
                     +number('Topology history:', `${model}.topHistorySize`, '"topHistorySize"', 'true', '1000', '0', 'Size of topology snapshots history')
                 .settings-row

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/events.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/events.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/events.pug
index 09cd40c..2f5cc31 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/clusters/events.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/events.pug
@@ -34,25 +34,21 @@ include /app/helpers/jade/mixins
     .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
         .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
             .col-sm-6
-                .settings-row
-                    +dropdown-multiple('Include type:', `${model}.includeEventTypes`, '"includeEventTypes"', true, 'Choose recorded event types', '', 'eventGroups',
-                    'Array of event types, which will be recorded by GridEventStorageManager#record(Event)<br/>\
-                    Note, that either the include event types or the exclude event types can be established')
-
-                .settings-row
-                    +dropdown('Event storage:', modelEventStorageKind, '"eventStorageKind"', 'true', 'Disabled',
-                    '[\
-                        {value: "Memory", label: "Memory"},\
-                        {value: "Custom", label: "Custom"},\
-                        {value: undefined, label: "Disabled"}\
-                    ]',
+                .settings-row(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    +dropdown('Event storage:', modelEventStorageKind, '"eventStorageKind"', 'true', 'Disabled', 'eventStorage',
+                    'Regulate how grid store events locally on node\
+                    <ul>\
+                        <li>Memory - All events are kept in the FIFO queue in-memory</li>\
+                        <li>Custom - Custom implementation of event storage SPI</li>\
+                    </ul>')
+                .settings-row(ng-if='$ctrl.available("2.0.0")')
+                    +dropdown('Event storage:', modelEventStorageKind, '"eventStorageKind"', 'true', 'Disabled', 'eventStorage',
                     'Regulate how grid store events locally on node\
                     <ul>\
                         <li>Memory - All events are kept in the FIFO queue in-memory</li>\
                         <li>Custom - Custom implementation of event storage SPI</li>\
                         <li>Disabled - Events are not collected</li>\
                     </ul>')
-
                 div(ng-show=eventStorageMemory)
                     .settings-row
                         +number('Events expiration time:', `${modelEventStorage}.Memory.expireAgeMs`, '"EventStorageExpireAgeMs"', 'true', 'Long.MAX_VALUE', '1', 'All events that exceed this value will be removed from the queue when next event comes')
@@ -66,5 +62,9 @@ include /app/helpers/jade/mixins
                 .settings-row(ng-show=eventStorageCustom)
                     +java-class('Class:', `${modelEventStorage}.Custom.className`, '"EventStorageCustom"', 'true', eventStorageCustom, 'Event storage implementation class name', eventStorageCustom)
 
+                .settings-row(ng-show=modelEventStorageKind)
+                    +dropdown-multiple('Include type:', `${model}.includeEventTypes`, '"includeEventTypes"', true, 'Choose recorded event types', '', 'eventGroups',
+                    'Array of event types, which will be recorded by GridEventStorageManager#record(Event)<br/>\
+                    Note, that either the include event types or the exclude event types can be established')
             .col-sm-6
                 +preview-xml-java(model, 'clusterEvents')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/failover.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/failover.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/failover.pug
index e0c2357..d61516c 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/clusters/failover.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/failover.pug
@@ -32,6 +32,15 @@ include /app/helpers/jade/mixins
     .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
         .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
             .col-sm-6
+                //- Since ignite 2.0
+                div(ng-if='$ctrl.available("2.0.0")')
+                    .settings-row
+                        +number('Failure detection timeout:', model + '.failureDetectionTimeout', '"failureDetectionTimeout"', 'true',
+                            '10000', '1', 'Failure detection timeout is used to determine how long the communication or discovery SPIs should wait before considering a remote connection failed')
+                    .settings-row
+                        +number('Client failure detection timeout:', model + '.clientFailureDetectionTimeout', '"clientFailureDetectionTimeout"', 'true',
+                            '30000', '1', 'Failure detection timeout is used to determine how long the communication or discovery SPIs should wait before considering a remote connection failed')
+
                 .settings-row(ng-init='failoverSpiTbl={type: "failoverSpi", model: "failoverSpi", focusId: "kind", ui: "failover-table"}')
                     +ignite-form-group()
                         ignite-form-field-label

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/general.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/general.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/general.pug
index 62cc23d..752eb79 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/clusters/general.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/general.pug
@@ -32,7 +32,7 @@ include /app/helpers/jade/mixins
         .panel-body
             .col-sm-6
                 .settings-row
-                    +text('Name:', `${model}.name`, '"clusterName"', 'true', 'Input name', 'Grid name allows to indicate to what grid this particular grid instance belongs to')
+                    +text('Name:', `${model}.name`, '"clusterName"', 'true', 'Input name', 'Instance name allows to indicate to what grid this particular grid instance belongs to')
                 .settings-row
                     +caches(model, 'Select caches to start in cluster or add a new cache')
                 .settings-row

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/hadoop.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/hadoop.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/hadoop.pug
new file mode 100644
index 0000000..b45efa4
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/hadoop.pug
@@ -0,0 +1,119 @@
+//-
+    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.
+
+include /app/helpers/jade/mixins
+
+-var form = 'hadoop'
+-var model = 'backupItem.hadoopConfiguration'
+-var plannerModel = model + '.mapReducePlanner'
+-var weightedModel = plannerModel + '.Weighted'
+-var weightedPlanner = plannerModel + '.kind === "Weighted"'
+-var customPlanner = plannerModel + '.kind === "Custom"'
+-var libs = model + '.nativeLibraryNames'
+
+.panel.panel-default(ng-form=form novalidate)
+    -var uniqueTip = 'Such native library already exists!'
+
+    .panel-heading(bs-collapse-toggle ng-click=`ui.loadPanel('${form}')`)
+        ignite-form-panel-chevron
+        label Hadoop configuration
+        ignite-form-field-tooltip.tipLabel
+            | Hadoop Accelerator configuration
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
+        .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
+            .col-sm-6
+                .settings-row
+                    +dropdown('Map reduce planner:', plannerModel + '.kind', '"MapReducePlanner"', 'true', 'Default', '[\
+                        {value: "Weighted", label: "Weighted"},\
+                        {value: "Custom", label: "Custom"},\
+                        {value: undefined, label: "Default"}\
+                    ]', 'Implementation of map reduce planner\
+                    <ul>\
+                        <li>Weighted - Planner which assigns mappers and reducers based on their "weights"</li>\
+                        <li>Custom - Custom planner implementation</li>\
+                        <li>Default - Default planner implementation</li>\
+                    </ul>')
+                .settings-row(ng-show=weightedPlanner)
+                    .panel-details
+                        .details-row
+                            +number('Local mapper weight:', weightedModel + '.localMapperWeight', '"LocalMapperWeight"', 'true', 100, '0',
+                                'This weight is added to a node when a mapper is assigned and it is input split data is located on this node')
+                        .details-row
+                            +number('Remote mapper weight:', weightedModel + '.remoteMapperWeight', '"remoteMapperWeight"', 'true', 100, '0',
+                                'This weight is added to a node when a mapper is assigned, but it is input split data is not located on this node')
+                        .details-row
+                            +number('Local reducer weight:', weightedModel + '.localReducerWeight', '"localReducerWeight"', 'true', 100, '0',
+                                'This weight is added to a node when a reducer is assigned and the node have at least one assigned mapper')
+                        .details-row
+                            +number('Remote reducer weight:', weightedModel + '.remoteReducerWeight', '"remoteReducerWeight"', 'true', 100, '0',
+                                'This weight is added to a node when a reducer is assigned, but the node does not have any assigned mappers')
+                        .details-row
+                            +number('Local mapper weight:', weightedModel + '.preferLocalReducerThresholdWeight', '"preferLocalReducerThresholdWeight"', 'true', 200, '0',
+                                "When threshold is reached, a node with mappers is no longer considered as preferred for further reducer assignments")
+                .settings-row(ng-show=customPlanner)
+                    .panel-details
+                        .details-row
+                            +java-class('Class name:', plannerModel + '.Custom.className', '"MapReducePlannerCustomClass"', 'true', customPlanner,
+                                'Custom planner implementation')
+                .settings-row
+                    +number('Finished job info TTL:', model + '.finishedJobInfoTtl', '"finishedJobInfoTtl"', 'true', '30000', '0',
+                        'Finished job info time-to-live in milliseconds')
+                .settings-row
+                    +number('Max parallel tasks:', model + '.maxParallelTasks', '"maxParallelTasks"', 'true', 'availableProcessors * 2', '1',
+                        'Max number of local tasks that may be executed in parallel')
+                .settings-row
+                    +number('Max task queue size:', model + '.maxTaskQueueSize', '"maxTaskQueueSize"', 'true', '8192', '1', 'Max task queue size')
+                .settings-row
+                    +ignite-form-group(ng-form=form ng-model=`${addresses}`)
+                        ignite-form-field-label
+                            | Native libraries
+                        ignite-form-group-tooltip
+                            | Library names
+                        ignite-form-group-add(ng-click='group.add = [{}]')
+                            | Add new library
+                        .group-content(ng-if=`${libs}.length`)
+                            -var model = 'obj.model';
+                            -var name = '"edit" + $index'
+                            -var valid = `${form}[${name}].$valid`
+                            -var save = `${libs}[$index] = ${model}`
+
+                            div(ng-repeat=`model in ${libs} track by $index` ng-init='obj = {}')
+                                label.col-xs-12.col-sm-12.col-md-12
+                                    .indexField
+                                        | {{ $index+1 }})
+                                    +table-remove-button(libs, 'Remove library')
+                                    span(ng-hide='field.edit')
+                                        a.labelFormField(ng-click=`field.edit = true; ${model} = model;`) {{ model }}
+                                    span(ng-if='field.edit')
+                                        +table-text-field(name, model, libs, valid, save, 'Input library name', false)
+                                            +table-save-button(valid, save, false)
+                                            +unique-feedback(name, uniqueTip)
+                        .group-content(ng-repeat='field in group.add')
+                            -var model = 'new';
+                            -var name = '"new"'
+                            -var valid = `${form}[${name}].$valid`
+                            -var save = `${libs}.push(${model})`
+
+                            div
+                                label.col-xs-12.col-sm-12.col-md-12
+                                    +table-text-field(name, model, libs, valid, save, 'Input library name', true)
+                                        +table-save-button(valid, save, true)
+                                        +unique-feedback(name, uniqueTip)
+                        .group-content-empty(id='libs' ng-if=`!(${libs}.length) && !group.add.length`)
+                            | Not defined
+            .col-sm-6
+                +preview-xml-java(model, 'clusterHadoop')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/marshaller.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/marshaller.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/marshaller.pug
index 274b014..6126a9e 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/clusters/marshaller.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/marshaller.pug
@@ -35,18 +35,21 @@ include /app/helpers/jade/mixins
         .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
             .col-sm-6
                 .settings-row
-                    +dropdown('Marshaller:', marshaller + '.kind', '"kind"', 'true', 'Choose marshaller',
-                        '[\
-                            {value: "OptimizedMarshaller", label: "OptimizedMarshaller"},\
-                            {value: "JdkMarshaller", label: "JdkMarshaller"},\
-                            {value: undefined, label: "Not set"}\
-                        ]',
-                        'Instance of marshaller to use in grid<br/>\
-                        <ul>\
-                            <li>OptimizedMarshaller - Optimized implementation of marshaller</li>\
-                            <li>JdkMarshaller - Marshaller based on JDK serialization mechanism</li>\
-                            <li>Not set - BinaryMarshaller serialize and deserialize all objects in the binary format</li>\
-                        </ul>')
+                    div(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                        +dropdown('Marshaller:', marshaller + '.kind', '"kind"', 'true', 'Default', 'marshallerVariant',
+                            'Instance of marshaller to use in grid<br/>\
+                            <ul>\
+                                <li>OptimizedMarshaller - Optimized implementation of marshaller</li>\
+                                <li>JdkMarshaller - Marshaller based on JDK serialization mechanism</li>\
+                                <li>Default - BinaryMarshaller serialize and deserialize all objects in the binary format</li>\
+                            </ul>')
+                    div(ng-if='$ctrl.available("2.0.0")')
+                        +dropdown('Marshaller:', marshaller + '.kind', '"kind"', 'true', 'Default', 'marshallerVariant',
+                            'Instance of marshaller to use in grid<br/>\
+                            <ul>\
+                                <li>JdkMarshaller - Marshaller based on JDK serialization mechanism</li>\
+                                <li>Default - BinaryMarshaller serialize and deserialize all objects in the binary format</li>\
+                            </ul>')
                     a.customize(
                         ng-if=`${marshaller}.kind && ${marshaller}.kind === 'OptimizedMarshaller'`
                         ng-click=`${marshaller}.expanded = !${marshaller}.expanded`
@@ -66,5 +69,15 @@ include /app/helpers/jade/mixins
                                 'Whether marshaller should require Serializable interface or not')
                 .settings-row
                     +checkbox('Marshal local jobs', `${model}.marshalLocalJobs`, '"marshalLocalJobs"', 'If this flag is enabled, jobs mapped to local node will be marshalled as if it was remote node')
+
+                //- Removed in ignite 2.0
+                div(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    .settings-row
+                        +number('Keep alive time:', `${model}.marshallerCacheKeepAliveTime`, '"marshallerCacheKeepAliveTime"', 'true', '10000', '0',
+                            'Keep alive time of thread pool that is in charge of processing marshaller messages')
+                    .settings-row
+                        +number('Pool size:', `${model}.marshallerCacheThreadPoolSize`, '"marshallerCacheThreadPoolSize"', 'true', 'max(8, availableProcessors) * 2', '1',
+                            'Default size of thread pool that is in charge of processing marshaller messages')
+
             .col-sm-6
                 +preview-xml-java(model, 'clusterMarshaller')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/memory.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/memory.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/memory.pug
new file mode 100644
index 0000000..62a07c1
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/memory.pug
@@ -0,0 +1,114 @@
+//-
+    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.
+
+include /app/helpers/jade/mixins
+
+-var form = 'memoryConfiguration'
+-var model = 'backupItem.memoryConfiguration'
+-var memoryPolicies = model + '.memoryPolicies'
+
+.panel.panel-default(ng-if='$ctrl.available("2.0.0")' ng-form=form novalidate)
+    .panel-heading(bs-collapse-toggle ng-click=`ui.loadPanel('${form}')`)
+        ignite-form-panel-chevron
+        label Memory configuration
+        ignite-form-field-tooltip.tipLabel
+            | Page memory is a manageable off-heap based memory architecture that is split into pages of fixed size#[br]
+            | #[a(href="https://apacheignite.readme.io/docs/page-memory" target="_blank") More info]
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
+        .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
+            .col-sm-6
+                .settings-row
+                    +number-min-max('Page size:', model + '.pageSize', '"MemoryConfigurationPageSize"',
+                    'true', '2048', '1024', '16384', 'Every memory region is split on pages of fixed size')
+                .settings-row
+                    +number('Concurrency level:', model + '.concurrencyLevel', '"MemoryConfigurationConcurrencyLevel"',
+                    'true', 'availableProcessors', '2', 'The number of concurrent segments in Ignite internal page mapping tables')
+                .settings-row
+                    +ignite-form-group
+                        ignite-form-field-label
+                            | System cache
+                        ignite-form-group-tooltip
+                            | System cache properties
+                        .group-content
+                            .details-row
+                                +number('Initial size:', model + '.systemCacheInitialSize', '"systemCacheInitialSize"',
+                                'true', '41943040', '10485760', 'Initial size of a memory region reserved for system cache')
+                            .details-row
+                                +number('Maximum size:', model + '.systemCacheMaxSize', '"systemCacheMaxSize"',
+                                'true', '104857600', '10485760', 'Maximum size of a memory region reserved for system cache')
+                .settings-row
+                    +ignite-form-group
+                        ignite-form-field-label
+                            | Memory policies
+                        ignite-form-group-tooltip
+                            | Memory policies configuration
+                        .group-content
+                            .details-row
+                                +text('Default region name:', model + '.defaultMemoryPolicyName', '"defaultMemoryPolicyName"',
+                                'false', 'default', 'Name of the memory policy that defines the default memory region')
+                            .details-row(ng-hide='(' + model + '.defaultMemoryPolicyName || "default") !== "default"')
+                                +number('Default region size:', model + '.defaultMemoryPolicySize', '"defaultMemoryPolicySize"',
+                                'true', '0.8 * totalMemoryAvailable', '10485760',
+                                'Size of the memory policy that defines the default memory region')
+                            .details-row(ng-init='memoryPoliciesTbl={type: "memoryPolicies", model: "memoryPolicies", focusId: "name", ui: "memory-policies-table"}')
+                                +ignite-form-group()
+                                    ignite-form-field-label
+                                        | Configured policies
+                                    ignite-form-group-tooltip
+                                        | List of configured policies
+                                    ignite-form-group-add(ng-click='tableNewItem(memoryPoliciesTbl)')
+                                        | Add Memory policy configuration
+                                    .group-content-empty(ng-if=`!(${memoryPolicies} && ${memoryPolicies}.length > 0)`)
+                                        | Not defined
+                                    .group-content(ng-show=`${memoryPolicies} && ${memoryPolicies}.length > 0` ng-repeat=`model in ${memoryPolicies} track by $index`)
+                                        hr(ng-if='$index != 0')
+                                        .settings-row
+                                            +text-enabled-autofocus('Name:', 'model.name', '"MemoryPolicyName" + $index', 'true', 'false', 'default', 'Memory policy name')
+                                                +table-remove-button(memoryPolicies, 'Remove memory configuration')
+                                        .settings-row
+                                            +number('Initial size:', 'model.initialSize', '"MemoryPolicyInitialSize" + $index',
+                                            'true', '268435456', '10485760', 'Initial memory region size defined by this memory policy')
+                                        .settings-row
+                                            +number('Maximum size:', 'model.maxSize', '"MemoryPolicyMaxSize" + $index',
+                                            'true', '0.8 * totalMemoryAvailable', '10485760', 'Maximum memory region size defined by this memory policy')
+                                        .settings-row
+                                            +text('Swap file path:', 'model.swapFilePath', '"MemoryPolicySwapFilePath" + $index', 'false',
+                                            'Input swap file path', 'An optional path to a memory mapped file for this memory policy')
+                                        .settings-row
+                                            +dropdown('Eviction mode:', 'model.pageEvictionMode', '"MemoryPolicyPageEvictionMode"', 'true', 'DISABLED',
+                                            '[\
+                                                {value: "DISABLED", label: "DISABLED"},\
+                                                {value: "RANDOM_LRU", label: "RANDOM_LRU"},\
+                                                {value: "RANDOM_2_LRU", label: "RANDOM_2_LRU"}\
+                                            ]',
+                                            'An algorithm for memory pages eviction\
+                                            <ul>\
+                                                <li>DISABLED - Eviction is disabled</li>\
+                                                <li>RANDOM_LRU - Once a memory region defined by a memory policy is configured, an off - heap array is allocated to track last usage timestamp for every individual data page</li>\
+                                                <li>RANDOM_2_LRU - Differs from Random - LRU only in a way that two latest access timestamps are stored for every data page</li>\
+                                            </ul>')
+                                        .settings-row
+                                            +number-min-max-step('Eviction threshold:', 'model.evictionThreshold', '"MemoryPolicyEvictionThreshold" + $index',
+                                            'true', '0.9', '0.5', '0.999', '0.05', 'A threshold for memory pages eviction initiation')
+                                        .settings-row
+                                            +number('Empty pages pool size:', 'model.emptyPagesPoolSize', '"MemoryPolicyEmptyPagesPoolSize" + $index',
+                                            'true', '100', '10', 'The minimal number of empty pages to be present in reuse lists for this memory policy')
+                                        .settings-row
+                                            +checkbox('Metrics enabled', 'model.metricsEnabled', '"MemoryPolicyMetricsEnabled" + $index',
+                                            'Whether memory metrics are enabled by default on node startup')
+            .col-sm-6
+                +preview-xml-java(model, 'clusterMemory')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/metrics.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/metrics.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/metrics.pug
index 6810e6b..bae3267 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/clusters/metrics.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/metrics.pug
@@ -40,7 +40,7 @@ include /app/helpers/jade/mixins
                         'Frequency of metrics log print out<br/>\ ' +
                         'When <b>0</b> log print of metrics is disabled')
                 .settings-row
-                    +number('Update frequency:', `${model}.metricsUpdateFrequency`, '"metricsUpdateFrequency"', 'true', '2000', '0',
+                    +number('Update frequency:', `${model}.metricsUpdateFrequency`, '"metricsUpdateFrequency"', 'true', '2000', '-1',
                         'Job metrics update frequency in milliseconds\
                         <ul>\
                             <li>If set to -1 job metrics are never updated</li>\

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/misc.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/misc.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/misc.pug
new file mode 100644
index 0000000..f84fae4
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/misc.pug
@@ -0,0 +1,60 @@
+//-
+    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.
+
+include /app/helpers/jade/mixins
+
+-var form = 'misc'
+-var model = 'backupItem'
+
+.panel.panel-default(ng-form=form novalidate)
+    .panel-heading(bs-collapse-toggle)
+        ignite-form-panel-chevron
+        label Miscellaneous
+        ignite-form-field-tooltip.tipLabel
+            | Various miscellaneous cluster settings
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
+        .panel-body
+            .col-sm-6
+                .settings-row
+                    +text('Work directory:', model + '.workDirectory', '"workDirectory"', 'false', 'Input work directory',
+                        'Ignite work directory.<br/>\
+                        If not provided, the method will use work directory under IGNITE_HOME specified by IgniteConfiguration#setIgniteHome(String)\
+                        or IGNITE_HOME environment variable or system property.')
+
+                //- Since ignite 2.0
+                div(ng-show='$ctrl.available("2.0.0")')
+                    .settings-row
+                        +text('Consistent ID:', model + '.consistentId', '"ConsistentId"', 'false', 'Input consistent ID', 'Consistent globally unique node ID which survives node restarts')
+                    .settings-row
+                        +java-class('Warmup closure:', model + '.warmupClosure', '"warmupClosure"', 'true', 'false', 'This closure will be executed before actual grid instance start')
+                    .settings-row
+                        +checkbox('Active on start', model + '.activeOnStart', '"activeOnStart"',
+                            'If cluster is not active on start, there will be no cache partition map exchanges performed until the cluster is activated')
+                    .settings-row
+                        +checkbox('Cache sanity check enabled', model + '.cacheSanityCheckEnabled', '"cacheSanityCheckEnabled"',
+                            'If enabled, then Ignite will perform the following checks and throw an exception if check fails<br/>\
+                            <ul>\
+                            <li>Cache entry is not externally locked with lock or lockAsync methods when entry is enlisted to transaction</li>\
+                            <li>Each entry in affinity group - lock transaction has the same affinity key as was specified on affinity transaction start</li>\
+                            <li>Each entry in partition group - lock transaction belongs to the same partition as was specified on partition transaction start</li>\
+                            </ul>')
+
+                .settings-row
+                    +checkbox('Late affinity assignment', model + '.lateAffinityAssignment', '"lateAffinityAssignment"',
+                        'With late affinity assignment mode if primary node was changed for some partition this nodes becomes primary only when rebalancing for all assigned primary partitions is finished')
+            .col-sm-6
+                +preview-xml-java(model, 'clusterMisc', 'caches')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/service.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/service.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/service.pug
new file mode 100644
index 0000000..cf4c27a
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/service.pug
@@ -0,0 +1,88 @@
+//-
+    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.
+
+include /app/helpers/jade/mixins
+
+-var form = 'serviceConfiguration'
+-var model = 'backupItem.serviceConfigurations'
+
+.panel.panel-default(ng-form=form novalidate)
+    .panel-heading(bs-collapse-toggle ng-click=`ui.loadPanel('${form}')`)
+        ignite-form-panel-chevron
+        label Service configuration
+        ignite-form-field-tooltip.tipLabel
+            | Service Grid allows for deployments of arbitrary user-defined services on the cluster#[br]
+            | #[a(href="https://apacheignite.readme.io/docs/fault-tolerance" target="_blank") More info]
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
+        .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
+            .col-sm-6
+                .settings-row(ng-init='serviceConfigurationsTbl={type: "serviceConfigurations", model: "serviceConfigurations", focusId: "kind", ui: "failover-table"}')
+                    +ignite-form-group()
+                        ignite-form-field-label
+                            | Service configurations
+                        ignite-form-group-tooltip
+                            | Service configurations
+                        ignite-form-group-add(ng-click='tableNewItem(serviceConfigurationsTbl)')
+                            | Add service configuration
+                        .group-content-empty(ng-if=`!(${model} && ${model}.length > 0)`)
+                            | Not defined
+                        .group-content(ng-show=`${model} && ${model}.length > 0` ng-repeat=`model in ${model} track by $index`)
+                            -var nodeFilter = 'model.nodeFilter';
+                            -var nodeFilterKind = nodeFilter + '.kind';
+                            -var igfsFilter = nodeFilterKind + ' === "IGFS"'
+                            -var customFilter = nodeFilterKind + ' === "Custom"'
+
+                            hr(ng-if='$index != 0')
+                            .settings-row
+                                +text-enabled-autofocus('Name:', 'model.name', '"ServiceName" + $index', 'true', 'true', 'Input service name', 'Service name')
+                                    +table-remove-button(model, 'Remove service configuration')
+                            .settings-row
+                                +java-class('Service class', 'model.service', '"serviceService" + $index', 'true', 'true', 'Service implementation class name')
+                            .settings-row
+                                +number('Max per node count:', 'model.maxPerNodeCount', '"ServiceMaxPerNodeCount" + $index', 'true', 'Unlimited', '0',
+                                    'Maximum number of deployed service instances on each node.<br/>' +
+                                    'Zero for unlimited')
+                            .settings-row
+                                +number('Total count:', 'model.totalCount', '"ServiceTotalCount" + $index', 'true', 'Unlimited', '0',
+                                    'Total number of deployed service instances in the cluster.<br/>' +
+                                    'Zero for unlimited')
+                            //-
+                                .settings-row
+                                    +dropdown('Node filter:', nodeFilterKind, '"nodeFilter" + $index', 'true', 'Not set',
+                                    '[\
+                                        {value: "IGFS", label: "IGFS nodes"},\
+                                        {value: "Custom", label: "Custom"},\
+                                        {value: undefined, label: "Not set"}\
+                                    ]',
+                                    'Node filter variant'
+                                    )
+                                .panel-details(ng-show=igfsFilter)
+                                    .settings-row
+                                        +dropdown-required-empty('IGFS:', nodeFilter + '.IGFS.igfs', '"igfsNodeFilter"', 'true', igfsFilter,
+                                            'Choose IGFS', 'No IGFS configured', 'igfss', 'Select IGFS to filter nodes')
+                                .panel-details(ng-show=customFilter)
+                                    .settings-row
+                                        +java-class('Class name:', nodeFilter + '.Custom.className', '"customNodeFilter"',
+                                            'true', customFilter, 'Class name of custom node filter implementation', customFilter)
+                            .settings-row
+                                +dropdown-required-empty('Cache:', 'model.cache', '"ServiceCache" + $index', 'true', 'false',
+                                    'Choose cache', 'No caches configured for current cluster', 'clusterCachesEmpty', 'Cache name used for key-to-node affinity calculation').settings-row
+                            .settings-row
+                                +text('Affinity key:', 'model.affinityKey', '"ServiceAffinityKey" + $index', 'false', 'Input affinity key',
+                                    'Affinity key used for key-to-node affinity calculation')
+            .col-sm-6
+                +preview-xml-java('backupItem', 'clusterServiceConfiguration', 'caches')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/swap.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/swap.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/swap.pug
new file mode 100644
index 0000000..7210f7a
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/swap.pug
@@ -0,0 +1,72 @@
+//-
+    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.
+
+include /app/helpers/jade/mixins
+
+-var form = 'swap'
+-var model = 'backupItem'
+-var swapModel = model + '.swapSpaceSpi'
+-var fileSwapModel = swapModel + '.FileSwapSpaceSpi'
+
+.panel.panel-default(ng-if='$ctrl.available(["1.0.0", "2.0.0"])' ng-form=form novalidate)
+    .panel-heading(bs-collapse-toggle ng-click=`ui.loadPanel('${form}')`)
+        ignite-form-panel-chevron
+        label Swap
+        ignite-form-field-tooltip.tipLabel
+            | Settings for overflow data to disk if it cannot fit in memory#[br]
+            | #[a(href="https://apacheignite.readme.io/docs/off-heap-memory#swap-space" target="_blank") More info]
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
+        .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
+            .col-sm-6
+                .settings-row
+                    +dropdown('Swap space SPI:', `${swapModel}.kind`, '"swapSpaceSpi"', 'true', 'Choose swap SPI',
+                        '[\
+                            {value: "FileSwapSpaceSpi", label: "File-based swap"},\
+                            {value: undefined, label: "Not set"}\
+                        ]',
+                        'Provides a mechanism in grid for storing data on disk<br/>\
+                        Ignite cache uses swap space to overflow data to disk if it cannot fit in memory\
+                        <ul>\
+                            <li>File-based swap - File-based swap space SPI implementation which holds keys in memory</li>\
+                            <li>Not set - File-based swap space SPI with default configuration when it needed</li>\
+                        </ul>')
+                    a.customize(
+                        ng-if=`${swapModel}.kind`
+                        ng-click=`${swapModel}.expanded = !${swapModel}.expanded`
+                    ) {{ #{swapModel}.expanded ? 'Hide settings' : 'Show settings'}}
+                .settings-row
+                    .panel-details(ng-show=`${swapModel}.expanded && ${swapModel}.kind`)
+                        .details-row
+                            +text('Base directory:', `${fileSwapModel}.baseDirectory`, '"baseDirectory"', 'false', 'swapspace',
+                                'Base directory where to write files')
+                        .details-row
+                            +number('Read stripe size:', `${fileSwapModel}.readStripesNumber`, '"readStripesNumber"', 'true', 'availableProcessors', '0',
+                                'Read stripe size defines number of file channels to be used concurrently')
+                        .details-row
+                            +number-min-max-step('Maximum sparsity:', `${fileSwapModel}.maximumSparsity`, '"maximumSparsity"', 'true', '0.5', '0', '0.999', '0.05',
+                                'This property defines maximum acceptable wasted file space to whole file size ratio<br/>\
+                                When this ratio becomes higher than specified number compacting thread starts working')
+                        .details-row
+                            +number('Max write queue size:', `${fileSwapModel}.maxWriteQueueSize`, '"maxWriteQueueSize"', 'true', '1024 * 1024', '0',
+                                'Max write queue size in bytes<br/>\
+                                If there are more values are waiting for being written to disk then specified size, SPI will block on store operation')
+                        .details-row
+                            +number('Write buffer size:', `${fileSwapModel}.writeBufferSize`, '"writeBufferSize"', 'true', '64 * 1024', '0',
+                                'Write buffer size in bytes<br/>\
+                                Write to disk occurs only when this buffer is full')
+            .col-sm-6
+                +preview-xml-java(model, 'clusterSwap')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/thread.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/thread.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/thread.pug
index 31dd333..ac4673c 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/clusters/thread.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/thread.pug
@@ -18,6 +18,7 @@ include /app/helpers/jade/mixins
 
 -var form = 'pools'
 -var model = 'backupItem'
+-var executors = model + '.executorConfiguration'
 
 .panel.panel-default(ng-form=form novalidate)
     .panel-heading(bs-collapse-toggle ng-click=`ui.loadPanel('${form}')`)
@@ -30,19 +31,62 @@ include /app/helpers/jade/mixins
         .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
             .col-sm-6
                 .settings-row
-                    +number('Public:', `${model}.publicThreadPoolSize`, '"publicThreadPoolSize"', 'true', 'max(8, availableProcessors) * 2', '1',
+                    +number('Public:', model + '.publicThreadPoolSize', '"publicThreadPoolSize"', 'true', 'max(8, availableProcessors) * 2', '1',
                         'Thread pool that is in charge of processing ComputeJob, GridJobs and user messages sent to node')
                 .settings-row
-                    +number('System:', `${model}.systemThreadPoolSize`, '"systemThreadPoolSize"', 'true', 'max(8, availableProcessors) * 2', '1',
+                    +number('System:', model + '.systemThreadPoolSize', '"systemThreadPoolSize"', 'true', 'max(8, availableProcessors) * 2', '1',
                         'Thread pool that is in charge of processing internal system messages')
                 .settings-row
-                    +number('Management:', `${model}.managementThreadPoolSize`, '"managementThreadPoolSize"', 'true', '4', '1',
+                    +number('Service:', model + '.serviceThreadPoolSize', '"serviceThreadPoolSize"', 'true', 'max(8, availableProcessors) * 2', '1',
+                        'Thread pool that is in charge of processing proxy invocation')
+                .settings-row
+                    +number('Management:', model + '.managementThreadPoolSize', '"managementThreadPoolSize"', 'true', '4', '1',
                         'Thread pool that is in charge of processing internal and Visor ComputeJob, GridJobs')
                 .settings-row
-                    +number('IGFS:', `${model}.igfsThreadPoolSize`, '"igfsThreadPoolSize"', 'true', 'availableProcessors', '1',
+                    +number('IGFS:', model + '.igfsThreadPoolSize', '"igfsThreadPoolSize"', 'true', 'availableProcessors', '1',
                         'Thread pool that is in charge of processing outgoing IGFS messages')
                 .settings-row
-                    +number('Rebalance:', `${model}.rebalanceThreadPoolSize`, '"rebalanceThreadPoolSize"', 'true', '1', '1',
+                    +number('Rebalance:', model + '.rebalanceThreadPoolSize', '"rebalanceThreadPoolSize"', 'true', '1', '1',
                         'Max count of threads can be used at rebalancing')
+                .settings-row
+                    +number('Utility cache:', model + '.utilityCacheThreadPoolSize', '"utilityCacheThreadPoolSize"', 'true', 'max(8, availableProcessors)', '1',
+                        'Default thread pool size that will be used to process utility cache messages')
+                .settings-row
+                    +number('Utility cache keep alive time:', model + '.utilityCacheKeepAliveTime', '"utilityCacheKeepAliveTime"', 'true', '60000', '0',
+                        'Keep alive time of thread pool size that will be used to process utility cache messages')
+                .settings-row
+                    +number('Async callback:', model + '.asyncCallbackPoolSize', '"asyncCallbackPoolSize"', 'true', 'max(8, availableProcessors)', '1',
+                        'Size of thread pool that is in charge of processing asynchronous callbacks')
+                .settings-row
+                    +number('Striped:', model + '.stripedPoolSize', '"stripedPoolSize"', 'true', 'max(8, availableProcessors)', '1',
+                        'Striped pool size that should be used for cache requests processing')
+
+                //- Since ignite 2.0
+                div(ng-if='$ctrl.available("2.0.0")')
+                    .settings-row
+                        +number('Data streamer:', model + '.dataStreamerThreadPoolSize', '"dataStreamerThreadPoolSize"', 'true', 'max(8, availableProcessors)', '1',
+                            'Size of thread pool that is in charge of processing data stream messages')
+                    .settings-row
+                        +number('Query:', model + '.queryThreadPoolSize', '"queryThreadPoolSize"', 'true', 'max(8, availableProcessors)', '1',
+                            'Size of thread pool that is in charge of processing query messages')
+                    .settings-row(ng-init='executorConfigurationsTbl={type: "executorConfigurations", model: "executorConfigurations", focusId: "kind", ui: "failover-table"}')
+                        +ignite-form-group()
+                            ignite-form-field-label
+                                | Executor configurations
+                            ignite-form-group-tooltip
+                                | Сustom thread pool configurations for compute tasks
+                            ignite-form-group-add(ng-click='tableNewItem(executorConfigurationsTbl)')
+                                | Add executor configuration
+                            .group-content-empty(ng-if=`!(${executors} && ${executors}.length > 0)`)
+                                | Not defined
+                            .group-content(ng-show=`${executors} && ${executors}.length > 0` ng-repeat=`model in ${executors} track by $index`)
+                                hr(ng-if='$index != 0')
+                                .settings-row
+                                    +text-enabled-autofocus('Name:', 'model.name', '"ExecutorName" + $index', 'true', 'true', 'Input executor name', 'Thread pool name')
+                                        +table-remove-button(executors, 'Remove executor configuration')
+                                .settings-row
+                                    +number('Pool size:', 'model.size', '"ExecutorPoolSize" + $index', 'true', 'max(8, availableProcessors)', '1',
+                                        'Thread pool size')
+
             .col-sm-6
                 +preview-xml-java(model, 'clusterPools')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/clusters/time.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/clusters/time.pug b/modules/web-console/frontend/app/modules/states/configuration/clusters/time.pug
index 1645a60..329d7c4 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/clusters/time.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/clusters/time.pug
@@ -29,8 +29,19 @@ include /app/helpers/jade/mixins
     .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
         .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
             .col-sm-6
+                //- Removed in ignite 2.0
+                div(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    .settings-row
+                        +number('Samples size:', `${model}.clockSyncSamples`, '"clockSyncSamples"', 'true', '8', '0',
+                            'Number of samples used to synchronize clocks between different nodes<br/>\
+                            Clock synchronization is used for cache version assignment in CLOCK order mode')
+                    .settings-row
+                        +number('Frequency:', `${model}.clockSyncFrequency`, '"clockSyncFrequency"', 'true', '120000', '0',
+                            'Frequency at which clock is synchronized between nodes, in milliseconds<br/>\
+                            Clock synchronization is used for cache version assignment in CLOCK order mode')
+
                 .settings-row
-                    +number-min-max('Port base:', model + '.timeServerPortBase', '"timeServerPortBase"', 'true', '31100', '0', '65535',
+                    +number-min-max('Port base:', `${model}.timeServerPortBase`, '"timeServerPortBase"', 'true', '31100', '0', '65535',
                         'Time server provides clock synchronization between nodes<br/>\
                         Base UPD port number for grid time server. Time server will be started on one of free ports in range')
                 .settings-row

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/domains/query.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/domains/query.pug b/modules/web-console/frontend/app/modules/states/configuration/domains/query.pug
index aff3c73..b8564dc 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/domains/query.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/domains/query.pug
@@ -25,7 +25,7 @@ include /app/helpers/jade/mixins
 -var queryAliasesForm = 'queryAliases'
 -var queryIndexesForm = 'queryIndexes'
 
-// LEGACY mixin for LEGACY index fields table.
+//- LEGACY mixin for LEGACY index fields table.
 mixin table-index-item-edit(prefix, index, sortAvailable, idAddition)
     -var fieldName = `${prefix}FieldName`
     -var direction = `${prefix}Direction`

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/igfs/dual.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/igfs/dual.pug b/modules/web-console/frontend/app/modules/states/configuration/igfs/dual.pug
new file mode 100644
index 0000000..c6c1f89
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/states/configuration/igfs/dual.pug
@@ -0,0 +1,42 @@
+//-
+    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.
+
+include /app/helpers/jade/mixins
+
+-var form = 'dualMode'
+-var model = 'backupItem'
+
+.panel.panel-default(ng-if='$ctrl.available(["1.0.0", "2.0.0"])' ng-form=form novalidate)
+    .panel-heading(bs-collapse-toggle='' ng-click=`ui.loadPanel('${form}')`)
+        ignite-form-panel-chevron
+        label Dual mode
+        ignite-form-field-tooltip.tipLabel
+            | IGFS supports dual-mode that allows it to work as either a standalone file system in Hadoop cluster, or work in tandem with HDFS, providing a primary caching layer for the secondary HDFS#[br]
+            | As a caching layer it provides highly configurable read-through and write-through behaviour
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
+        .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
+            .col-sm-6
+                .settings-row
+                    +number('Maximum pending puts size:', `${model}.dualModeMaxPendingPutsSize`, '"dualModeMaxPendingPutsSize"', 'true', '0', 'Number.MIN_SAFE_INTEGER',
+                        'Maximum amount of pending data read from the secondary file system and waiting to be written to data cache<br/>\
+                        Zero or negative value stands for unlimited size')
+                .settings-row
+                    +java-class('Put executor service:', `${model}.dualModePutExecutorService`, '"dualModePutExecutorService"', 'true', 'false', 'DUAL mode put operation executor service')
+                .settings-row
+                    +checkbox('Put executor service shutdown', `${model}.dualModePutExecutorServiceShutdown`, '"dualModePutExecutorServiceShutdown"', 'DUAL mode put operation executor service shutdown flag')
+            .col-sm-6
+                +preview-xml-java(model, 'igfsDualMode')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/igfs/misc.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/igfs/misc.pug b/modules/web-console/frontend/app/modules/states/configuration/igfs/misc.pug
index 29f955a..72d0649 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/igfs/misc.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/igfs/misc.pug
@@ -54,8 +54,18 @@ mixin table-igfs-path-mode-edit(prefix, focusId, index)
             .col-sm-6
                 .settings-row
                     +number('Block size:', `${model}.blockSize`, '"blockSize"', 'true', '65536', '0', 'File data block size in bytes')
-                .settings-row
-                    +number('Buffer size:', `${model}.bufferSize`, '"bufferSize"', 'true', '65536', '0', 'Read/write buffer size for IGFS stream operations in bytes')
+
+                //- Since ignite 2.0
+                .settings-row(ng-if='$ctrl.available("2.0.0")')
+                    +number('Buffer size:', `${model}.streamBufferSize`, '"streamBufferSize"', 'true', '65536', '0', 'Read/write buffer size for IGFS stream operations in bytes')
+
+                //- Removed in ignite 2.0
+                div(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    .settings-row
+                        +number('Stream buffer size:', `${model}.streamBufferSize`, '"streamBufferSize"', 'true', '65536', '0', 'Read/write buffer size for IGFS stream operations in bytes')
+                    .settings-row
+                        +number('Maximum space size:', `${model}.maxSpaceSize`, '"maxSpaceSize"', 'true', '0', '0', 'Maximum space available for data cache to store file system entries')
+
                 .settings-row
                     +number('Maximum task range length:', `${model}.maximumTaskRangeLength`, '"maximumTaskRangeLength"', 'true', '0', '0', 'Maximum default range size of a file being split during IGFS task execution')
                 .settings-row
@@ -68,6 +78,11 @@ mixin table-igfs-path-mode-edit(prefix, focusId, index)
                     +number('Prefetch blocks:', `${model}.prefetchBlocks`, '"prefetchBlocks"', 'true', '0', '0', 'Number of pre-fetched blocks if specific file chunk is requested')
                 .settings-row
                     +number('Sequential reads before prefetch:', `${model}.sequentialReadsBeforePrefetch`, '"sequentialReadsBeforePrefetch"', 'true', '0', '0', 'Amount of sequential block reads before prefetch is triggered')
+
+                //- Removed in ignite 2.0
+                .settings-row(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    +number('Trash purge timeout:', `${model}.trashPurgeTimeout`, '"trashPurgeTimeout"', 'true', '1000', '0', 'Maximum timeout awaiting for trash purging in case data cache oversize is detected')
+
                 .settings-row
                     +checkbox('Colocate metadata', `${model}.colocateMetadata`, '"colocateMetadata"', 'Whether to co-locate metadata on a single node')
                 .settings-row
@@ -75,6 +90,11 @@ mixin table-igfs-path-mode-edit(prefix, focusId, index)
                         'If value of this flag is <b>true</b>, IGFS will skip expensive consistency checks<br/>\
                         It is recommended to set this flag to <b>false</b> if your application has conflicting\
                         operations, or you do not know how exactly users will use your system')
+
+                //- Since ignite 2.0
+                .settings-row(ng-if='$ctrl.available("2.0.0")')
+                    +checkbox('Update file length on flush', model + '.updateFileLengthOnFlush', '"updateFileLengthOnFlush"', 'Update file length on flush flag')
+
                 .settings-row
                     +ignite-form-group(ng-model=pathModes ng-form=pathModesForm)
                         ignite-form-field-label
@@ -99,6 +119,5 @@ mixin table-igfs-path-mode-edit(prefix, focusId, index)
                                     tr
                                         td.col-sm-12
                                             +table-igfs-path-mode-edit('new', 'PathMode', '-1')
-
             .col-sm-6
                 +preview-xml-java(model, 'igfsMisc')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/summary/summary-zipper.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/summary/summary-zipper.service.js b/modules/web-console/frontend/app/modules/states/configuration/summary/summary-zipper.service.js
index 08cfa71..0259d39 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/summary/summary-zipper.service.js
+++ b/modules/web-console/frontend/app/modules/states/configuration/summary/summary-zipper.service.js
@@ -18,11 +18,11 @@
 import Worker from 'worker?inline=true!./summary.worker';
 
 export default ['$q', function($q) {
-    return function({ cluster, data }) {
+    return function(message) {
         const defer = $q.defer();
         const worker = new Worker();
 
-        worker.postMessage({ cluster, data });
+        worker.postMessage(message);
 
         worker.onmessage = (e) => {
             defer.resolve(e.data);

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js b/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js
index 71b5a82..8f6a6fa 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js
+++ b/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js
@@ -314,7 +314,7 @@ export default [
 
             ActivitiesData.post({ action: '/configuration/download' });
 
-            return new SummaryZipper({ cluster, data: ctrl.data || {}, IgniteDemoMode: $root.IgniteDemoMode })
+            return new SummaryZipper({ cluster, data: ctrl.data || {}, demo: $root.IgniteDemoMode, targetVer: Version.currentSbj.getValue() })
                 .then((data) => {
                     saver.saveAs(data, escapeFileName(cluster.name) + '-project.zip');
                 })


[31/50] [abbrv] ignite git commit: IGNITE-5388 Added support to configuration of Ignite 2.x and Ignite 1.x.

Posted by sb...@apache.org.
IGNITE-5388 Added support to configuration of Ignite 2.x and Ignite 1.x.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e04df7d1
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e04df7d1
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e04df7d1

Branch: refs/heads/ignite-5075
Commit: e04df7d1fb6cf0ed1756cd7df9980cf4c509ab6f
Parents: 898781a
Author: Andrey Novikov <an...@gridgain.com>
Authored: Mon Jun 5 10:27:23 2017 +0700
Committer: Andrey Novikov <an...@gridgain.com>
Committed: Mon Jun 5 10:27:23 2017 +0700

----------------------------------------------------------------------
 modules/web-console/backend/app/mongo.js        |  79 ++-
 modules/web-console/backend/services/caches.js  |   2 +
 modules/web-console/backend/services/igfss.js   |   5 +
 modules/web-console/frontend/app/app.config.js  |   3 +-
 modules/web-console/frontend/app/app.js         |  12 +-
 .../cluster-select/cluster-select.pug           |   2 +-
 .../list-of-registered-users.column-defs.js     |   2 +-
 .../app/components/version-picker/component.js  |  52 ++
 .../app/components/version-picker/index.js      |  25 +
 .../app/components/version-picker/style.scss    |  41 ++
 .../app/components/version-picker/template.pug  |  33 ++
 .../frontend/app/data/event-groups.json         |  14 +
 .../ui-ace-docker/ui-ace-docker.controller.js   |   8 +-
 .../ui-ace-java/ui-ace-java.controller.js       |  29 +-
 .../ui-ace-java/ui-ace-java.directive.js        |  12 +-
 .../ui-ace-pom/ui-ace-pom.controller.js         |   8 +-
 .../ui-ace-spring/ui-ace-spring.controller.js   |  29 +-
 .../ui-ace-spring/ui-ace-spring.directive.js    |  12 +-
 .../frontend/app/helpers/jade/mixins.pug        |   4 +-
 .../app/modules/agent/AgentManager.service.js   |  15 +-
 .../frontend/app/modules/cluster/Cache.js       |   4 +
 .../app/modules/cluster/CacheMetrics.js         |   4 +
 .../modules/configuration/Version.service.js    | 180 +++---
 .../generator/AbstractTransformer.js            | 110 ++--
 .../generator/ConfigurationGenerator.js         | 570 +++++++++++++++----
 .../configuration/generator/Docker.service.js   |  12 +-
 .../generator/JavaTransformer.service.js        |  32 +-
 .../configuration/generator/Maven.service.js    |  38 +-
 .../generator/PlatformGenerator.js              |  19 +-
 .../generator/SpringTransformer.service.js      |  23 +-
 .../defaults/Cache.platform.service.js          |   9 +
 .../generator/defaults/Cache.service.js         |  23 +-
 .../generator/defaults/Cluster.service.js       |  46 +-
 .../generator/defaults/IGFS.service.js          |   9 +-
 .../frontend/app/modules/sql/sql.controller.js  |   6 +-
 .../app/modules/states/configuration.state.js   |  21 +-
 .../states/configuration/caches/affinity.pug    |  23 +-
 .../states/configuration/caches/concurrency.pug |  14 +
 .../states/configuration/caches/general.pug     |  71 ++-
 .../states/configuration/caches/memory.pug      |  99 +++-
 .../states/configuration/caches/node-filter.pug |  27 +-
 .../states/configuration/caches/query.pug       |  25 +-
 .../states/configuration/caches/store.pug       |   5 +
 .../configuration/clusters/deployment.pug       |   8 +-
 .../states/configuration/clusters/discovery.pug |  14 +-
 .../states/configuration/clusters/events.pug    |  26 +-
 .../states/configuration/clusters/failover.pug  |   9 +
 .../states/configuration/clusters/general.pug   |   2 +-
 .../states/configuration/clusters/hadoop.pug    | 119 ++++
 .../configuration/clusters/marshaller.pug       |  37 +-
 .../states/configuration/clusters/memory.pug    | 114 ++++
 .../states/configuration/clusters/metrics.pug   |   2 +-
 .../states/configuration/clusters/misc.pug      |  60 ++
 .../states/configuration/clusters/service.pug   |  88 +++
 .../states/configuration/clusters/swap.pug      |  72 +++
 .../states/configuration/clusters/thread.pug    |  54 +-
 .../states/configuration/clusters/time.pug      |  13 +-
 .../states/configuration/domains/query.pug      |   2 +-
 .../modules/states/configuration/igfs/dual.pug  |  42 ++
 .../modules/states/configuration/igfs/misc.pug  |  25 +-
 .../summary/summary-zipper.service.js           |   4 +-
 .../configuration/summary/summary.controller.js |   2 +-
 .../configuration/summary/summary.worker.js     |  13 +-
 .../frontend/app/primitives/btn-group/index.pug |  12 +-
 .../frontend/app/primitives/btn/index.scss      |   6 +
 .../frontend/app/primitives/dropdown/index.pug  |   3 +-
 .../frontend/app/primitives/dropdown/index.scss |  19 +-
 .../frontend/controllers/caches-controller.js   |  71 ++-
 .../frontend/controllers/clusters-controller.js | 190 ++++++-
 .../frontend/controllers/domains-controller.js  |   7 +-
 .../frontend/controllers/igfs-controller.js     |   9 +-
 .../frontend/public/stylesheets/style.scss      |  19 +-
 .../frontend/test/unit/Version.test.js          |  95 ++--
 .../frontend/views/configuration/caches.tpl.pug |   2 +-
 .../views/configuration/clusters.tpl.pug        |  13 +-
 .../views/configuration/domains.tpl.pug         |   2 +-
 .../frontend/views/configuration/igfs.tpl.pug   |   6 +-
 .../views/configuration/sidebar.tpl.pug         |   4 +-
 .../frontend/views/includes/header-left.pug     |   3 -
 .../frontend/views/includes/header-right.pug    |   1 -
 .../frontend/views/settings/admin.tpl.pug       |   2 +-
 .../frontend/views/settings/profile.tpl.pug     |   2 +-
 .../web-console/frontend/views/signin.tpl.pug   |   6 +-
 .../web-console/frontend/views/sql/sql.tpl.pug  |   8 +-
 .../frontend/webpack/webpack.common.js          |   8 +-
 .../frontend/webpack/webpack.dev.babel.js       |   5 +-
 .../console/agent/handlers/ClusterListener.java |  12 +-
 87 files changed, 2396 insertions(+), 572 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/backend/app/mongo.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/mongo.js b/modules/web-console/backend/app/mongo.js
index 077044c..d3bc4c0 100644
--- a/modules/web-console/backend/app/mongo.js
+++ b/modules/web-console/backend/app/mongo.js
@@ -101,7 +101,7 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
 
     // Define Domain model schema.
     const DomainModelSchema = new Schema({
-        space: {type: ObjectId, ref: 'Space', index: true},
+        space: {type: ObjectId, ref: 'Space', index: true, required: true},
         caches: [{type: ObjectId, ref: 'Cache'}],
         queryMetadata: {type: String, enum: ['Annotations', 'Configuration']},
         kind: {type: String, enum: ['query', 'store', 'both']},
@@ -139,7 +139,7 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
 
     // Define Cache schema.
     const CacheSchema = new Schema({
-        space: {type: ObjectId, ref: 'Space', index: true},
+        space: {type: ObjectId, ref: 'Space', index: true, required: true},
         name: {type: String},
         clusters: [{type: ObjectId, ref: 'Cluster'}],
         domains: [{type: ObjectId, ref: 'DomainModel'}],
@@ -180,6 +180,10 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
         },
 
         backups: Number,
+        memoryMode: {type: String, enum: ['ONHEAP_TIERED', 'OFFHEAP_TIERED', 'OFFHEAP_VALUES']},
+        offHeapMaxMemory: Number,
+        startSize: Number,
+        swapEnabled: Boolean,
 
         onheapCacheEnabled: Boolean,
 
@@ -259,16 +263,19 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
         writeBehindFlushSize: Number,
         writeBehindFlushFrequency: Number,
         writeBehindFlushThreadCount: Number,
-        writeBehindCoalescing: Boolean,
+        writeBehindCoalescing: {type: Boolean, default: true},
 
         invalidate: Boolean,
         defaultLockTimeout: Number,
+        atomicWriteOrderMode: {type: String, enum: ['CLOCK', 'PRIMARY']},
         writeSynchronizationMode: {type: String, enum: ['FULL_SYNC', 'FULL_ASYNC', 'PRIMARY_SYNC']},
 
         sqlEscapeAll: Boolean,
         sqlSchema: String,
+        sqlOnheapRowCacheSize: Number,
         longQueryWarningTimeout: Number,
         sqlFunctionClasses: [String],
+        snapshotableIndex: Boolean,
         queryDetailMetricsSize: Number,
         queryParallelism: Number,
         statisticsEnabled: Boolean,
@@ -332,15 +339,18 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
     result.Cache = mongoose.model('Cache', CacheSchema);
 
     const IgfsSchema = new Schema({
-        space: {type: ObjectId, ref: 'Space', index: true},
+        space: {type: ObjectId, ref: 'Space', index: true, required: true},
         name: {type: String},
         clusters: [{type: ObjectId, ref: 'Cluster'}],
         affinnityGroupSize: Number,
         blockSize: Number,
-        bufferSize: Number,
+        streamBufferSize: Number,
         dataCacheName: String,
         metaCacheName: String,
         defaultMode: {type: String, enum: ['PRIMARY', 'PROXY', 'DUAL_SYNC', 'DUAL_ASYNC']},
+        dualModeMaxPendingPutsSize: Number,
+        dualModePutExecutorService: String,
+        dualModePutExecutorServiceShutdown: Boolean,
         fragmentizerConcurrentFiles: Number,
         fragmentizerEnabled: Boolean,
         fragmentizerThrottlingBlockLength: Number,
@@ -354,6 +364,7 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
             threadCount: Number
         },
         ipcEndpointEnabled: Boolean,
+        maxSpaceSize: Number,
         maximumTaskRangeLength: Number,
         managementPort: Number,
         pathModes: [{path: String, mode: {type: String, enum: ['PRIMARY', 'PROXY', 'DUAL_SYNC', 'DUAL_ASYNC']}}],
@@ -361,6 +372,7 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
         perNodeParallelBatchCount: Number,
         prefetchBlocks: Number,
         sequentialReadsBeforePrefetch: Number,
+        trashPurgeTimeout: Number,
         secondaryFileSystemEnabled: Boolean,
         secondaryFileSystem: {
             uri: String,
@@ -369,7 +381,7 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
         },
         colocateMetadata: Boolean,
         relaxedConsistency: Boolean,
-        updateFileLenOnFlush: Boolean
+        updateFileLengthOnFlush: Boolean
     });
 
     IgfsSchema.index({name: 1, space: 1}, {unique: true});
@@ -379,9 +391,9 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
 
     // Define Cluster schema.
     const ClusterSchema = new Schema({
-        space: {type: ObjectId, ref: 'Space', index: true},
+        space: {type: ObjectId, ref: 'Space', index: true, required: true},
         name: {type: String},
-        activeOnStart: Boolean,
+        activeOnStart: {type: Boolean, default: true},
         localHost: String,
         discovery: {
             localAddress: String,
@@ -394,7 +406,9 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
             networkTimeout: Number,
             joinTimeout: Number,
             threadPriority: Number,
-            metricsUpdateFrequency: Number,
+            heartbeatFrequency: Number,
+            maxMissedHeartbeats: Number,
+            maxMissedClientHeartbeats: Number,
             topHistorySize: Number,
             listener: String,
             dataExchange: String,
@@ -553,6 +567,8 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
             compactFooter: Boolean
         },
         caches: [{type: ObjectId, ref: 'Cache'}],
+        clockSyncSamples: Number,
+        clockSyncFrequency: Number,
         deploymentMode: {type: String, enum: ['PRIVATE', 'ISOLATED', 'SHARED', 'CONTINUOUS']},
         discoveryStartupDelay: Number,
         igfsThreadPoolSize: Number,
@@ -578,6 +594,8 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
             }
         },
         marshalLocalJobs: Boolean,
+        marshallerCacheKeepAliveTime: Number,
+        marshallerCacheThreadPoolSize: Number,
         metricsExpireTime: Number,
         metricsHistorySize: Number,
         metricsLogFrequency: Number,
@@ -635,6 +653,16 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
         peerClassLoadingMissedResourcesCacheSize: Number,
         peerClassLoadingThreadPoolSize: Number,
         publicThreadPoolSize: Number,
+        swapSpaceSpi: {
+            kind: {type: String, enum: ['FileSwapSpaceSpi']},
+            FileSwapSpaceSpi: {
+                baseDirectory: String,
+                readStripesNumber: Number,
+                maximumSparsity: Number,
+                maxWriteQueueSize: Number,
+                writeBufferSize: Number
+            }
+        },
         systemThreadPoolSize: Number,
         timeServerPortBase: Number,
         timeServerPortRange: Number,
@@ -858,10 +886,22 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
         },
         warmupClosure: String,
         hadoopConfiguration: {
+            mapReducePlanner: {
+                kind: {type: String, enum: ['Weighted', 'Custom']},
+                Weighted: {
+                    localMapperWeight: Number,
+                    remoteMapperWeight: Number,
+                    localReducerWeight: Number,
+                    remoteReducerWeight: Number,
+                    preferLocalReducerThresholdWeight: Number
+                },
+                Custom: {
+                    className: String
+                }
+            },
             finishedJobInfoTtl: Number,
-            mapReducePlanner: String,
             maxParallelTasks: Number,
-            naxTaskQueueSize: Number,
+            maxTaskQueueSize: Number,
             nativeLibraryNames: [String]
         },
         serviceConfigurations: [{
@@ -884,10 +924,11 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
             cache: {type: ObjectId, ref: 'Cache'},
             affinityKey: String
         }],
-        cacheSanityCheckEnabled: Boolean,
+        cacheSanityCheckEnabled: {type: Boolean, default: true},
         classLoader: String,
         consistentId: String,
         failureDetectionTimeout: Number,
+        clientFailureDetectionTimeout: Number,
         workDirectory: String,
         lateAffinityAssignment: Boolean,
         utilityCacheKeepAliveTime: Number,
@@ -899,18 +940,24 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
         utilityCacheThreadPoolSize: Number,
         executorConfiguration: [{
             name: String,
-            poolSize: Number
+            size: Number
         }],
         memoryConfiguration: {
+            systemCacheInitialSize: Number,
+            systemCacheMaxSize: Number,
             pageSize: Number,
-            systemCacheMemorySize: Number,
             concurrencyLevel: Number,
             defaultMemoryPolicyName: String,
+            defaultMemoryPolicySize: Number,
             memoryPolicies: [{
                 name: String,
+                initialSize: Number,
                 maxSize: Number,
                 swapFilePath: String,
-                pageEvictionMode: {type: String, enum: ['DISABLED', 'RANDOM_LRU', 'RANDOM_2_LRU']}
+                pageEvictionMode: {type: String, enum: ['DISABLED', 'RANDOM_LRU', 'RANDOM_2_LRU']},
+                evictionThreshold: Number,
+                emptyPagesPoolSize: Number,
+                metricsEnabled: Boolean
             }]
         }
     });
@@ -922,7 +969,7 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
 
     // Define Notebook schema.
     const NotebookSchema = new Schema({
-        space: {type: ObjectId, ref: 'Space', index: true},
+        space: {type: ObjectId, ref: 'Space', index: true, required: true},
         name: String,
         expandedParagraphs: [Number],
         paragraphs: [{

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/backend/services/caches.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/services/caches.js b/modules/web-console/backend/services/caches.js
index 646fbea..19aed82 100644
--- a/modules/web-console/backend/services/caches.js
+++ b/modules/web-console/backend/services/caches.js
@@ -131,6 +131,8 @@ module.exports.factory = (_, mongo, spaceService, errors) => {
 
             return mongo.Cluster.update({caches: {$in: [cacheId]}}, {$pull: {caches: cacheId}}, {multi: true}).exec()
                 .then(() => mongo.Cluster.update({}, {$pull: {checkpointSpi: {kind: 'Cache', Cache: {cache: cacheId}}}}, {multi: true}).exec())
+                // TODO WC-201 fix clenup of cache on deletion for cluster service configuration.
+                // .then(() => mongo.Cluster.update({'serviceConfigurations.cache': cacheId}, {$unset: {'serviceConfigurations.$.cache': ''}}, {multi: true}).exec())
                 .then(() => mongo.DomainModel.update({caches: {$in: [cacheId]}}, {$pull: {caches: cacheId}}, {multi: true}).exec())
                 .then(() => mongo.Cache.remove({_id: cacheId}).exec())
                 .then(convertRemoveStatus);

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/backend/services/igfss.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/services/igfss.js b/modules/web-console/backend/services/igfss.js
index 578c642..acb565b 100644
--- a/modules/web-console/backend/services/igfss.js
+++ b/modules/web-console/backend/services/igfss.js
@@ -122,6 +122,11 @@ module.exports.factory = (_, mongo, spacesService, errors) => {
                 return Promise.reject(new errors.IllegalArgumentException('IGFS id can not be undefined or null'));
 
             return mongo.Cluster.update({igfss: {$in: [igfsId]}}, {$pull: {igfss: igfsId}}, {multi: true}).exec()
+                // TODO WC-201 fix clenup on node filter on deletion for cluster serviceConfigurations and caches.
+                // .then(() => mongo.Cluster.update({ 'serviceConfigurations.$.nodeFilter.kind': { $ne: 'IGFS' }, 'serviceConfigurations.nodeFilter.IGFS.igfs': igfsId},
+                //     {$unset: {'serviceConfigurations.$.nodeFilter.IGFS.igfs': ''}}, {multi: true}).exec())
+                // .then(() => mongo.Cluster.update({ 'serviceConfigurations.nodeFilter.kind': 'IGFS', 'serviceConfigurations.nodeFilter.IGFS.igfs': igfsId},
+                //     {$unset: {'serviceConfigurations.$.nodeFilter': ''}}, {multi: true}).exec())
                 .then(() => mongo.Igfs.remove({_id: igfsId}).exec())
                 .then(convertRemoveStatus);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/app.config.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.config.js b/modules/web-console/frontend/app/app.config.js
index 1772453..f93ee7e 100644
--- a/modules/web-console/frontend/app/app.config.js
+++ b/modules/web-console/frontend/app/app.config.js
@@ -98,7 +98,8 @@ igniteConsoleCfg.config(['$alertProvider', ($alertProvider) => {
 // AngularStrap dropdowns () configuration.
 igniteConsoleCfg.config(['$dropdownProvider', ($dropdownProvider) => {
     angular.extend($dropdownProvider.defaults, {
-        templateUrl: dropdownTemplateUrl
+        templateUrl: dropdownTemplateUrl,
+        animation: ''
     });
 }]);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/app.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.js b/modules/web-console/frontend/app/app.js
index df58f0e..ff089bb 100644
--- a/modules/web-console/frontend/app/app.js
+++ b/modules/web-console/frontend/app/app.js
@@ -103,11 +103,7 @@ import hasPojo from './filters/hasPojo.filter';
 import uiGridSubcategories from './filters/uiGridSubcategories.filter';
 
 // Controllers
-import caches from '../controllers/caches-controller';
-import clusters from '../controllers/clusters-controller';
-import domains from '../controllers/domains-controller';
-import igfs from '../controllers/igfs-controller';
-import profile from '../controllers/profile-controller';
+import profile from 'Controllers/profile-controller';
 import auth from './controllers/auth.controller';
 import resetPassword from './controllers/reset-password.controller';
 
@@ -119,6 +115,7 @@ import './components/input-dialog';
 import webConsoleHeader from './components/web-console-header';
 import webConsoleFooter from './components/web-console-footer';
 import igniteIcon from './components/ignite-icon';
+import versionPicker from './components/version-picker';
 
 // Inject external modules.
 import IgniteModules from 'IgniteModules/index';
@@ -179,6 +176,7 @@ angular
     webConsoleHeader.name,
     webConsoleFooter.name,
     igniteIcon.name,
+    versionPicker.name,
     // Ignite modules.
     IgniteModules.name
 ])
@@ -227,10 +225,6 @@ angular
 // Controllers.
 .controller(...auth)
 .controller(...resetPassword)
-.controller(...caches)
-.controller(...clusters)
-.controller(...domains)
-.controller(...igfs)
 .controller(...profile)
 // Filters.
 .filter('byName', byName)

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/components/cluster-select/cluster-select.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/cluster-select/cluster-select.pug b/modules/web-console/frontend/app/components/cluster-select/cluster-select.pug
index 444e567..a5fd08c 100644
--- a/modules/web-console/frontend/app/components/cluster-select/cluster-select.pug
+++ b/modules/web-console/frontend/app/components/cluster-select/cluster-select.pug
@@ -26,7 +26,7 @@ ul.nav(ng-switch='ctrl.clusters.length')
             label.padding-left-dflt {{ctrl.cluster.name}}
 
     li(ng-switch-default)
-        a.dropdown-toggle(bs-dropdown='' data-placement='bottom-left' data-trigger='hover focus' data-container='self' data-animation='' ng-click='$event.stopPropagation()' aria-haspopup='true' aria-expanded='expanded')
+        a.dropdown-toggle(bs-dropdown='' data-placement='bottom-left' data-trigger='hover focus' data-container='self' ng-click='$event.stopPropagation()' aria-haspopup='true' aria-expanded='expanded')
             i.icon-cluster
             label.padding-left-dflt {{ctrl.cluster.name}}
             span.caret

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js
index cb95735..d50c44a 100644
--- a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js
+++ b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js
@@ -51,7 +51,7 @@ const EMAIL_TEMPLATE = '<div class="ui-grid-cell-contents"><a ng-href="mailto:{{
 export default [
     {name: 'actions', displayName: 'Actions', categoryDisplayName: 'Actions', cellTemplate: ACTIONS_TEMPLATE, field: 'actions', minWidth: 70, width: 70, enableFiltering: false, enableSorting: false, visible: false},
     {name: 'user', displayName: 'User', categoryDisplayName: 'User', field: 'userName', cellTemplate: USER_TEMPLATE, minWidth: 160, enableFiltering: true, pinnedLeft: true, filter: { placeholder: 'Filter by name...' }},
-    {name: 'email', displayName: 'Email', categoryDisplayName: 'Email', field: 'email', cellTemplate: EMAIL_TEMPLATE, minWidth: 160, enableFiltering: false, filter: { placeholder: 'Filter by email...' }},
+    {name: 'email', displayName: 'Email', categoryDisplayName: 'Email', field: 'email', cellTemplate: EMAIL_TEMPLATE, minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by email...' }},
     {name: 'company', displayName: 'Company', categoryDisplayName: 'Company', field: 'company', minWidth: 180, enableFiltering: true, filter: { placeholder: 'Filter by company...' }},
     {name: 'country', displayName: 'Country', categoryDisplayName: 'Country', field: 'countryCode', minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by country...' }},
     {name: 'lastlogin', displayName: 'Last login', categoryDisplayName: 'Last login', field: 'lastLogin', cellFilter: 'date:"M/d/yy HH:mm"', minWidth: 120, width: 120, enableFiltering: false, visible: false},

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/components/version-picker/component.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/version-picker/component.js b/modules/web-console/frontend/app/components/version-picker/component.js
new file mode 100644
index 0000000..68382ee
--- /dev/null
+++ b/modules/web-console/frontend/app/components/version-picker/component.js
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+import template from './template.pug';
+import './style.scss';
+
+export default {
+    template,
+    controller: class {
+        static $inject = ['IgniteVersion', '$scope'];
+
+        constructor(Version, $scope) {
+            this.currentSbj = Version.currentSbj;
+            this.supportedVersions = Version.supportedVersions;
+
+            const dropdownToggle = (active) => {
+                this.isActive = active;
+
+                // bs-dropdown does not call apply on callbacks
+                $scope.$apply();
+            };
+
+            this.onDropdownShow = () => dropdownToggle(true);
+            this.onDropdownHide = () => dropdownToggle(false);
+        }
+
+        $onInit() {
+            this.dropdown = _.map(this.supportedVersions, (ver) => ({
+                text: ver.label,
+                click: () => this.currentSbj.next(ver)
+            }));
+
+            this.currentSbj.subscribe({
+                next: (ver) => this.currentVersion = ver.label
+            });
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/components/version-picker/index.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/version-picker/index.js b/modules/web-console/frontend/app/components/version-picker/index.js
new file mode 100644
index 0000000..f58753e
--- /dev/null
+++ b/modules/web-console/frontend/app/components/version-picker/index.js
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+import angular from 'angular';
+import component from './component';
+
+export default angular
+    .module('ignite-console.version-picker', [
+        'ignite-console.configuration'
+    ])
+    .component('versionPicker', component);

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/components/version-picker/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/version-picker/style.scss b/modules/web-console/frontend/app/components/version-picker/style.scss
new file mode 100644
index 0000000..98a4e9d
--- /dev/null
+++ b/modules/web-console/frontend/app/components/version-picker/style.scss
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+version-picker {
+    display: inline-flex;
+    align-items: center;
+
+    .btn-ignite {
+        border-radius: 9px;
+        min-height: 0;
+        font-size: 12px;
+        font-weight: bold;
+        line-height: 17px;
+        padding-top: 0;
+        padding-bottom: 1px;
+    }
+
+    .icon-help {
+        margin-left: 5px;
+        font-size: 16px;
+    }
+
+    .dropdown-menu a {
+        // Fixes style leak from above
+        font-size: 14px !important;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/components/version-picker/template.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/version-picker/template.pug b/modules/web-console/frontend/app/components/version-picker/template.pug
new file mode 100644
index 0000000..1abe471
--- /dev/null
+++ b/modules/web-console/frontend/app/components/version-picker/template.pug
@@ -0,0 +1,33 @@
+//-
+    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.
+
+.btn-ignite.btn-ignite--primary(
+    bs-dropdown='$ctrl.dropdown'
+    data-trigger='hover focus'
+    bs-on-before-show='$ctrl.onDropdownShow'
+    bs-on-before-hide='$ctrl.onDropdownHide'
+    data-container='self'
+    ng-class='{"active": $ctrl.isActive }'
+)
+    | {{$ctrl.currentVersion}}
+    span.icon-right.fa.fa-caret-down
+    
+i.icon-help(
+    bs-tooltip=''
+    data-title='Web Console supports multiple Ignite versions.<br /> \
+                Select version you need to configure cluster.'
+    data-placement='right'
+)

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/data/event-groups.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/event-groups.json b/modules/web-console/frontend/app/data/event-groups.json
index 094fd28..8d0c878 100644
--- a/modules/web-console/frontend/app/data/event-groups.json
+++ b/modules/web-console/frontend/app/data/event-groups.json
@@ -97,6 +97,8 @@
       "EVT_CACHE_OBJECT_REMOVED",
       "EVT_CACHE_OBJECT_LOCKED",
       "EVT_CACHE_OBJECT_UNLOCKED",
+      "EVT_CACHE_OBJECT_SWAPPED",
+      "EVT_CACHE_OBJECT_UNSWAPPED",
       "EVT_CACHE_OBJECT_EXPIRED"
     ]
   },
@@ -134,6 +136,18 @@
     ]
   },
   {
+    "label": "EVTS_SWAPSPACE",
+    "value": "EVTS_SWAPSPACE",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_SWAP_SPACE_CLEARED",
+      "EVT_SWAP_SPACE_DATA_REMOVED",
+      "EVT_SWAP_SPACE_DATA_READ",
+      "EVT_SWAP_SPACE_DATA_STORED",
+      "EVT_SWAP_SPACE_DATA_EVICTED"
+    ]
+  },
+  {
     "label": "EVTS_IGFS",
     "value": "EVTS_IGFS",
     "class": "org.apache.ignite.events.EventType",

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/directives/ui-ace-docker/ui-ace-docker.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/directives/ui-ace-docker/ui-ace-docker.controller.js b/modules/web-console/frontend/app/directives/ui-ace-docker/ui-ace-docker.controller.js
index de335ae..8ebaae4 100644
--- a/modules/web-console/frontend/app/directives/ui-ace-docker/ui-ace-docker.controller.js
+++ b/modules/web-console/frontend/app/directives/ui-ace-docker/ui-ace-docker.controller.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-export default ['$scope', 'IgniteDockerGenerator', function($scope, docker) {
+export default ['$scope', 'IgniteVersion', 'IgniteDockerGenerator', function($scope, Version, docker) {
     const ctrl = this;
 
     // Watchers definition.
@@ -25,9 +25,13 @@ export default ['$scope', 'IgniteDockerGenerator', function($scope, docker) {
         if (!$scope.cluster)
             return;
 
-        ctrl.data = docker.generate($scope.cluster, 'latest');
+        ctrl.data = docker.generate($scope.cluster, Version.currentSbj.getValue());
     };
 
     // Setup watchers.
+    Version.currentSbj.subscribe({
+        next: clusterWatcher
+    });
+
     $scope.$watch('cluster', clusterWatcher);
 }];

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.controller.js b/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.controller.js
index 7e7a0e4..66a10af 100644
--- a/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.controller.js
+++ b/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.controller.js
@@ -15,19 +15,21 @@
  * limitations under the License.
  */
 
-export default ['$scope', 'JavaTransformer', function($scope, java) {
+export default ['IgniteVersion', 'JavaTransformer', function(Version, java) {
     const ctrl = this;
 
     delete ctrl.data;
 
     const client = ctrl.client === 'true';
 
+    const available = Version.available.bind(Version);
+
     // Setup generator.
     switch (ctrl.generator) {
         case 'igniteConfiguration':
             const clsName = client ? 'ClientConfigurationFactory' : 'ServerConfigurationFactory';
 
-            ctrl.generate = (cluster) => java.cluster(cluster, 'config', clsName, client);
+            ctrl.generate = (cluster) => java.cluster(cluster, Version.current, 'config', clsName, client);
 
             break;
         case 'clusterCaches':
@@ -39,9 +41,9 @@ export default ['$scope', 'JavaTransformer', function($scope, java) {
                     return acc;
                 }, []);
 
-                const cfg = java.generator.clusterGeneral(cluster);
+                const cfg = java.generator.clusterGeneral(cluster, available);
 
-                java.generator.clusterCaches(cluster, clusterCaches, null, false, cfg);
+                java.generator.clusterCaches(cluster, clusterCaches, null, available, false, cfg);
 
                 return java.toSection(cfg);
             };
@@ -57,7 +59,7 @@ export default ['$scope', 'JavaTransformer', function($scope, java) {
                     return acc;
                 }, []);
 
-                return java[ctrl.generator](cache, cacheDomains);
+                return java[ctrl.generator](cache, cacheDomains, available);
             };
 
             break;
@@ -73,6 +75,19 @@ export default ['$scope', 'JavaTransformer', function($scope, java) {
             };
 
             break;
+        case 'clusterServiceConfiguration':
+            ctrl.generate = (cluster, caches) => {
+                const clusterCaches = _.reduce(caches, (acc, cache) => {
+                    if (_.includes(cluster.caches, cache.value))
+                        acc.push(cache.cache);
+
+                    return acc;
+                }, []);
+
+                return java.clusterServiceConfiguration(cluster.serviceConfigurations, clusterCaches);
+            };
+
+            break;
         case 'igfss':
             ctrl.generate = (cluster, igfss) => {
                 const clusterIgfss = _.reduce(igfss, (acc, igfs) => {
@@ -82,11 +97,11 @@ export default ['$scope', 'JavaTransformer', function($scope, java) {
                     return acc;
                 }, []);
 
-                return java.clusterIgfss(clusterIgfss);
+                return java.clusterIgfss(clusterIgfss, available);
             };
 
             break;
         default:
-            ctrl.generate = (master, detail) => java[ctrl.generator](master, detail);
+            ctrl.generate = (master) => java[ctrl.generator](master, available);
     }
 }];

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.directive.js b/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.directive.js
index 5f43b23..5d1df42 100644
--- a/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.directive.js
+++ b/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.directive.js
@@ -18,7 +18,7 @@
 import template from './ui-ace-java.pug';
 import controller from './ui-ace-java.controller';
 
-export default ['igniteUiAceJava', [() => {
+export default ['igniteUiAceJava', ['IgniteVersion', (Version) => {
     const link = (scope, $el, attrs, [ctrl, igniteUiAceTabs, formCtrl, ngModelCtrl]) => {
         if (formCtrl && ngModelCtrl)
             formCtrl.$removeControl(ngModelCtrl);
@@ -36,10 +36,14 @@ export default ['igniteUiAceJava', [() => {
 
         const noDeepWatch = !(typeof attrs.noDeepWatch !== 'undefined');
 
-        // Setup watchers.
-        scope.$watch('master', () => {
+        const next = () => {
             ctrl.data = _.isNil(scope.master) ? null : ctrl.generate(scope.master, scope.detail).asString();
-        }, noDeepWatch);
+        };
+
+        // Setup watchers.
+        scope.$watch('master', next, noDeepWatch);
+
+        Version.currentSbj.subscribe({next});
     };
 
     return {

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/directives/ui-ace-pom/ui-ace-pom.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/directives/ui-ace-pom/ui-ace-pom.controller.js b/modules/web-console/frontend/app/directives/ui-ace-pom/ui-ace-pom.controller.js
index 0ae1269..0135eb3 100644
--- a/modules/web-console/frontend/app/directives/ui-ace-pom/ui-ace-pom.controller.js
+++ b/modules/web-console/frontend/app/directives/ui-ace-pom/ui-ace-pom.controller.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-export default ['$scope', 'IgniteMavenGenerator', function($scope, maven) {
+export default ['$scope', 'IgniteVersion', 'IgniteMavenGenerator', function($scope, Version, maven) {
     const ctrl = this;
 
     // Watchers definition.
@@ -25,9 +25,13 @@ export default ['$scope', 'IgniteMavenGenerator', function($scope, maven) {
         if (!value)
             return;
 
-        ctrl.data = maven.generate($scope.cluster);
+        ctrl.data = maven.generate($scope.cluster, Version.currentSbj.getValue());
     };
 
     // Setup watchers.
+    Version.currentSbj.subscribe({
+        next: clusterWatcher
+    });
+
     $scope.$watch('cluster', clusterWatcher);
 }];

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/directives/ui-ace-spring/ui-ace-spring.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/directives/ui-ace-spring/ui-ace-spring.controller.js b/modules/web-console/frontend/app/directives/ui-ace-spring/ui-ace-spring.controller.js
index 50b71cb..92b0ae8 100644
--- a/modules/web-console/frontend/app/directives/ui-ace-spring/ui-ace-spring.controller.js
+++ b/modules/web-console/frontend/app/directives/ui-ace-spring/ui-ace-spring.controller.js
@@ -15,15 +15,17 @@
  * limitations under the License.
  */
 
-export default ['$scope', 'SpringTransformer', function($scope, spring) {
+export default ['IgniteVersion', 'SpringTransformer', function(Version, spring) {
     const ctrl = this;
 
     delete ctrl.data;
 
+    const targetSince = Version.available.bind(Version);
+
     // Setup generator.
     switch (ctrl.generator) {
         case 'igniteConfiguration':
-            ctrl.generate = (cluster) => spring.cluster(cluster, ctrl.client === 'true');
+            ctrl.generate = (cluster) => spring.cluster(cluster, Version.current, ctrl.client === 'true');
 
             break;
         case 'clusterCaches':
@@ -35,9 +37,9 @@ export default ['$scope', 'SpringTransformer', function($scope, spring) {
                     return acc;
                 }, []);
 
-                const cfg = spring.generator.clusterGeneral(cluster);
+                const cfg = spring.generator.clusterGeneral(cluster, targetSince);
 
-                spring.generator.clusterCaches(cluster, clusterCaches, null, false, cfg);
+                spring.generator.clusterCaches(cluster, clusterCaches, null, targetSince, false, cfg);
 
                 return spring.toSection(cfg);
             };
@@ -53,7 +55,7 @@ export default ['$scope', 'SpringTransformer', function($scope, spring) {
                     return acc;
                 }, []);
 
-                return spring[ctrl.generator](cache, cacheDomains);
+                return spring[ctrl.generator](cache, cacheDomains, targetSince);
             };
 
             break;
@@ -69,6 +71,19 @@ export default ['$scope', 'SpringTransformer', function($scope, spring) {
             };
 
             break;
+        case 'clusterServiceConfiguration':
+            ctrl.generate = (cluster, caches) => {
+                const clusterCaches = _.reduce(caches, (acc, cache) => {
+                    if (_.includes(cluster.caches, cache.value))
+                        acc.push(cache.cache);
+
+                    return acc;
+                }, []);
+
+                return spring.clusterServiceConfiguration(cluster.serviceConfigurations, clusterCaches);
+            };
+
+            break;
         case 'igfss':
             ctrl.generate = (cluster, igfss) => {
                 const clusterIgfss = _.reduce(igfss, (acc, igfs) => {
@@ -78,11 +93,11 @@ export default ['$scope', 'SpringTransformer', function($scope, spring) {
                     return acc;
                 }, []);
 
-                return spring.clusterIgfss(clusterIgfss);
+                return spring.clusterIgfss(clusterIgfss, targetSince);
             };
 
             break;
         default:
-            ctrl.generate = (master, detail) => spring[ctrl.generator](master, detail);
+            ctrl.generate = (master) => spring[ctrl.generator](master, targetSince);
     }
 }];

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/directives/ui-ace-spring/ui-ace-spring.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/directives/ui-ace-spring/ui-ace-spring.directive.js b/modules/web-console/frontend/app/directives/ui-ace-spring/ui-ace-spring.directive.js
index de3f434..953d6cd 100644
--- a/modules/web-console/frontend/app/directives/ui-ace-spring/ui-ace-spring.directive.js
+++ b/modules/web-console/frontend/app/directives/ui-ace-spring/ui-ace-spring.directive.js
@@ -20,7 +20,7 @@ import _ from 'lodash';
 import template from './ui-ace-spring.pug';
 import controller from './ui-ace-spring.controller';
 
-export default ['igniteUiAceSpring', [() => {
+export default ['igniteUiAceSpring', ['IgniteVersion', (Version) => {
     const link = (scope, $el, attrs, [ctrl, igniteUiAceTabs, formCtrl, ngModelCtrl]) => {
         if (formCtrl && ngModelCtrl)
             formCtrl.$removeControl(ngModelCtrl);
@@ -39,10 +39,14 @@ export default ['igniteUiAceSpring', [() => {
 
         const noDeepWatch = !(typeof attrs.noDeepWatch !== 'undefined');
 
-        // Setup watchers.
-        scope.$watch('master', () => {
+        const next = () => {
             ctrl.data = _.isNil(scope.master) ? null : ctrl.generate(scope.master, scope.detail).asString();
-        }, noDeepWatch);
+        };
+
+        // Setup watchers.
+        scope.$watch('master', next, noDeepWatch);
+
+        Version.currentSbj.subscribe({next});
     };
 
     return {

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/helpers/jade/mixins.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/helpers/jade/mixins.pug b/modules/web-console/frontend/app/helpers/jade/mixins.pug
index 3176cb8..a357966 100644
--- a/modules/web-console/frontend/app/helpers/jade/mixins.pug
+++ b/modules/web-console/frontend/app/helpers/jade/mixins.pug
@@ -66,9 +66,9 @@ mixin save-remove-clone-undo-buttons(objectName)
         .panel-tip-container(ng-show='backupItem._id')
             a.btn.btn-primary(id='clone-item' ng-click='cloneItem()' bs-tooltip=cloneTip data-placement='bottom' data-trigger='hover') Clone
 
-        -var actions = [{ text: "Remove", click: "removeItem()" }, { text: "Remove All", click: "removeAllItems()" }]
+        -var options = [{ text: "Remove", click: "removeItem()" }, { text: "Remove All", click: "removeAllItems()" }]
 
-        +btn-group(actions, removeTip)(ng-show='backupItem._id')
+        +btn-group(false, options, removeTip)(ng-show='backupItem._id')
 
         .panel-tip-container(ng-show='backupItem')
             i.btn.btn-primary.fa.fa-undo(id='undo-item' ng-disabled='!ui.inputForm.$dirty' ng-click='ui.inputForm.$dirty && resetAll()' bs-tooltip=undoTip data-placement='bottom' data-trigger='hover')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/agent/AgentManager.service.js b/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
index 3344ef2..58e071b 100644
--- a/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
+++ b/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
@@ -45,12 +45,14 @@ export default class IgniteAgentManager {
 
         this.ignite2x = false;
 
-        $root.$watch(() => _.get(this, 'cluster.clusterVersion'), (ver) => {
-            if (_.isEmpty(ver))
-                return;
+        if (!$root.IgniteDemoMode) {
+            $root.$watch(() => _.get(this, 'cluster.clusterVersion'), (ver) => {
+                if (_.isEmpty(ver))
+                    return;
 
-            this.ignite2x = ver.startsWith('2.');
-        }, true);
+                this.ignite2x = ver.startsWith('2.');
+            }, true);
+        }
 
         /**
          * Connection to backend.
@@ -509,6 +511,9 @@ export default class IgniteAgentManager {
      * @returns {Promise}
      */
     queryNextPage(nid, queryId, pageSize) {
+        if (this.ignite2x)
+            return this.visorTask('queryFetchX2', nid, queryId, pageSize);
+
         return this.visorTask('queryFetch', nid, queryId, pageSize);
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/cluster/Cache.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/cluster/Cache.js b/modules/web-console/frontend/app/modules/cluster/Cache.js
index f954ad2..4918a7c 100644
--- a/modules/web-console/frontend/app/modules/cluster/Cache.js
+++ b/modules/web-console/frontend/app/modules/cluster/Cache.js
@@ -40,6 +40,10 @@ export default class Cache {
         this.offHeapPrimarySize = cache.offHeapPrimaryEntriesCount || 0;
         this.offHeapBackupSize = cache.offHeapBackupEntriesCount || 0;
 
+        // Swap.
+        this.swapSize = cache.swapSize;
+        this.swapKeys = cache.swapKeys;
+
         const m = cache.metrics;
 
         // Read/write metrics.

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/cluster/CacheMetrics.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/cluster/CacheMetrics.js b/modules/web-console/frontend/app/modules/cluster/CacheMetrics.js
index 160b7d1..90d3a9b 100644
--- a/modules/web-console/frontend/app/modules/cluster/CacheMetrics.js
+++ b/modules/web-console/frontend/app/modules/cluster/CacheMetrics.js
@@ -40,6 +40,10 @@ export default class CacheMetrics {
         this.offHeapPrimarySize = cache.offHeapPrimaryEntriesCount || 0;
         this.offHeapBackupSize = cache.offHeapBackupEntriesCount || 0;
 
+        // Swap.
+        this.swapSize = cache.swapSize;
+        this.swapKeys = cache.swapKeys;
+
         const m = cache.metrics;
 
         // Read/write metrics.

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/Version.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/Version.service.js b/modules/web-console/frontend/app/modules/configuration/Version.service.js
index 1cbe635..cf2bfc5 100644
--- a/modules/web-console/frontend/app/modules/configuration/Version.service.js
+++ b/modules/web-console/frontend/app/modules/configuration/Version.service.js
@@ -15,96 +15,148 @@
  * limitations under the License.
  */
 
+import { BehaviorSubject } from 'rxjs/BehaviorSubject';
+
 /**
  * Utility service for version parsing and comparing
  */
 const VERSION_MATCHER = /(\d+)\.(\d+)\.(\d+)([-.]([^0123456789][^-]+)(-SNAPSHOT)?)?(-(\d+))?(-([\da-f]+))?/i;
 
-const numberComparator = (a, b) => a > b ? 1 : a < b ? -1 : 0;
+/**
+ * Tries to parse product version from it's string representation.
+ *
+ * @param {String} ver - String representation of version.
+ * @returns {{major: Number, minor: Number, maintenance: Number, stage: String, revTs: Number, revHash: String}} - Object that contains product version fields.
+ */
+const parse = (ver) => {
+    // Development or built from source ZIP.
+    ver = ver.replace(/(-DEV|-n\/a)$/i, '');
+
+    const [, major, minor, maintenance, stage, ...chunks] = ver.match(VERSION_MATCHER);
+
+    return {
+        major: parseInt(major, 10),
+        minor: parseInt(minor, 10),
+        maintenance: parseInt(maintenance, 10),
+        stage: (stage || '').substring(1),
+        revTs: chunks[2] ? parseInt(chunks[3], 10) : 0,
+        revHash: chunks[4] ? chunks[5] : null
+    };
+};
 
-export default class IgniteVersion {
-    /** Current product version. */
-    static ignite = '2.0.0';
+const numberComparator = (a, b) => a > b ? 1 : a < b ? -1 : 0;
 
-    /**
-     * Tries to parse product version from it's string representation.
-     *
-     * @param {String} ver - String representation of version.
-     * @returns {{major: Number, minor: Number, maintenance: Number, stage: String, revTs: Number, revHash: String}} - Object that contains product version fields.
-     */
-    parse(ver) {
-        // Development or built from source ZIP.
-        ver = ver.replace(/(-DEV|-n\/a)$/i, '');
-
-        const [, major, minor, maintenance, stage, ...chunks] = ver.match(VERSION_MATCHER);
-
-        return {
-            major: parseInt(major, 10),
-            minor: parseInt(minor, 10),
-            maintenance: parseInt(maintenance, 10),
-            stage: (stage || '').substring(1),
-            revTs: chunks[2] ? parseInt(chunks[3], 10) : 0,
-            revHash: chunks[4] ? chunks[5] : null
-        };
-    }
+/**
+ * Compare to version.
+ * @param a {Object} first compared version.
+ * @param b {Object} second compared version.
+ * @returns {Number} 1 if a > b, 0 if versions equals, -1 if a < b
+ */
+const compare = (a, b) => {
+    let res = numberComparator(a.major, b.major);
 
-    /**
-     * Compare to version.
-     * @param a {String} first compared version.
-     * @param b {String} second compared version.
-     * @returns {Number} 1 if a > b, 0 if versions equals, -1 if a < b
-     */
-    compare(a, b) {
-        const pa = this.parse(a);
-        const pb = this.parse(b);
+    if (res !== 0)
+        return res;
 
-        let res = numberComparator(pa.major, pb.major);
+    res = numberComparator(a.minor, b.minor);
 
-        if (res !== 0)
-            return res;
+    if (res !== 0)
+        return res;
 
-        res = numberComparator(pa.minor, pb.minor);
+    res = numberComparator(a.maintenance, b.maintenance);
 
-        if (res !== 0)
-            return res;
+    if (res !== 0)
+        return res;
 
-        res = numberComparator(pa.maintenance, pb.maintenance);
+    return numberComparator(a.revTs, b.revTs);
+};
 
-        if (res !== 0)
-            return res;
+export default class IgniteVersion {
+    constructor() {
+        this.supportedVersions = [
+            {
+                label: 'Ignite 2.0',
+                ignite: '2.0.0'
+            },
+            {
+                label: 'Ignite 1.x',
+                ignite: '1.9.0'
+            }
+        ];
+
+        /** Current product version. */
+        let current = _.head(this.supportedVersions);
+
+        try {
+            const ignite = localStorage.configurationVersion;
+
+            const restored = _.find(this.supportedVersions, {ignite});
+
+            if (restored)
+                current = restored;
+        }
+        catch (ignored) {
+            // No-op.
+        }
+
+        this.currentSbj = new BehaviorSubject(current);
+
+        this.currentSbj.subscribe({
+            next: (ver) => {
+                try {
+                    localStorage.setItem('configurationVersion', ver.ignite);
+                }
+                catch (ignored) {
+                    // No-op.
+                }
+            }
+        });
+    }
 
-        return numberComparator(pa.revTs, pb.revTs);
+    /**
+     * @return {String} Target Ignite version.
+     */
+    get current() {
+        return this.currentSbj.getValue().ignite;
     }
 
     /**
-     * Check if node version in range
-     * @param {String} nodeVer Node version.
-     * @param {Array.<String>} ranges Version ranges to compare with.
-     * @returns {Boolean} `True` if node version is equal or greater than specified range.
+     * Check if version in range
+     * @param {String} target Target version.
+     * @param {String | Array.<String>} ranges Version ranges to compare with.
+     * @returns {Boolean} `True` if version is equal or greater than specified range.
      */
-    includes(nodeVer, ...ranges) {
-        return !!_.find(ranges, ([after, before]) =>
-            this.compare(nodeVer, after) >= 0 && (_.isNil(before) || this.compare(nodeVer, before) < 0)
-        );
+    since(target, ...ranges) {
+        const targetVer = parse(target);
+
+        return !!_.find(ranges, (range) => {
+            if (_.isArray(range)) {
+                const [after, before] = range;
+
+                return compare(targetVer, parse(after)) >= 0 &&
+                    (_.isNil(before) || compare(targetVer, parse(before)) < 0);
+            }
+
+            return compare(targetVer, parse(range)) >= 0;
+        });
     }
 
     /**
-     * Check if node version is newer or same
-     * @param {String} nodeVer Node version.
-     * @param {String} sinceVer Version to compare with.
-     * @returns {Boolean} `True` if node version is equal or greater than specified version.
+     * Check whether version before than specified version.
+     * @param {String} target Target version.
+     * @param {String} ranges Version ranges to compare with.
+     * @return {Boolean} `True` if version before than specified version.
      */
-    since(nodeVer, sinceVer) {
-        return this.includes(nodeVer, [sinceVer]);
+    before(target, ...ranges) {
+        return !this.since(target, ...ranges);
     }
 
     /**
-     * Check whether node version before than specified version.
-     * @param {String} nodeVer Node version.
-     * @param {String} sinceVer Version to compare with.
-     * @return {Boolean} `True` if node version before than specified version.
+     * Check if configuration version in range
+     * @param {String|Array.<String>} ranges Version ranges to compare with.
+     * @returns {Boolean} `True` if configuration version is equal or greater than specified range.
      */
-    before(nodeVer, sinceVer) {
-        return !this.since(nodeVer, sinceVer);
+    available(...ranges) {
+        return this.since(this.current, ...ranges);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/AbstractTransformer.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/AbstractTransformer.js b/modules/web-console/frontend/app/modules/configuration/generator/AbstractTransformer.js
index e008fc6..20393c5 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/AbstractTransformer.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/AbstractTransformer.js
@@ -18,7 +18,6 @@
 import StringBuilder from './StringBuilder';
 
 import IgniteConfigurationGenerator from './ConfigurationGenerator';
-import IgniteEventGroups from './defaults/Event-groups.service';
 
 import IgniteClusterDefaults from './defaults/Cluster.service';
 import IgniteCacheDefaults from './defaults/Cache.service';
@@ -33,7 +32,6 @@ const igfsDflts = new IgniteIGFSDefaults();
 export default class AbstractTransformer {
     static generator = IgniteConfigurationGenerator;
     static javaTypes = new JavaTypes(clusterDflts, cacheDflts, igfsDflts);
-    static eventGroups = new IgniteEventGroups();
 
     // Append comment with time stamp.
     static mainComment(sb, ...lines) {
@@ -61,8 +59,8 @@ export default class AbstractTransformer {
     }
 
     // Generate general section.
-    static clusterGeneral(cluster) {
-        return this.toSection(this.generator.clusterGeneral(cluster));
+    static clusterGeneral(cluster, available) {
+        return this.toSection(this.generator.clusterGeneral(cluster, available));
     }
 
     // Generate atomics group.
@@ -96,28 +94,33 @@ export default class AbstractTransformer {
     }
 
     // Generate deployment group.
-    static clusterDeployment(cluster) {
-        return this.toSection(this.generator.clusterDeployment(cluster));
+    static clusterDeployment(cluster, available) {
+        return this.toSection(this.generator.clusterDeployment(cluster, available));
     }
 
     // Generate discovery group.
-    static clusterDiscovery(disco) {
-        return this.toSection(this.generator.clusterDiscovery(disco));
+    static clusterDiscovery(disco, available) {
+        return this.toSection(this.generator.clusterDiscovery(disco, available));
     }
 
     // Generate events group.
-    static clusterEvents(cluster) {
-        return this.toSection(this.generator.clusterEvents(cluster));
+    static clusterEvents(cluster, available) {
+        return this.toSection(this.generator.clusterEvents(cluster, available));
     }
 
     // Generate failover group.
-    static clusterFailover(cluster) {
-        return this.toSection(this.generator.clusterFailover(cluster));
+    static clusterFailover(cluster, available) {
+        return this.toSection(this.generator.clusterFailover(cluster, available));
+    }
+
+    // Generate hadoop group.
+    static clusterHadoop(hadoop) {
+        return this.toSection(this.generator.clusterHadoop(hadoop));
     }
 
     // Generate cluster IGFSs group.
-    static clusterIgfss(igfss) {
-        return this.toSection(this.generator.clusterIgfss(igfss));
+    static clusterIgfss(igfss, available) {
+        return this.toSection(this.generator.clusterIgfss(igfss, available));
     }
 
     // Generate load balancing SPI group.
@@ -130,14 +133,24 @@ export default class AbstractTransformer {
         return this.toSection(this.generator.clusterLogger(cluster));
     }
 
+    // Generate memory configuration group.
+    static clusterMemory(memoryConfiguration) {
+        return this.toSection(this.generator.clusterMemory(memoryConfiguration));
+    }
+
+    // Generate marshaller group.
+    static clusterMisc(cluster, available) {
+        return this.toSection(this.generator.clusterMisc(cluster, available));
+    }
+
     // Generate marshaller group.
-    static clusterMarshaller(cluster) {
-        return this.toSection(this.generator.clusterMarshaller(cluster));
+    static clusterMarshaller(cluster, available) {
+        return this.toSection(this.generator.clusterMarshaller(cluster, available));
     }
 
     // Generate metrics group.
-    static clusterMetrics(cluster) {
-        return this.toSection(this.generator.clusterMetrics(cluster));
+    static clusterMetrics(cluster, available) {
+        return this.toSection(this.generator.clusterMetrics(cluster, available));
     }
 
     // Generate ODBC group.
@@ -145,19 +158,29 @@ export default class AbstractTransformer {
         return this.toSection(this.generator.clusterODBC(odbc));
     }
 
+    // Generate cache node filter group.
+    static clusterServiceConfiguration(srvs, caches) {
+        return this.toSection(this.generator.clusterServiceConfiguration(srvs, caches));
+    }
+
     // Generate ssl group.
     static clusterSsl(cluster) {
         return this.toSection(this.generator.clusterSsl(cluster));
     }
 
+    // Generate swap group.
+    static clusterSwap(cluster) {
+        return this.toSection(this.generator.clusterSwap(cluster));
+    }
+
     // Generate time group.
-    static clusterTime(cluster) {
-        return this.toSection(this.generator.clusterTime(cluster));
+    static clusterTime(cluster, available) {
+        return this.toSection(this.generator.clusterTime(cluster, available));
     }
 
     // Generate thread pools group.
-    static clusterPools(cluster) {
-        return this.toSection(this.generator.clusterPools(cluster));
+    static clusterPools(cluster, available) {
+        return this.toSection(this.generator.clusterPools(cluster, available));
     }
 
     // Generate transactions group.
@@ -171,8 +194,8 @@ export default class AbstractTransformer {
     }
 
     // Generate IGFS general group.
-    static igfsGeneral(igfs) {
-        return this.toSection(this.generator.igfsGeneral(igfs));
+    static igfsGeneral(igfs, available) {
+        return this.toSection(this.generator.igfsGeneral(igfs, available));
     }
 
     // Generate IGFS secondary file system group.
@@ -190,39 +213,44 @@ export default class AbstractTransformer {
         return this.toSection(this.generator.igfsFragmentizer(igfs));
     }
 
+    // Generate IGFS Dual mode group.
+    static igfsDualMode(igfs) {
+        return this.toSection(this.generator.igfsDualMode(igfs));
+    }
+
     // Generate IGFS miscellaneous group.
-    static igfsMisc(igfs) {
-        return this.toSection(this.generator.igfsMisc(igfs));
+    static igfsMisc(igfs, available) {
+        return this.toSection(this.generator.igfsMisc(igfs, available));
     }
 
     // Generate cache general group.
-    static cacheGeneral(cache) {
-        return this.toSection(this.generator.cacheGeneral(cache));
+    static cacheGeneral(cache, available) {
+        return this.toSection(this.generator.cacheGeneral(cache, available));
     }
 
     // Generate cache memory group.
-    static cacheAffinity(cache) {
-        return this.toSection(this.generator.cacheAffinity(cache));
+    static cacheAffinity(cache, available) {
+        return this.toSection(this.generator.cacheAffinity(cache, available));
     }
 
     // Generate cache memory group.
-    static cacheMemory(cache) {
-        return this.toSection(this.generator.cacheMemory(cache));
+    static cacheMemory(cache, available) {
+        return this.toSection(this.generator.cacheMemory(cache, available));
     }
 
     // Generate cache queries & Indexing group.
-    static cacheQuery(cache, domains) {
-        return this.toSection(this.generator.cacheQuery(cache, domains));
+    static cacheQuery(cache, domains, available) {
+        return this.toSection(this.generator.cacheQuery(cache, domains, available));
     }
 
     // Generate cache store group.
-    static cacheStore(cache, domains) {
-        return this.toSection(this.generator.cacheStore(cache, domains));
+    static cacheStore(cache, domains, available) {
+        return this.toSection(this.generator.cacheStore(cache, domains, available));
     }
 
     // Generate cache concurrency control group.
-    static cacheConcurrency(cache) {
-        return this.toSection(this.generator.cacheConcurrency(cache));
+    static cacheConcurrency(cache, available) {
+        return this.toSection(this.generator.cacheConcurrency(cache, available));
     }
 
     // Generate cache node filter group.
@@ -251,12 +279,12 @@ export default class AbstractTransformer {
     }
 
     // Generate caches configs.
-    static clusterCaches(cluster, caches, igfss, client) {
-        return this.toSection(this.generator.clusterCaches(cluster, caches, igfss, client));
+    static clusterCaches(cluster, available, caches, igfss, client) {
+        return this.toSection(this.generator.clusterCaches(cluster, caches, igfss, available, client));
     }
 
     // Generate caches configs.
-    static clusterCheckpoint(cluster, caches) {
+    static clusterCheckpoint(cluster, available, caches) {
         return this.toSection(this.generator.clusterCheckpoint(cluster, caches));
     }
 


[44/50] [abbrv] ignite git commit: IGNITE-5380: Added SQL query entity conflicts validation in discovery thread. This closes #2082.

Posted by sb...@apache.org.
IGNITE-5380: Added SQL query entity conflicts validation in discovery thread. This closes #2082.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/de658caf
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/de658caf
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/de658caf

Branch: refs/heads/ignite-5075
Commit: de658caf8e21971659ba601bdf7132de32a793d1
Parents: ae4d073
Author: Alexander Paschenko <al...@gmail.com>
Authored: Mon Jun 5 21:34:25 2017 +0300
Committer: devozerov <pp...@gmail.com>
Committed: Mon Jun 5 21:34:25 2017 +0300

----------------------------------------------------------------------
 .../processors/cache/ClusterCachesInfo.java     |  11 ++
 .../processors/cache/GridCacheUtils.java        |   3 +
 .../processors/query/GridQueryProcessor.java    |  12 ++-
 .../internal/processors/query/QueryUtils.java   |  44 ++++++++
 .../query/h2/ddl/DdlStatementsProcessor.java    |  18 +++-
 .../cache/index/H2DynamicTableSelfTest.java     | 106 +++++++++++++++----
 6 files changed, 173 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/de658caf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
index 7ff5622..e4d2668 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
@@ -40,6 +40,8 @@ import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.query.QuerySchema;
+import org.apache.ignite.internal.processors.query.QueryUtils;
+import org.apache.ignite.internal.processors.query.schema.SchemaOperationException;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.T2;
 import org.apache.ignite.internal.util.typedef.internal.CU;
@@ -281,6 +283,15 @@ class ClusterCachesInfo {
                             "client cache (a cache with the given name is not started): " + req.cacheName()));
                     }
                     else {
+                        SchemaOperationException err = QueryUtils.checkQueryEntityConflicts(
+                            req.startCacheConfiguration(), ctx.cache().cacheDescriptors());
+
+                        if (err != null) {
+                            ctx.cache().completeCacheStartFuture(req, false, err);
+
+                            continue;
+                        }
+
                         CacheConfiguration<?, ?> ccfg = req.startCacheConfiguration();
 
                         assert req.cacheType() != null : req;

http://git-wip-us.apache.org/repos/asf/ignite/blob/de658caf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
index 4dc5f8e..27dd23d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
@@ -64,6 +64,7 @@ import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.igfs.IgfsUtils;
+import org.apache.ignite.internal.processors.query.schema.SchemaOperationException;
 import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
 import org.apache.ignite.internal.util.lang.IgniteInClosureX;
 import org.apache.ignite.internal.util.typedef.C1;
@@ -1271,6 +1272,8 @@ public class GridCacheUtils {
             return new CacheAtomicUpdateTimeoutException(e.getMessage(), e);
         else if (e instanceof ClusterTopologyServerNotFoundException)
             return new CacheServerNotFoundException(e.getMessage(), e);
+        else if (e instanceof SchemaOperationException)
+            return new CacheException(e.getMessage(), e);
 
         if (e.getCause() instanceof CacheException)
             return (CacheException)e.getCause();

http://git-wip-us.apache.org/repos/asf/ignite/blob/de658caf/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index e729af5..175bcea 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -1316,7 +1316,17 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         ccfg.setSqlEscapeAll(true);
         ccfg.setQueryEntities(Collections.singleton(entity));
 
-        boolean res = ctx.grid().getOrCreateCache0(ccfg, true).get2();
+        boolean res;
+
+        try {
+            res = ctx.grid().getOrCreateCache0(ccfg, true).get2();
+        }
+        catch (CacheException e) {
+            if (e.getCause() instanceof SchemaOperationException)
+                throw (SchemaOperationException)e.getCause();
+            else
+                throw e;
+        }
 
         if (!res && !ifNotExists)
             throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_EXISTS,  entity.getTableName());

http://git-wip-us.apache.org/repos/asf/ignite/blob/de658caf/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
index 748768e..6ac2390 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
@@ -27,6 +27,7 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
 import org.apache.ignite.internal.processors.cache.CacheObjectContext;
+import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheDefaultAffinityKeyMapper;
 import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
@@ -1022,6 +1023,49 @@ public class QueryUtils {
     }
 
     /**
+     * Check given {@link CacheConfiguration} for conflicts in table and index names from any query entities
+     *     found in collection of {@link DynamicCacheDescriptor}s and belonging to the same schema.
+     *
+     * @param ccfg New cache configuration.
+     * @param descs Cache descriptors.
+     * @return Exception message describing found conflict or {@code null} if none found.
+     */
+    public static SchemaOperationException checkQueryEntityConflicts(CacheConfiguration<?, ?> ccfg,
+        Collection<DynamicCacheDescriptor> descs) {
+        String schema = QueryUtils.normalizeSchemaName(ccfg.getName(), ccfg.getSqlSchema());
+
+        Set<String> idxNames = new HashSet<>();
+
+        Set<String> tblNames = new HashSet<>();
+
+        for (DynamicCacheDescriptor desc : descs) {
+            String descSchema = QueryUtils.normalizeSchemaName(desc.cacheName(),
+                desc.cacheConfiguration().getSqlSchema());
+
+            if (!F.eq(schema, descSchema))
+                continue;
+
+            for (QueryEntity e : desc.schema().entities()) {
+                tblNames.add(e.getTableName());
+
+                for (QueryIndex idx : e.getIndexes())
+                    idxNames.add(idx.getName());
+            }
+        }
+
+        for (QueryEntity e : ccfg.getQueryEntities()) {
+            if (!tblNames.add(e.getTableName()))
+                return new SchemaOperationException(SchemaOperationException.CODE_TABLE_EXISTS, e.getTableName());
+
+            for (QueryIndex idx : e.getIndexes())
+                if (!idxNames.add(idx.getName()))
+                    return new SchemaOperationException(SchemaOperationException.CODE_INDEX_EXISTS, idx.getName());
+        }
+
+        return null;
+    }
+
+    /**
      * Validate query entity.
      *
      * @param entity Entity.

http://git-wip-us.apache.org/repos/asf/ignite/blob/de658caf/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
index c9e3295..fb2129b 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
@@ -26,6 +26,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.cache.query.FieldsQueryCursor;
+import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
@@ -85,7 +86,7 @@ public class DdlStatementsProcessor {
      * @param sql SQL.
      * @param stmt H2 statement to parse and execute.
      */
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked", "ThrowableResultOfMethodCallIgnored"})
     public FieldsQueryCursor<List<?>> runDdlStatement(String sql, PreparedStatement stmt)
         throws IgniteCheckedException {
         assert stmt instanceof JdbcPreparedStatement;
@@ -162,7 +163,20 @@ public class DdlStatementsProcessor {
                             cmd.tableName());
                 }
                 else {
-                    ctx.query().dynamicTableCreate(cmd.schemaName(), toQueryEntity(cmd), cmd.templateName(),
+                    QueryEntity e = toQueryEntity(cmd);
+
+                    CacheConfiguration<?, ?> ccfg = new CacheConfiguration<>(cmd.tableName());
+
+                    ccfg.setQueryEntities(Collections.singleton(e));
+                    ccfg.setSqlSchema(cmd.schemaName());
+
+                    SchemaOperationException err =
+                        QueryUtils.checkQueryEntityConflicts(ccfg, ctx.cache().cacheDescriptors());
+
+                    if (err != null)
+                        throw err;
+
+                    ctx.query().dynamicTableCreate(cmd.schemaName(), e, cmd.templateName(),
                         cmd.atomicityMode(), cmd.backups(), cmd.ifNotExists());
                 }
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de658caf/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
index d97d1eb..1d376c1 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
@@ -20,17 +20,22 @@ package org.apache.ignite.internal.processors.cache.index;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.concurrent.Callable;
 
 import javax.cache.CacheException;
+
+import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
@@ -42,8 +47,11 @@ import org.apache.ignite.internal.processors.query.IgniteSQLException;
 import org.apache.ignite.internal.processors.query.QueryTypeDescriptorImpl;
 import org.apache.ignite.internal.processors.query.QueryUtils;
 import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
+import org.apache.ignite.internal.processors.query.h2.ddl.DdlStatementsProcessor;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
+import org.apache.ignite.internal.processors.query.schema.SchemaOperationException;
 import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.GridTestUtils;
 
 /**
@@ -89,6 +97,9 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
         if (client().cache("Person") != null)
             executeDdl("DROP TABLE IF EXISTS PUBLIC.\"Person\"");
 
+
+            executeDdl("DROP TABLE IF EXISTS PUBLIC.\"City\"");
+
         super.afterTest();
     }
 
@@ -376,37 +387,68 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     }
 
     /**
-     * Execute {@code CREATE TABLE} w/given params.
-     * @param params Engine parameters.
+     * Tests index name conflict check in discovery thread.
+     * @throws Exception if failed.
      */
-    private void createTableWithParams(final String params) {
-        cache().query(new SqlFieldsQuery("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar" +
-            ", \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"template=cache," + params + '"'));
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    public void testIndexNameConflictCheckDiscovery() throws Exception {
+        executeDdl(grid(0), "CREATE TABLE \"Person\" (id int primary key, name varchar)");
+
+        executeDdl(grid(0), "CREATE INDEX \"idx\" ON \"Person\" (\"name\")");
+
+        GridTestUtils.assertThrows(null, new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                QueryEntity e = new QueryEntity();
+
+                e.setTableName("City");
+                e.setKeyFields(Collections.singleton("name"));
+                e.setFields(new LinkedHashMap<>(Collections.singletonMap("name", String.class.getName())));
+                e.setIndexes(Collections.singleton(new QueryIndex("name").setName("idx")));
+                e.setValueType("CityKey");
+                e.setValueType("City");
+
+                queryProcessor(client()).dynamicTableCreate("PUBLIC", e, CacheMode.PARTITIONED.name(),
+                    CacheAtomicityMode.ATOMIC, 10, false);
+
+                return null;
+            }
+        }, SchemaOperationException.class, "Index already exists: idx");
     }
 
     /**
-     * Execute {@code CREATE TABLE} w/given params expecting a particular error.
-     * @param params Engine parameters.
-     * @param expErrMsg Expected error message.
+     * Tests table name conflict check in {@link DdlStatementsProcessor}.
+     * @throws Exception if failed.
      */
-    private void assertCreateTableWithParamsThrows(final String params, String expErrMsg) {
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    public void testTableNameConflictCheckSql() throws Exception {
+        executeDdl(grid(0), "CREATE TABLE \"Person\" (id int primary key, name varchar)");
+
         GridTestUtils.assertThrows(null, new Callable<Object>() {
-            @Override public Object call() throws Exception {
-                createTableWithParams(params);
+            @Override  public Object call() throws Exception {
+                executeDdl(client(), "CREATE TABLE \"Person\" (id int primary key, name varchar)");
 
                 return null;
             }
-        }, IgniteSQLException.class, expErrMsg);
+        }, IgniteSQLException.class, "Table already exists: Person");
     }
 
     /**
-     * Test that {@code CREATE TABLE} on non-public schema causes an exception.
+     * Execute {@code CREATE TABLE} w/given params.
+     * @param params Engine parameters.
+     */
+    private void createTableWithParams(final String params) {
+        executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar" +
+            ", \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
+            "\"template=cache," + params + '"');
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} in non-public schema causes an exception.
      *
      * @throws Exception if failed.
      */
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
-    public void testCreateTableNotPublicSchema() throws Exception {
+    public void testCreateTableInNonPublicSchema() throws Exception {
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 executeDdl("CREATE TABLE \"cache_idx\".\"Person\" (\"id\" int, \"city\" varchar," +
@@ -419,6 +461,21 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     }
 
     /**
+     * Execute {@code CREATE TABLE} w/given params expecting a particular error.
+     * @param params Engine parameters.
+     * @param expErrMsg Expected error message.
+     */
+    private void assertCreateTableWithParamsThrows(final String params, String expErrMsg) {
+        GridTestUtils.assertThrows(null, new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                createTableWithParams(params);
+
+                return null;
+            }
+        }, IgniteSQLException.class, expErrMsg);
+    }
+
+    /**
      * Test that {@code DROP TABLE} on non-public schema causes an exception.
      *
      * @throws Exception if failed.
@@ -435,12 +492,12 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     }
 
     /**
-     * Execute DDL statement.
+     * Execute DDL statement on client node.
      *
      * @param sql Statement.
      */
     private void executeDdl(String sql) {
-        queryProcessor(client()).querySqlFieldsNoCache(new SqlFieldsQuery(sql).setSchema("PUBLIC"), true);
+        executeDdl(client(), sql);
     }
 
     /**
@@ -514,6 +571,16 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     }
 
     /**
+     * Execute DDL statement on given node.
+     *
+     * @param node Node.
+     * @param sql Statement.
+     */
+    private void executeDdl(Ignite node, String sql) {
+        queryProcessor(node).querySqlFieldsNoCache(new SqlFieldsQuery(sql).setSchema("PUBLIC"), true);
+    }
+
+    /**
      * @return Client node.
      */
     private IgniteEx client() {
@@ -562,6 +629,9 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @return Cache configuration with query entities in {@code PUBLIC} schema.
      */
     private CacheConfiguration cacheConfigurationForIndexingInPublicSchema() {
-        return cacheConfigurationForIndexing().setName(INDEXED_CACHE_NAME_2).setSqlSchema(QueryUtils.DFLT_SCHEMA);
+        return cacheConfigurationForIndexing()
+            .setName(INDEXED_CACHE_NAME_2)
+            .setSqlSchema(QueryUtils.DFLT_SCHEMA)
+            .setNodeFilter(F.not(new DynamicIndexAbstractSelfTest.NodeFilter()));
     }
 }


[34/50] [abbrv] ignite git commit: Minor improvements

Posted by sb...@apache.org.
Minor improvements


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/31ac7e9a
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/31ac7e9a
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/31ac7e9a

Branch: refs/heads/ignite-5075
Commit: 31ac7e9a06457cb967e37bef11fe70d6e13fbf5d
Parents: e273f2e
Author: Pavel Kovalenko <jo...@gmail.com>
Authored: Mon Jun 5 10:48:46 2017 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Mon Jun 5 10:56:31 2017 +0300

----------------------------------------------------------------------
 ...gniteCacheInvokeReadThroughAbstractTest.java | 92 ++++++++++----------
 .../testframework/junits/GridAbstractTest.java  | 24 +++++
 .../ignite/testframework/junits/IgniteMock.java | 11 +--
 .../junits/IgniteTestResources.java             | 52 +++++------
 .../cache/GridAbstractCacheStoreSelfTest.java   |  5 +-
 5 files changed, 102 insertions(+), 82 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/31ac7e9a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughAbstractTest.java
index 1caf157..963271f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughAbstractTest.java
@@ -90,6 +90,13 @@ public abstract class IgniteCacheInvokeReadThroughAbstractTest extends GridCommo
     }
 
     /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        ignite(0).destroyCache(DEFAULT_CACHE_NAME);
+    }
+
+    /** {@inheritDoc} */
     @Override protected void afterTestsStopped() throws Exception {
         stopAllGrids();
 
@@ -127,76 +134,71 @@ public abstract class IgniteCacheInvokeReadThroughAbstractTest extends GridCommo
 
         ignite0.createCache(ccfg);
 
-        try {
-            int key = 0;
+        int key = 0;
 
-            for (Ignite node : G.allGrids()) {
-                if (node.configuration().isClientMode() && ccfg.getNearConfiguration() != null)
-                    node.createNearCache(ccfg.getName(), ccfg.getNearConfiguration());
-            }
+        for (Ignite node : G.allGrids()) {
+            if (node.configuration().isClientMode() && ccfg.getNearConfiguration() != null)
+                node.createNearCache(ccfg.getName(), ccfg.getNearConfiguration());
+        }
 
-            for (Ignite node : G.allGrids()) {
-                log.info("Test for node: " + node.name());
+        for (Ignite node : G.allGrids()) {
+            log.info("Test for node: " + node.name());
 
-                IgniteCache<Object, Object> cache = node.cache(ccfg.getName());
+            IgniteCache<Object, Object> cache = node.cache(ccfg.getName());
 
-                for (int i = 0; i < 50; i++)
-                    checkReadThrough(cache, key++, null, null);
+            for (int i = 0; i < 50; i++)
+                checkReadThrough(cache, key++, null, null);
 
-                Set<Object> keys = new HashSet<>();
+            Set<Object> keys = new HashSet<>();
 
-                for (int i = 0; i < 5; i++)
-                    keys.add(key++);
+            for (int i = 0; i < 5; i++)
+                keys.add(key++);
 
-                checkReadThroughInvokeAll(cache, keys, null, null);
+            checkReadThroughInvokeAll(cache, keys, null, null);
 
-                keys = new HashSet<>();
+            keys = new HashSet<>();
 
-                for (int i = 0; i < 100; i++)
-                    keys.add(key++);
+            for (int i = 0; i < 100; i++)
+                keys.add(key++);
 
-                checkReadThroughInvokeAll(cache, keys, null, null);
+            checkReadThroughInvokeAll(cache, keys, null, null);
 
-                if (ccfg.getAtomicityMode() == TRANSACTIONAL) {
-                    for (TransactionConcurrency concurrency : TransactionConcurrency.values()) {
-                        for (TransactionIsolation isolation : TransactionIsolation.values()) {
-                            log.info("Test tx [concurrency=" + concurrency + ", isolation=" + isolation + ']');
+            if (ccfg.getAtomicityMode() == TRANSACTIONAL) {
+                for (TransactionConcurrency concurrency : TransactionConcurrency.values()) {
+                    for (TransactionIsolation isolation : TransactionIsolation.values()) {
+                        log.info("Test tx [concurrency=" + concurrency + ", isolation=" + isolation + ']');
 
-                            for (int i = 0; i < 50; i++)
-                                checkReadThrough(cache, key++, concurrency, isolation);
+                        for (int i = 0; i < 50; i++)
+                            checkReadThrough(cache, key++, concurrency, isolation);
 
-                            keys = new HashSet<>();
+                        keys = new HashSet<>();
 
-                            for (int i = 0; i < 5; i++)
-                                keys.add(key++);
+                        for (int i = 0; i < 5; i++)
+                            keys.add(key++);
 
-                            checkReadThroughInvokeAll(cache, keys, concurrency, isolation);
+                        checkReadThroughInvokeAll(cache, keys, concurrency, isolation);
 
-                            keys = new HashSet<>();
+                        keys = new HashSet<>();
 
-                            for (int i = 0; i < 100; i++)
-                                keys.add(key++);
+                        for (int i = 0; i < 100; i++)
+                            keys.add(key++);
 
-                            checkReadThroughInvokeAll(cache, keys, concurrency, isolation);
-                        }
+                        checkReadThroughInvokeAll(cache, keys, concurrency, isolation);
                     }
+                }
 
-                    for (TransactionConcurrency concurrency : TransactionConcurrency.values()) {
-                        for (TransactionIsolation isolation : TransactionIsolation.values()) {
-                            log.info("Test tx2 [concurrency=" + concurrency + ", isolation=" + isolation + ']');
+                for (TransactionConcurrency concurrency : TransactionConcurrency.values()) {
+                    for (TransactionIsolation isolation : TransactionIsolation.values()) {
+                        log.info("Test tx2 [concurrency=" + concurrency + ", isolation=" + isolation + ']');
 
-                            for (int i = 0; i < 50; i++)
-                                checkReadThroughGetAndInvoke(cache, key++, concurrency, isolation);
-                        }
+                        for (int i = 0; i < 50; i++)
+                            checkReadThroughGetAndInvoke(cache, key++, concurrency, isolation);
                     }
                 }
             }
-
-            ignite0.cache(ccfg.getName()).removeAll();
-        }
-        finally {
-            ignite0.destroyCache(ccfg.getName());
         }
+
+        ignite0.cache(ccfg.getName()).removeAll();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/31ac7e9a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
index 29c6396..1f096e4 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
@@ -270,6 +270,13 @@ public abstract class GridAbstractTest extends TestCase {
     }
 
     /**
+     * @return Test resources.
+     */
+    protected IgniteTestResources getTestResources(IgniteConfiguration cfg) throws IgniteCheckedException {
+        return getTestCounters(cfg).getTestResources();
+    }
+
+    /**
      * @param msg Message to print.
      */
     protected void info(String msg) {
@@ -1867,6 +1874,15 @@ public abstract class GridAbstractTest extends TestCase {
         return tc;
     }
 
+    /**
+     * @param cfg Ignite configuration
+     * @return Test counters
+     * @throws IgniteCheckedException In case of error
+     */
+    protected synchronized TestCounters getTestCounters(IgniteConfiguration cfg) throws IgniteCheckedException {
+        return new TestCounters(cfg);
+    }
+
     /** {@inheritDoc} */
     @SuppressWarnings({"ProhibitedExceptionDeclared"})
     @Override protected void runTest() throws Throwable {
@@ -2224,6 +2240,14 @@ public abstract class GridAbstractTest extends TestCase {
         }
 
         /**
+         * @param cfg Ignite configuration
+         * @throws IgniteCheckedException In case of error
+         */
+        public TestCounters(IgniteConfiguration cfg) throws IgniteCheckedException {
+            rsrcs = new IgniteTestResources(cfg);
+        }
+
+        /**
          * @return Reset flag.
          */
         public boolean isReset() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/31ac7e9a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java
index 1f95dd9..97157a8 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java
@@ -26,22 +26,22 @@ import org.apache.ignite.IgniteAtomicLong;
 import org.apache.ignite.IgniteAtomicReference;
 import org.apache.ignite.IgniteAtomicSequence;
 import org.apache.ignite.IgniteAtomicStamped;
+import org.apache.ignite.IgniteBinary;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteCluster;
 import org.apache.ignite.IgniteCompute;
 import org.apache.ignite.IgniteCountDownLatch;
-import org.apache.ignite.IgniteException;
-import org.apache.ignite.IgniteLock;
-import org.apache.ignite.IgniteSemaphore;
 import org.apache.ignite.IgniteDataStreamer;
 import org.apache.ignite.IgniteEvents;
+import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteFileSystem;
+import org.apache.ignite.IgniteLock;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.IgniteMessaging;
-import org.apache.ignite.IgniteBinary;
 import org.apache.ignite.IgniteQueue;
 import org.apache.ignite.IgniteScheduler;
+import org.apache.ignite.IgniteSemaphore;
 import org.apache.ignite.IgniteServices;
 import org.apache.ignite.IgniteSet;
 import org.apache.ignite.IgniteTransactions;
@@ -109,13 +109,14 @@ public class IgniteMock implements Ignite {
      * @param home Ignite home.
      */
     public IgniteMock(
-        String name, String locHost, UUID nodeId, Marshaller marshaller, MBeanServer jmx, String home) {
+        String name, String locHost, UUID nodeId, Marshaller marshaller, MBeanServer jmx, String home, IgniteConfiguration staticCfg) {
         this.locHost = locHost;
         this.nodeId = nodeId;
         this.marshaller = marshaller;
         this.jmx = jmx;
         this.home = home;
         this.name = name;
+        this.staticCfg = staticCfg;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/31ac7e9a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java
index 2222274..5fef8bc 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java
@@ -58,21 +58,24 @@ public class IgniteTestResources {
     private final IgniteLogger log;
 
     /** Local host. */
-    private final String locHost;
+    private final String locHost = localHost();
 
     /** */
-    private final UUID nodeId;
+    private final UUID nodeId = UUID.randomUUID();
 
     /** */
     private final MBeanServer jmx;
 
     /** */
-    private final String home;
+    private final String home = U.getIgniteHome();
 
     /** */
     private ThreadPoolExecutor execSvc;
 
     /** */
+    private IgniteConfiguration cfg;
+
+    /** */
     private GridResourceProcessor rsrcProc;
 
     /**
@@ -84,14 +87,18 @@ public class IgniteTestResources {
         else
             log = rootLog.getLogger(getClass());
 
-        nodeId = UUID.randomUUID();
-        jmx = ManagementFactory.getPlatformMBeanServer();
-        home = U.getIgniteHome();
-        locHost = localHost();
-
-        GridTestKernalContext ctx = new GridTestKernalContext(log);
+        this.jmx = ManagementFactory.getPlatformMBeanServer();
+        this.rsrcProc = new GridResourceProcessor(new GridTestKernalContext(this.log));
+    }
 
-        rsrcProc = new GridResourceProcessor(ctx);
+    /**
+     * @param cfg Ignite configuration
+     */
+    public IgniteTestResources(IgniteConfiguration cfg) throws IgniteCheckedException {
+        this.cfg = cfg;
+        this.log = rootLog.getLogger(getClass());
+        this.jmx = ManagementFactory.getPlatformMBeanServer();
+        this.rsrcProc = new GridResourceProcessor(new GridTestKernalContext(this.log, this.cfg));
     }
 
     /**
@@ -101,16 +108,8 @@ public class IgniteTestResources {
         assert jmx != null;
 
         this.jmx = jmx;
-
-        log = rootLog.getLogger(getClass());
-
-        nodeId = UUID.randomUUID();
-        home = U.getIgniteHome();
-        locHost = localHost();
-
-        GridTestKernalContext ctx = new GridTestKernalContext(log);
-
-        rsrcProc = new GridResourceProcessor(ctx);
+        this.log = rootLog.getLogger(getClass());
+        this.rsrcProc = new GridResourceProcessor(new GridTestKernalContext(this.log));
     }
 
     /**
@@ -120,15 +119,8 @@ public class IgniteTestResources {
         assert log != null;
 
         this.log = log.getLogger(getClass());
-
-        nodeId = UUID.randomUUID();
-        jmx = ManagementFactory.getPlatformMBeanServer();
-        home = U.getIgniteHome();
-        locHost = localHost();
-
-        GridTestKernalContext ctx = new GridTestKernalContext(log);
-
-        rsrcProc = new GridResourceProcessor(ctx);
+        this.jmx = ManagementFactory.getPlatformMBeanServer();
+        this.rsrcProc = new GridResourceProcessor(new GridTestKernalContext(this.log));
     }
 
     /**
@@ -185,7 +177,7 @@ public class IgniteTestResources {
 
         rsrcProc.injectBasicResource(target, LoggerResource.class, getLogger().getLogger(target.getClass()));
         rsrcProc.injectBasicResource(target, IgniteInstanceResource.class,
-            new IgniteMock(null, locHost, nodeId, getMarshaller(), jmx, home));
+            new IgniteMock(null, locHost, nodeId, getMarshaller(), jmx, home, cfg));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/31ac7e9a/modules/core/src/test/java/org/apache/ignite/testframework/junits/cache/GridAbstractCacheStoreSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/cache/GridAbstractCacheStoreSelfTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/cache/GridAbstractCacheStoreSelfTest.java
index 8aba684..c5673b3 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/cache/GridAbstractCacheStoreSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/cache/GridAbstractCacheStoreSelfTest.java
@@ -466,9 +466,10 @@ public abstract class GridAbstractCacheStoreSelfTest<T extends CacheStore<Object
     }
 
     /**
-     * @return Store.
+     * @return Store
+     * @throws Exception In case of error
      */
-    protected abstract T store();
+    protected abstract T store() throws Exception;
 
     /**
      * Dummy transaction for test purposes.


[32/50] [abbrv] ignite git commit: Mentioned ignite-rocketmq module in README.

Posted by sb...@apache.org.
Mentioned ignite-rocketmq module in README.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/0d5a35a3
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/0d5a35a3
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/0d5a35a3

Branch: refs/heads/ignite-5075
Commit: 0d5a35a3a50d1f1d0b4ff3c505907efccedffb9e
Parents: e04df7d
Author: shroman <rs...@yahoo.com>
Authored: Mon Jun 5 16:04:07 2017 +0900
Committer: shroman <rs...@yahoo.com>
Committed: Mon Jun 5 16:04:07 2017 +0900

----------------------------------------------------------------------
 assembly/libs/README.txt | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/0d5a35a3/assembly/libs/README.txt
----------------------------------------------------------------------
diff --git a/assembly/libs/README.txt b/assembly/libs/README.txt
index a5e8a01..678da15 100644
--- a/assembly/libs/README.txt
+++ b/assembly/libs/README.txt
@@ -95,6 +95,7 @@ The following modules are available:
 - ignite-osgi-karaf (to seemlessly intall ignite into Apache Karaf container)
 - ignite-osgi-paxlogging (to expose PAX Logging API to Log4j if needed)
 - ignite-rest-http (for HTTP REST messages)
+- ignite-rocketmq (for streaming messages from Apache RocketMQ into Ignite)
 - ignite-scalar (for ignite Scala API)
 - ignite-scalar_2.10 (for Ignite Scala 2.10 API)
 - ignite-schedule (for Cron-based task scheduling)


[27/50] [abbrv] ignite git commit: IGNITE-5373: JDBC: added socket send buffer size, receive buffer size, tcp NO_DELAY flag to connection string. This closes #2076.

Posted by sb...@apache.org.
IGNITE-5373: JDBC: added socket send buffer size, receive buffer size, tcp NO_DELAY flag to connection string. This closes #2076.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/898781aa
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/898781aa
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/898781aa

Branch: refs/heads/ignite-5075
Commit: 898781aa03d9549f0e785b64770bdc1363d82d49
Parents: 1a9c942
Author: devozerov <pp...@gmail.com>
Authored: Sat Jun 3 22:56:53 2017 +0300
Committer: devozerov <pp...@gmail.com>
Committed: Sat Jun 3 22:56:53 2017 +0300

----------------------------------------------------------------------
 .../jdbc2/JdbcDynamicIndexAbstractSelfTest.java |   2 +
 .../jdbc/thin/JdbcThinConnectionSelfTest.java   | 201 +++++++++++--------
 .../JdbcThinDynamicIndexAbstractSelfTest.java   |   2 +
 .../jdbc/thin/JdbcThinNoDefaultSchemaTest.java  |  13 +-
 .../org/apache/ignite/IgniteJdbcThinDriver.java | 131 ++++--------
 .../internal/jdbc/thin/JdbcThinConnection.java  | 160 ++++++++++++---
 .../internal/jdbc/thin/JdbcThinResultSet.java   |   6 +-
 .../internal/jdbc/thin/JdbcThinStatement.java   |   2 +-
 .../internal/jdbc/thin/JdbcThinTcpIo.java       |  98 +++++++--
 .../internal/jdbc/thin/JdbcThinUtils.java       |  58 +++++-
 10 files changed, 439 insertions(+), 234 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/898781aa/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java
index 7bbda6f..d4da1f3 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java
@@ -242,6 +242,8 @@ public abstract class JdbcDynamicIndexAbstractSelfTest extends JdbcAbstractDmlSt
      * Test that changes in cache affect index, and vice versa.
      */
     public void testIndexState() throws SQLException {
+        fail("https://issues.apache.org/jira/browse/IGNITE-5373");
+
         IgniteCache<String, Person> cache = cache();
 
         assertSize(3);

http://git-wip-us.apache.org/repos/asf/ignite/blob/898781aa/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
index c3ce73a..8407a15 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
@@ -17,24 +17,23 @@
 
 package org.apache.ignite.jdbc.thin;
 
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.concurrent.Callable;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.jdbc.thin.JdbcThinConnection;
+import org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo;
+import org.apache.ignite.internal.jdbc.thin.JdbcThinUtils;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.jetbrains.annotations.NotNull;
 
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.concurrent.Callable;
+
 /**
  * Connection test.
  */
@@ -42,12 +41,6 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     /** IP finder. */
     private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
 
-    /** URL prefix. */
-    private static final String URL_PREFIX = "jdbc:ignite:thin://";
-
-    /** Host. */
-    private static final String HOST = "127.0.0.1";
-
     /** {@inheritDoc} */
     @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
         IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
@@ -93,122 +86,152 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     /**
      * @throws Exception If failed.
      */
+    @SuppressWarnings({"EmptyTryBlock", "unused"})
     public void testDefaults() throws Exception {
-        String url = URL_PREFIX + HOST;
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
+            // No-op.
+        }
 
-        assert DriverManager.getConnection(url) != null;
-        assert DriverManager.getConnection(url + "/") != null;
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1/")) {
+            // No-op.
+        }
     }
 
     /**
+     * Test invalid endpoint.
+     *
      * @throws Exception If failed.
      */
-    public void testFailedHandshake() throws Exception {
-        final ServerSocket srvSock = new ServerSocket(60000, 0, InetAddress.getByName("127.0.0.1"));
-
-        IgniteInternalFuture f = GridTestUtils.runAsync(new Runnable() {
-            @Override public void run() {
-                try {
-                    Socket s = srvSock.accept();
-
-                    s.close();
-                }
-                catch (IOException e) {
-                    log.error("Unexpected exception", e);
-                    fail();
-                }
-            }
-        });
+    public void testInvalidEndpoint() throws Exception {
+        assertInvalid("jdbc:ignite:thin://", "Host name is empty");
+        assertInvalid("jdbc:ignite:thin://:10000", "Host name is empty");
+        assertInvalid("jdbc:ignite:thin://     :10000", "Host name is empty");
+
+        assertInvalid("jdbc:ignite:thin://127.0.0.1:-1", "Invalid port");
+        assertInvalid("jdbc:ignite:thin://127.0.0.1:0", "Invalid port");
+        assertInvalid("jdbc:ignite:thin://127.0.0.1:100000", "Invalid port");
+    }
+
+    /**
+     * Test invalid socket buffer sizes.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSocketBuffers() throws Exception {
+        assertInvalid("jdbc:ignite:thin://127.0.0.1?socketSendBuffer=-1",
+            "Property cannot be negative [name=" + JdbcThinUtils.PARAM_SOCK_SND_BUF);
+
+        assertInvalid("jdbc:ignite:thin://127.0.0.1?socketReceiveBuffer=-1",
+            "Property cannot be negative [name=" + JdbcThinUtils.PARAM_SOCK_RCV_BUF);
+
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
+            assertEquals(0, socket(conn).socketSendBuffer());
+            assertEquals(0, socket(conn).socketReceiveBuffer());
+        }
 
-        try {
-            GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-                @Override public Void call() throws Exception {
-                    DriverManager.getConnection(URL_PREFIX + "127.0.0.1:60000");
+        // Note that SO_* options are hints, so we check that value is equals to either what we set or to default.
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?socketSendBuffer=1024")) {
+            assertEquals(1024, socket(conn).socketSendBuffer());
+            assertEquals(0, socket(conn).socketReceiveBuffer());
+        }
 
-                    return null;
-                }
-            }, SQLException.class, "Failed to connect to Ignite cluster [host=127.0.0.1, port=60000]");
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?socketReceiveBuffer=1024")) {
+            assertEquals(0, socket(conn).socketSendBuffer());
+            assertEquals(1024, socket(conn).socketReceiveBuffer());
         }
-        finally {
-            f.get(3000);
 
-            srvSock.close();
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?" +
+            "socketSendBuffer=1024&socketReceiveBuffer=2048")) {
+            assertEquals(1024, socket(conn).socketSendBuffer());
+            assertEquals(2048, socket(conn).socketReceiveBuffer());
         }
     }
 
     /**
+     * Test TCP no delay property handling.
+     *
      * @throws Exception If failed.
      */
-    public void testInvalidUrls() throws Exception {
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection("q");
+    public void testPropertyTcpNoDelay() throws Exception {
+        assertInvalid("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=0",
+            "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_TCP_NO_DELAY);
 
-                return null;
-            }
-        }, SQLException.class, "No suitable driver found for q");
+        assertInvalid("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=1",
+            "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_TCP_NO_DELAY);
 
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:-1");
+        assertInvalid("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=false1",
+            "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_TCP_NO_DELAY);
 
-                return null;
-            }
-        }, SQLException.class, "Invalid port:");
+        assertInvalid("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=true1",
+            "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_TCP_NO_DELAY);
 
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:0");
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
+            assertTrue(socket(conn).tcpNoDelay());
+        }
 
-                return null;
-            }
-        }, SQLException.class, "Invalid port:");
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=true")) {
+            assertTrue(socket(conn).tcpNoDelay());
+        }
 
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:100000");
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=false")) {
+            assertFalse(socket(conn).tcpNoDelay());
+        }
+    }
 
-                return null;
-            }
-        }, SQLException.class, "Invalid port:");
+    /**
+     * Get client socket for connection.
+     *
+     * @param conn Connection.
+     * @return Socket.
+     * @throws Exception If failed.
+     */
+    private static JdbcThinTcpIo socket(Connection conn) throws Exception {
+        JdbcThinConnection conn0 = conn.unwrap(JdbcThinConnection.class);
 
+        return conn0.io();
+    }
+
+    /**
+     * Assert that provided URL is invalid.
+     *
+     * @param url URL.
+     * @param errMsg Error message.
+     */
+    @SuppressWarnings("ThrowableNotThrown")
+    private void assertInvalid(final String url, String errMsg) {
         GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
             @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "     :10000");
+                DriverManager.getConnection(url);
 
                 return null;
             }
-        }, SQLException.class, "Host name is empty");
+        }, SQLException.class, errMsg);
     }
 
     /**
      * @throws Exception If failed.
      */
+    @SuppressWarnings("ThrowableNotThrown")
     public void testClose() throws Exception {
-        String url = URL_PREFIX + HOST;
-
-        final Connection conn = DriverManager.getConnection(url);
+        final Connection conn;
 
-        assert conn != null;
-        assert !conn.isClosed();
+        try (Connection conn0 = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
+            conn = conn0;
 
-        conn.close();
+            assert conn != null;
+            assert !conn.isClosed();
+        }
 
         assert conn.isClosed();
 
         assert !conn.isValid(2): "Connection must be closed";
 
-        GridTestUtils.assertThrows(
-            log,
-            new Callable<Object>() {
-                @Override public Object call() throws Exception {
-                    conn.isValid(-2);
-
-                    return null;
-                }
-            },
-            SQLException.class,
-            "Invalid timeout"
-        );
+        GridTestUtils.assertThrows(log, new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                conn.isValid(-2);
+
+                return null;
+            }
+        }, SQLException.class, "Invalid timeout");
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/898781aa/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
index 3f762fc..7404ebd 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
@@ -254,6 +254,8 @@ public abstract class JdbcThinDynamicIndexAbstractSelfTest extends JdbcThinAbstr
      * @throws SQLException If failed.
      */
     public void testIndexState() throws SQLException {
+        fail("https://issues.apache.org/jira/browse/IGNITE-5373");
+
         IgniteCache<String, Person> cache = cache();
 
         assertSize(3);

http://git-wip-us.apache.org/repos/asf/ignite/blob/898781aa/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
index 97008c8..cea176e 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
@@ -44,7 +44,7 @@ public class JdbcThinNoDefaultSchemaTest extends JdbcThinAbstractSelfTest {
     private static final String CACHE2_NAME = "cache2";
 
     /** URL. */
-    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1";
 
     /** Grid count. */
     private static final int GRID_CNT = 2;
@@ -107,15 +107,14 @@ public class JdbcThinNoDefaultSchemaTest extends JdbcThinAbstractSelfTest {
     /**
      * @throws Exception If failed.
      */
+    @SuppressWarnings({"EmptyTryBlock", "unused"})
     public void testDefaults() throws Exception {
-        String url = URL;
-
-        try (Connection conn = DriverManager.getConnection(url)) {
-            assertNotNull(conn);
+        try (Connection conn = DriverManager.getConnection(URL)) {
+            // No-op.
         }
 
-        try (Connection conn = DriverManager.getConnection(url + '/')) {
-            assertNotNull(conn);
+        try (Connection conn = DriverManager.getConnection(URL + '/')) {
+            // No-op.
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/898781aa/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
index 5c04701..665ac69 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
@@ -28,10 +28,11 @@ import java.util.List;
 import java.util.Properties;
 import java.util.logging.Logger;
 import org.apache.ignite.cache.affinity.AffinityKey;
-import org.apache.ignite.configuration.OdbcConfiguration;
 import org.apache.ignite.internal.IgniteVersionUtils;
 import org.apache.ignite.internal.jdbc.JdbcDriverPropertyInfo;
 import org.apache.ignite.internal.jdbc.thin.JdbcThinConnection;
+import org.apache.ignite.internal.jdbc.thin.JdbcThinUtils;
+import org.apache.ignite.internal.util.typedef.F;
 
 /**
  * JDBC driver thin implementation for In-Memory Data Grid.
@@ -132,32 +133,6 @@ import org.apache.ignite.internal.jdbc.thin.JdbcThinConnection;
  */
 @SuppressWarnings("JavadocReference")
 public class IgniteJdbcThinDriver implements Driver {
-    /** Prefix for property names. */
-    private static final String PROP_PREFIX = "ignite.jdbc";
-
-    /** Distributed joins parameter name. */
-    private static final String PARAM_DISTRIBUTED_JOINS = "distributedJoins";
-
-    /** Enforce join order parameter name. */
-    private static final String ENFORCE_JOIN_ORDER = "enforceJoinOrder";
-
-    /** Hostname property name. */
-    public static final String PROP_HOST = PROP_PREFIX + "host";
-
-    /** Port number property name. */
-    public static final String PROP_PORT = PROP_PREFIX + "port";
-
-    /** Distributed joins property name. */
-    public static final String PROP_DISTRIBUTED_JOINS = PROP_PREFIX + PARAM_DISTRIBUTED_JOINS;
-
-    /** Transactions allowed property name. */
-    public static final String PROP_ENFORCE_JOIN_ORDER = PROP_PREFIX + ENFORCE_JOIN_ORDER;
-
-    /** URL prefix. */
-    public static final String URL_PREFIX = "jdbc:ignite:thin://";
-
-    /** Default port. */
-    public static final int DFLT_PORT = OdbcConfiguration.DFLT_TCP_PORT_FROM;
 
     /** Major version. */
     private static final int MAJOR_VER = IgniteVersionUtils.VER.major();
@@ -182,27 +157,25 @@ public class IgniteJdbcThinDriver implements Driver {
         if (!acceptsURL(url))
             return null;
 
-        if (!parseUrl(url, props))
-            throw new SQLException("URL is invalid: " + url);
+        parseUrl(url, props);
 
         return new JdbcThinConnection(url, props);
     }
 
     /** {@inheritDoc} */
     @Override public boolean acceptsURL(String url) throws SQLException {
-        return url.startsWith(URL_PREFIX);
+        return url.startsWith(JdbcThinUtils.URL_PREFIX);
     }
 
     /** {@inheritDoc} */
     @Override public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
-        if (!parseUrl(url, info))
-            throw new SQLException("URL is invalid: " + url);
+        parseUrl(url, info);
 
         List<DriverPropertyInfo> props = Arrays.<DriverPropertyInfo>asList(
-            new JdbcDriverPropertyInfo("Hostname", info.getProperty(PROP_HOST), ""),
-            new JdbcDriverPropertyInfo("Port number", info.getProperty(PROP_PORT), ""),
-            new JdbcDriverPropertyInfo("Distributed Joins", info.getProperty(PROP_DISTRIBUTED_JOINS), ""),
-            new JdbcDriverPropertyInfo("Enforce Join Order", info.getProperty(PROP_ENFORCE_JOIN_ORDER), "")
+            new JdbcDriverPropertyInfo("Hostname", info.getProperty(JdbcThinUtils.PROP_HOST), ""),
+            new JdbcDriverPropertyInfo("Port number", info.getProperty(JdbcThinUtils.PROP_PORT), ""),
+            new JdbcDriverPropertyInfo("Distributed Joins", info.getProperty(JdbcThinUtils.PROP_DISTRIBUTED_JOINS), ""),
+            new JdbcDriverPropertyInfo("Enforce Join Order", info.getProperty(JdbcThinUtils.PROP_ENFORCE_JOIN_ORDER), "")
         );
 
         return props.toArray(new DriverPropertyInfo[0]);
@@ -233,83 +206,65 @@ public class IgniteJdbcThinDriver implements Driver {
      *
      * @param props Properties.
      * @param url URL.
-     * @return Whether URL is valid.
-     */
-    private boolean parseUrl(String url, Properties props) {
-        if (url == null)
-            return false;
-
-        if (url.startsWith(URL_PREFIX) && url.length() > URL_PREFIX.length())
-            return parseJdbcUrl(url, props);
-
-        return false;
-    }
-
-    /**
-     * @param url Url.
-     * @param props Properties.
-     * @return Whether URL is valid.
      */
-    private boolean parseJdbcUrl(String url, Properties props) {
-        url = url.substring(URL_PREFIX.length());
-
-        String[] parts = url.split("\\?");
-
-        if (parts.length > 2)
-            return false;
+    private void parseUrl(String url, Properties props) throws SQLException {
+        if (F.isEmpty(url))
+            throw new SQLException("URL cannot be null or empty.");
 
-        if (parts.length == 2)
-            if (!parseParameters(parts[1], "&", props))
-                return false;
+        if (!url.startsWith(JdbcThinUtils.URL_PREFIX))
+            throw new SQLException("URL must start with \"" + JdbcThinUtils.URL_PREFIX + "\"");
 
-        parts = parts[0].split("/");
+        String nakedUrl = url.substring(JdbcThinUtils.URL_PREFIX.length()).trim();
 
-        assert parts.length > 0;
+        String[] nakedUrlParts = nakedUrl.split("\\?");
 
-        if (parts.length > 1)
-            return false;
+        if (nakedUrlParts.length > 2)
+            throw new SQLException("Invalid URL format (only one ? character is allowed): " + url);
 
-        url = parts[0];
+        String endpoint = nakedUrlParts[0];
 
-        parts = url.split(":");
+        if (endpoint.endsWith("/"))
+            endpoint = endpoint.substring(0, endpoint.length() - 1);
 
-        assert parts.length > 0;
+        String[] endpointParts = endpoint.split(":");
 
-        if (parts.length > 2)
-            return false;
+        if (endpointParts.length > 2)
+            throw new SQLException("Invalid endpoint format (should be \"host[:port]\"): " + endpoint);
 
-        props.setProperty(PROP_HOST, parts[0]);
+        props.setProperty(JdbcThinUtils.PROP_HOST, endpointParts[0]);
 
-        try {
-            props.setProperty(PROP_PORT, String.valueOf(parts.length == 2 ? Integer.valueOf(parts[1]) : DFLT_PORT));
-        }
-        catch (NumberFormatException ignored) {
-            return false;
-        }
+        if (endpointParts.length == 2)
+            props.setProperty(JdbcThinUtils.PROP_PORT, endpointParts[1]);
 
-        return true;
+        if (nakedUrlParts.length == 2)
+            parseParameters(nakedUrlParts[1], props);
     }
 
     /**
      * Validates and parses URL parameters.
      *
-     * @param val Parameters string.
+     * @param str Parameters string.
      * @param delim Delimiter.
      * @param props Properties.
-     * @return Whether URL parameters string is valid.
+     * @throws SQLException If failed.
      */
-    private boolean parseParameters(String val, String delim, Properties props) {
-        String[] params = val.split(delim);
+    private void parseParameters(String str, Properties props) throws SQLException {
+        String[] params = str.split("&");
 
         for (String param : params) {
             String[] pair = param.split("=");
 
-            if (pair.length != 2 || pair[0].isEmpty() || pair[1].isEmpty())
-                return false;
+            if (pair.length != 2)
+                throw new SQLException("Invalid parameter format (only one = character is allowed per key/value " +
+                    "pair: " + param);
 
-            props.setProperty(PROP_PREFIX + pair[0], pair[1]);
-        }
+            String key = pair[0].trim();
+            String val = pair[1].trim();
+
+            if (key.isEmpty() || val.isEmpty())
+                throw new SQLException("Invalid parameter format (key and value cannot be empty): " + param);
 
-        return true;
+            props.setProperty(JdbcThinUtils.PROP_PREFIX + key, val);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/898781aa/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
index 4ba7557..b284f62 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal.jdbc.thin;
 
+import org.apache.ignite.internal.util.typedef.F;
+
 import java.sql.Array;
 import java.sql.Blob;
 import java.sql.CallableStatement;
@@ -41,10 +43,14 @@ import java.util.logging.Logger;
 import static java.sql.ResultSet.CONCUR_READ_ONLY;
 import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
 import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
-import static org.apache.ignite.IgniteJdbcThinDriver.PROP_DISTRIBUTED_JOINS;
-import static org.apache.ignite.IgniteJdbcThinDriver.PROP_ENFORCE_JOIN_ORDER;
-import static org.apache.ignite.IgniteJdbcThinDriver.PROP_HOST;
-import static org.apache.ignite.IgniteJdbcThinDriver.PROP_PORT;
+
+import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_HOST;
+import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_PORT;
+import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_DISTRIBUTED_JOINS;
+import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_ENFORCE_JOIN_ORDER;
+import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SOCK_SND_BUF;
+import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SOCK_RCV_BUF;
+import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_TCP_NO_DELAY;
 
 /**
  * JDBC connection implementation.
@@ -91,36 +97,27 @@ public class JdbcThinConnection implements Connection {
         autoCommit = true;
         txIsolation = Connection.TRANSACTION_NONE;
 
-        boolean distributedJoins = Boolean.parseBoolean(props.getProperty(PROP_DISTRIBUTED_JOINS, "false"));
-        boolean enforceJoinOrder = Boolean.parseBoolean(props.getProperty(PROP_ENFORCE_JOIN_ORDER, "false"));
+        String host = extractHost(props);
+        int port = extractPort(props);
 
-        String host = props.getProperty(PROP_HOST);
-        String portStr = props.getProperty(PROP_PORT);
+        boolean distributedJoins = extractBoolean(props, PROP_DISTRIBUTED_JOINS, false);
+        boolean enforceJoinOrder = extractBoolean(props, PROP_ENFORCE_JOIN_ORDER, false);
 
-        try {
-            int port = Integer.parseInt(portStr);
+        int sockSndBuf = extractIntNonNegative(props, PROP_SOCK_SND_BUF, 0);
+        int sockRcvBuf = extractIntNonNegative(props, PROP_SOCK_RCV_BUF, 0);
 
-            if (port <= 0 || port > 0xFFFF)
-                throw new SQLException("Invalid port: " + portStr);
-        }
-        catch (NumberFormatException e) {
-            throw new SQLException("Invalid port: " + portStr, e);
-        }
-
-        if (host == null || host.trim().isEmpty())
-            throw new SQLException("Host name is empty.");
-
-        String endpoint = host.trim() + ":" + portStr.trim();
+        boolean tcpNoDelay  = extractBoolean(props, PROP_TCP_NO_DELAY, true);
 
         try {
-            cliIo = new JdbcThinTcpIo(endpoint, distributedJoins, enforceJoinOrder);
+            cliIo = new JdbcThinTcpIo(host, port, distributedJoins, enforceJoinOrder,
+                sockSndBuf, sockRcvBuf, tcpNoDelay);
 
             cliIo.start();
         }
         catch (Exception e) {
             cliIo.close();
 
-            throw new SQLException("Failed to connect to Ignite cluster [host=" + host + ", port=" + portStr + ']', e);
+            throw new SQLException("Failed to connect to Ignite node [host=" + host + ", port=" + port + ']', e);
         }
     }
 
@@ -486,6 +483,7 @@ public class JdbcThinConnection implements Connection {
     }
 
     /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
     @Override public <T> T unwrap(Class<T> iface) throws SQLException {
         if (!isWrapperFor(iface))
             throw new SQLException("Connection is not a wrapper for " + iface.getName());
@@ -539,7 +537,121 @@ public class JdbcThinConnection implements Connection {
     /**
      * @return Ignite endpoint and I/O protocol.
      */
-    JdbcThinTcpIo cliIo() {
+    public JdbcThinTcpIo io() {
         return cliIo;
     }
+
+    /**
+     * Extract host.
+     *
+     * @param props Properties.
+     * @return Host.
+     * @throws SQLException If failed.
+     */
+    private static String extractHost(Properties props) throws SQLException {
+        String host = props.getProperty(PROP_HOST);
+
+        if (host != null)
+            host = host.trim();
+
+        if (F.isEmpty(host))
+            throw new SQLException("Host name is empty.");
+
+        return host;
+    }
+
+    /**
+     * Extract port.
+     *
+     * @param props Properties.
+     * @return Port.
+     * @throws SQLException If failed.
+     */
+    private static int extractPort(Properties props) throws SQLException {
+        String portStr = props.getProperty(PROP_PORT);
+
+        if (portStr == null)
+            return JdbcThinUtils.DFLT_PORT;
+
+        int port;
+
+        try {
+            port = Integer.parseInt(portStr);
+
+            if (port <= 0 || port > 0xFFFF)
+                throw new SQLException("Invalid port: " + portStr);
+        }
+        catch (NumberFormatException e) {
+            throw new SQLException("Invalid port: " + portStr, e);
+        }
+
+        return port;
+    }
+
+    /**
+     * Extract boolean property.
+     *
+     * @param props Properties.
+     * @param propName Property name.
+     * @param dfltVal Default value.
+     * @return Value.
+     * @throws SQLException If failed.
+     */
+    private static boolean extractBoolean(Properties props, String propName, boolean dfltVal) throws SQLException {
+        String strVal = props.getProperty(propName);
+
+        if (strVal == null)
+            return dfltVal;
+
+        if (Boolean.TRUE.toString().equalsIgnoreCase(strVal))
+            return true;
+        else if (Boolean.FALSE.toString().equalsIgnoreCase(strVal))
+            return false;
+        else
+            throw new SQLException("Failed to parse boolean property [name=" + JdbcThinUtils.trimPrefix(propName) +
+                    ", value=" + strVal + ']');
+    }
+
+    /**
+     * Extract non-negative int property.
+     *
+     * @param props Properties.
+     * @param propName Property name.
+     * @param dfltVal Default value.
+     * @return Value.
+     * @throws SQLException If failed.
+     */
+    private static int extractIntNonNegative(Properties props, String propName, int dfltVal) throws SQLException {
+        int res = extractInt(props, propName, dfltVal);
+
+        if (res < 0)
+            throw new SQLException("Property cannot be negative [name=" + JdbcThinUtils.trimPrefix(propName) +
+                ", value=" + res + ']');
+
+        return res;
+    }
+
+    /**
+     * Extract int property.
+     *
+     * @param props Properties.
+     * @param propName Property name.
+     * @param dfltVal Default value.
+     * @return Value.
+     * @throws SQLException If failed.
+     */
+    private static int extractInt(Properties props, String propName, int dfltVal) throws SQLException {
+        String strVal = props.getProperty(propName);
+
+        if (strVal == null)
+            return dfltVal;
+
+        try {
+            return Integer.parseInt(strVal);
+        }
+        catch (NumberFormatException e) {
+            throw new SQLException("Failed to parse int property [name=" + JdbcThinUtils.trimPrefix(propName) +
+                ", value=" + strVal + ']');
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/898781aa/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
index 36f938b..87bc526 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
@@ -136,7 +136,7 @@ public class JdbcThinResultSet implements ResultSet {
 
         if (rowsIter == null && !finished) {
             try {
-                JdbcQueryFetchResult res = stmt.connection().cliIo().queryFetch(qryId, fetchSize);
+                JdbcQueryFetchResult res = stmt.connection().io().queryFetch(qryId, fetchSize);
 
                 rows = res.items();
                 finished = res.last();
@@ -178,7 +178,7 @@ public class JdbcThinResultSet implements ResultSet {
             return;
 
         try {
-            stmt.connection().cliIo().queryClose(qryId);
+            stmt.connection().io().queryClose(qryId);
 
             closed = true;
         }
@@ -1618,7 +1618,7 @@ public class JdbcThinResultSet implements ResultSet {
     private List<JdbcColumnMeta> meta() throws SQLException {
         if (!metaInit) {
             try {
-                JdbcQueryMetadataResult res = stmt.connection().cliIo().queryMeta(qryId);
+                JdbcQueryMetadataResult res = stmt.connection().io().queryMeta(qryId);
 
                 meta = res.meta();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/898781aa/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
index 91b8b06..a0b7ee6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
@@ -106,7 +106,7 @@ public class JdbcThinStatement implements Statement {
             throw new SQLException("SQL query is empty.");
 
         try {
-            JdbcQueryExecuteResult res = conn.cliIo().queryExecute(conn.getSchema(), pageSize, maxRows,
+            JdbcQueryExecuteResult res = conn.io().queryExecute(conn.getSchema(), pageSize, maxRows,
                 sql, args);
 
             assert res != null;

http://git-wip-us.apache.org/repos/asf/ignite/blob/898781aa/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
index 136fcf9..3f6edb8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
@@ -20,8 +20,9 @@ package org.apache.ignite.internal.jdbc.thin;
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
 import java.util.List;
-import java.util.logging.Logger;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.binary.BinaryReaderExImpl;
 import org.apache.ignite.internal.binary.BinaryWriterExImpl;
@@ -41,9 +42,8 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult;
-import org.apache.ignite.internal.processors.odbc.jdbc.JdbcUtils;
 import org.apache.ignite.internal.util.ipc.IpcEndpoint;
-import org.apache.ignite.internal.util.ipc.IpcEndpointFactory;
+import org.apache.ignite.internal.util.ipc.loopback.IpcClientTcpEndpoint;
 import org.apache.ignite.internal.util.typedef.internal.U;
 
 /**
@@ -68,14 +68,29 @@ public class JdbcThinTcpIo {
     /** Initial output for query close message. */
     private static final int QUERY_CLOSE_MSG_SIZE = 9;
 
-    /** Logger. */
-    private static final Logger log = Logger.getLogger(JdbcThinTcpIo.class.getName());
+    /** Host. */
+    private final String host;
 
-    /** Server endpoint address. */
-    private final String endpointAddr;
+    /** Port. */
+    private final int port;
+
+    /** Distributed joins. */
+    private final boolean distributedJoins;
+
+    /** Enforce join order. */
+    private final boolean enforceJoinOrder;
+
+    /** Socket send buffer. */
+    private final int sockSndBuf;
+
+    /** Socket receive buffer. */
+    private final int sockRcvBuf;
+
+    /** TCP no delay flag. */
+    private final boolean tcpNoDelay;
 
     /** Endpoint. */
-    private IpcEndpoint endpoint;
+    private IpcClientTcpEndpoint endpoint;
 
     /** Output stream. */
     private BufferedOutputStream out;
@@ -83,26 +98,29 @@ public class JdbcThinTcpIo {
     /** Input stream. */
     private BufferedInputStream in;
 
-    /** Distributed joins. */
-    private boolean distributedJoins;
-
-    /** Enforce join order. */
-    private boolean enforceJoinOrder;
-
     /** Closed flag. */
     private boolean closed;
 
     /**
-     * @param endpointAddr Endpoint.
+     * Constructor.
+     *
+     * @param host Host.
+     * @param port Port.
      * @param distributedJoins Distributed joins flag.
      * @param enforceJoinOrder Enforce join order flag.
+     * @param sockSndBuf Socket send buffer.
+     * @param sockRcvBuf Socket receive buffer.
+     * @param tcpNoDelay TCP no delay flag.
      */
-    JdbcThinTcpIo(String endpointAddr, boolean distributedJoins, boolean enforceJoinOrder) {
-        assert endpointAddr != null;
-
-        this.endpointAddr = endpointAddr;
+    JdbcThinTcpIo(String host, int port, boolean distributedJoins, boolean enforceJoinOrder, int sockSndBuf,
+        int sockRcvBuf, boolean tcpNoDelay) {
+        this.host = host;
+        this.port = port;
         this.distributedJoins = distributedJoins;
-        this.enforceJoinOrder= enforceJoinOrder;
+        this.enforceJoinOrder = enforceJoinOrder;
+        this.sockSndBuf = sockSndBuf;
+        this.sockRcvBuf = sockRcvBuf;
+        this.tcpNoDelay = tcpNoDelay;
     }
 
     /**
@@ -110,7 +128,24 @@ public class JdbcThinTcpIo {
      * @throws IOException On IO error in handshake.
      */
     public void start() throws IgniteCheckedException, IOException {
-        endpoint = IpcEndpointFactory.connectEndpoint(endpointAddr, null);
+        Socket sock = new Socket();
+
+        if (sockSndBuf != 0)
+            sock.setSendBufferSize(sockSndBuf);
+
+        if (sockRcvBuf != 0)
+            sock.setReceiveBufferSize(sockRcvBuf);
+
+        sock.setTcpNoDelay(tcpNoDelay);
+
+        try {
+            sock.connect(new InetSocketAddress(host, port));
+        }
+        catch (IOException e) {
+            throw new IgniteCheckedException("Failed to connect to server [host=" + host + ", port=" + port + ']', e);
+        }
+
+        endpoint = new IpcClientTcpEndpoint(sock);
 
         out = new BufferedOutputStream(endpoint.outputStream());
         in = new BufferedInputStream(endpoint.inputStream());
@@ -306,4 +341,25 @@ public class JdbcThinTcpIo {
 
         closed = true;
     }
+
+    /**
+     * @return Socket send buffer size.
+     */
+    public int socketSendBuffer() {
+        return sockSndBuf;
+    }
+
+    /**
+     * @return Socket receive buffer size.
+     */
+    public int socketReceiveBuffer() {
+        return sockRcvBuf;
+    }
+
+    /**
+     * @return TCP no delay flag.
+     */
+    public boolean tcpNoDelay() {
+        return tcpNoDelay;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/898781aa/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
index 7f4c111..a346ea8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal.jdbc.thin;
 
+import org.apache.ignite.configuration.OdbcConfiguration;
+
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.sql.Types;
@@ -40,6 +42,61 @@ import static java.sql.Types.VARCHAR;
  * Utility methods for thin JDBC driver.
  */
 public class JdbcThinUtils {
+    /** URL prefix. */
+    public static final String URL_PREFIX = "jdbc:ignite:thin://";
+
+    /** Prefix for property names. */
+    public static final String PROP_PREFIX = "ignite.jdbc";
+
+    /** Port number property name. */
+    public static final String PROP_PORT = PROP_PREFIX + "port";
+
+    /** Hostname property name. */
+    public static final String PROP_HOST = PROP_PREFIX + "host";
+
+    /** Parameter: distributed joins flag. */
+    public static final String PARAM_DISTRIBUTED_JOINS = "distributedJoins";
+
+    /** Parameter: enforce join order flag. */
+    public static final String PARAM_ENFORCE_JOIN_ORDER = "enforceJoinOrder";
+
+    /** Parameter: socket send buffer. */
+    public static final String PARAM_SOCK_SND_BUF = "socketSendBuffer";
+
+    /** Parameter: socket receive buffer. */
+    public static final String PARAM_SOCK_RCV_BUF = "socketReceiveBuffer";
+
+    /** Parameter: TCP no-delay flag. */
+    public static final String PARAM_TCP_NO_DELAY = "tcpNoDelay";
+
+    /** Distributed joins property name. */
+    public static final String PROP_DISTRIBUTED_JOINS = PROP_PREFIX + PARAM_DISTRIBUTED_JOINS;
+
+    /** Transactions allowed property name. */
+    public static final String PROP_ENFORCE_JOIN_ORDER = PROP_PREFIX + PARAM_ENFORCE_JOIN_ORDER;
+
+    /** Socket send buffer property name. */
+    public static final String PROP_SOCK_SND_BUF = PROP_PREFIX + PARAM_SOCK_SND_BUF;
+
+    /** Socket receive buffer property name. */
+    public static final String PROP_SOCK_RCV_BUF = PROP_PREFIX + PARAM_SOCK_RCV_BUF;
+
+    /** TCP no delay property name. */
+    public static final String PROP_TCP_NO_DELAY = PROP_PREFIX + PARAM_TCP_NO_DELAY;
+
+    /** Default port. */
+    public static final int DFLT_PORT = OdbcConfiguration.DFLT_TCP_PORT_FROM;
+
+    /**
+     * Trim prefix from property.
+     *
+     * @param prop Property.
+     * @return Parameter name.
+     */
+    public static String trimPrefix(String prop) {
+        return prop.substring(PROP_PREFIX.length());
+    }
+
     /**
      * Converts Java class name to type from {@link Types}.
      *
@@ -126,7 +183,6 @@ public class JdbcThinUtils {
             && type != Types.NVARCHAR
             && type != Types.LONGNVARCHAR
             && type != Types.REF
-            && type != Types.NCHAR
             && type != Types.ROWID
             && type != Types.SQLXML;
     }


[10/50] [abbrv] ignite git commit: IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
new file mode 100644
index 0000000..0b1cad8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
@@ -0,0 +1,461 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLXML;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Calendar;
+import org.apache.ignite.internal.processors.odbc.SqlListenerUtils;
+
+/**
+ * JDBC prepared statement implementation.
+ */
+public class JdbcThinPreparedStatement extends JdbcThinStatement implements PreparedStatement {
+    /** SQL query. */
+    private final String sql;
+
+    /**
+     * Creates new prepared statement.
+     *
+     * @param conn Connection.
+     * @param sql SQL query.
+     */
+    JdbcThinPreparedStatement(JdbcThinConnection conn, String sql) {
+        super(conn);
+
+        this.sql = sql;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ResultSet executeQuery() throws SQLException {
+        ResultSet rs = super.executeQuery(sql);
+
+        args = null;
+
+        return rs;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ResultSet executeQuery(String sql) throws SQLException {
+        throw new SQLException("The method 'executeQuery(String)' is called on PreparedStatement instance.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int executeUpdate() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int executeUpdate(String sql) throws SQLException {
+        throw new SQLException("The method 'executeUpdate(String)' is called on PreparedStatement instance.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setNull(int paramIdx, int sqlType) throws SQLException {
+        setArgument(paramIdx, null);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setBoolean(int paramIdx, boolean x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setByte(int paramIdx, byte x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setShort(int paramIdx, short x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setInt(int paramIdx, int x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setLong(int paramIdx, long x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setFloat(int paramIdx, float x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setDouble(int paramIdx, double x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setBigDecimal(int paramIdx, BigDecimal x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setString(int paramIdx, String x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setBytes(int paramIdx, byte[] x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setDate(int paramIdx, Date x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setTime(int paramIdx, Time x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setTimestamp(int paramIdx, Timestamp x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setAsciiStream(int paramIdx, InputStream x, int length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setUnicodeStream(int paramIdx, InputStream x, int length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setBinaryStream(int paramIdx, InputStream x, int length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clearParameters() throws SQLException {
+        ensureNotClosed();
+
+        args = null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setObject(int paramIdx, Object x, int targetSqlType) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setObject(int paramIdx, Object x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean execute() throws SQLException {
+        return super.execute(sql);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean execute(String sql) throws SQLException {
+        throw new SQLException("The method 'execute(String)' is called on PreparedStatement instance.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void addBatch() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setCharacterStream(int paramIdx, Reader x, int length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setRef(int paramIdx, Ref x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setBlob(int paramIdx, Blob x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setClob(int paramIdx, Clob x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setArray(int paramIdx, Array x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public ResultSetMetaData getMetaData() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Meta data for prepared statement is not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setDate(int paramIdx, Date x, Calendar cal) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setTime(int paramIdx, Time x, Calendar cal) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setTimestamp(int paramIdx, Timestamp x, Calendar cal) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setNull(int paramIdx, int sqlType, String typeName) throws SQLException {
+        if (!JdbcThinUtils.isPlainJdbcType(sqlType)) {
+            throw new SQLFeatureNotSupportedException("The SQL type is unsupported. [type=" + sqlType + "typeName="
+                + typeName + ']');
+        }
+
+        setNull(paramIdx, sqlType);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setURL(int paramIdx, URL x) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ParameterMetaData getParameterMetaData() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Meta data for prepared statement is not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setRowId(int paramIdx, RowId x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setNString(int paramIdx, String val) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setNCharacterStream(int paramIdx, Reader val, long length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setNClob(int paramIdx, NClob val) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setClob(int paramIdx, Reader reader, long length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setBlob(int paramIdx, InputStream inputStream, long length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setNClob(int paramIdx, Reader reader, long length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setSQLXML(int paramIdx, SQLXML xmlObj) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setObject(int paramIdx, Object x, int targetSqlType, int scaleOrLength) throws SQLException {
+        setArgument(paramIdx, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setAsciiStream(int paramIdx, InputStream x, long length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setBinaryStream(int paramIdx, InputStream x, long length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setCharacterStream(int paramIdx, Reader x, long length) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setAsciiStream(int paramIdx, InputStream x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setBinaryStream(int paramIdx, InputStream x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setCharacterStream(int paramIdx, Reader x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setNCharacterStream(int paramIdx, Reader val) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setClob(int paramIdx, Reader reader) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setBlob(int paramIdx, InputStream inputStream) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setNClob(int paramIdx, Reader reader) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> T unwrap(Class<T> iface) throws SQLException {
+        if (!isWrapperFor(iface))
+            throw new SQLException("Prepared statement is not a wrapper for " + iface.getName());
+
+        return (T)this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        return iface != null && iface.isAssignableFrom(JdbcThinPreparedStatement.class);
+    }
+
+    /**
+     * Sets query argument value.
+     *
+     * @param paramIdx Index.
+     * @param val Value.
+     * @throws SQLException If index is invalid.
+     */
+    private void setArgument(int paramIdx, Object val) throws SQLException {
+        ensureNotClosed();
+
+        if (val != null && !SqlListenerUtils.isPlainType(val.getClass()))
+            throw new SQLException("Parameter type is unsupported. [cls=" + val.getClass() + ']');
+
+        if (paramIdx < 1)
+            throw new SQLException("Parameter index is invalid: " + paramIdx);
+
+        if (args == null)
+            args = new ArrayList<>(paramIdx);
+
+        while (args.size() < paramIdx)
+            args.add(null);
+
+        args.set(paramIdx - 1, val);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
new file mode 100644
index 0000000..f4ab444
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
@@ -0,0 +1,1698 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult;
+
+/**
+ * JDBC result set implementation.
+ */
+public class JdbcThinResultSet implements ResultSet {
+    /** Statement. */
+    private final JdbcThinStatement stmt;
+
+    /** Query ID. */
+    private final Long qryId;
+
+    /** Metadata. */
+    private List<JdbcColumnMeta> meta;
+
+    /** Column order map. */
+    private Map<String, Integer> colOrder;
+
+    /** Metadata initialization flag. */
+    private boolean metaInit;
+
+    /** Rows. */
+    private List<List<Object>> rows;
+
+    /** Rows iterator. */
+    private Iterator<List<Object>> rowsIter;
+
+    /** Current row. */
+    private List<Object> curRow;
+
+    /** Current position. */
+    private int curPos;
+
+    /** Finished flag. */
+    private boolean finished;
+
+    /** Closed flag. */
+    private boolean closed;
+
+    /** Was {@code NULL} flag. */
+    private boolean wasNull;
+
+    /** Fetch size. */
+    private int fetchSize;
+
+    /** Is query flag. */
+    private boolean isQuery;
+
+    /** Update count. */
+    private long updCnt;
+
+    /**
+     * Creates new result set.
+     *
+     * @param stmt Statement.
+     * @param qryId Query ID.
+     * @param fetchSize Fetch size.
+     * @param finished Finished flag.
+     * @param rows Rows.
+     * @param isQuery Is Result ser for Select query
+     */
+    @SuppressWarnings("OverlyStrongTypeCast") JdbcThinResultSet(JdbcThinStatement stmt, long qryId, int fetchSize, boolean finished,
+        List<List<Object>> rows, boolean isQuery) {
+        assert stmt != null;
+        assert fetchSize > 0;
+
+        this.stmt = stmt;
+        this.qryId = qryId;
+        this.fetchSize = fetchSize;
+        this.rows = rows;
+        this.finished = finished;
+
+        rowsIter = rows.iterator();
+
+        this.isQuery = isQuery;
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override public boolean next() throws SQLException {
+        ensureNotClosed();
+
+        if (rowsIter == null && !finished) {
+            try {
+                JdbcQueryFetchResult res = stmt.connection().cliIo().queryFetch(qryId, fetchSize);
+
+                rows = res.items();
+                finished = res.last();
+
+                rowsIter = rows.iterator();
+            }
+            catch (IOException e) {
+                stmt.connection().close();
+
+                throw new SQLException("Failed to query Ignite.", e);
+            }
+            catch (IgniteCheckedException e) {
+                throw new SQLException("Failed to query Ignite.", e);
+            }
+        }
+
+        if (rowsIter != null) {
+            if (rowsIter.hasNext()) {
+                curRow = rowsIter.next();
+
+                curPos++;
+
+                return true;
+            }
+            else {
+                rowsIter = null;
+                curRow = null;
+
+                return false;
+            }
+        }
+        else
+            return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void close() throws SQLException {
+        if (closed || stmt.connection().isClosed())
+            return;
+
+        try {
+            stmt.connection().cliIo().queryClose(qryId);
+
+            closed = true;
+        }
+        catch (IOException e) {
+            stmt.connection().close();
+
+            throw new SQLException("Failed to close Ignite query.", e);
+        }
+        catch (IgniteCheckedException e) {
+            throw new SQLException("Failed to close Ignite query.", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean wasNull() throws SQLException {
+        return wasNull;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getString(int colIdx) throws SQLException {
+        ensureNotClosed();
+        ensureHasCurrentRow();
+
+        try {
+            Object val = curRow.get(colIdx - 1);
+
+            wasNull = val == null;
+
+            if (val == null)
+                return null;
+            else
+                return String.valueOf(val);
+        }
+        catch (IndexOutOfBoundsException e) {
+            throw new SQLException("Invalid column index: " + colIdx, e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean getBoolean(int colIdx) throws SQLException {
+        try {
+            Object val = curRow.get(colIdx - 1);
+
+            wasNull = val == null;
+
+            if (val == null)
+                return false;
+            else if (val.getClass() == Boolean.class)
+                return (Boolean)val;
+            else {
+                if (val.getClass() == Byte.class
+                    || val.getClass() == Short.class
+                    || val.getClass() == Integer.class
+                    || val.getClass() == Long.class)
+                    return castToBoolean((Number)val);
+                else if (val.getClass() == Character.class
+                    || val.getClass() == String.class)
+                    return castToBoolean(val.toString());
+                else
+                    throw new ClassCastException("Cannot cast " + val.getClass().getName() + " to boolean");
+            }
+        }
+        catch (IndexOutOfBoundsException e) {
+            throw new SQLException("Invalid column index: " + colIdx, e);
+        }
+        catch (ClassCastException e) {
+            throw new SQLException("Value is an not instance of " + Boolean.class.getName(), e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte getByte(int colIdx) throws SQLException {
+        Byte val = getTypedValue(colIdx, Byte.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public short getShort(int colIdx) throws SQLException {
+        Short val = getTypedValue(colIdx, Short.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getInt(int colIdx) throws SQLException {
+        Integer val = getTypedValue(colIdx, Integer.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getLong(int colIdx) throws SQLException {
+        Long val = getTypedValue(colIdx, Long.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public float getFloat(int colIdx) throws SQLException {
+        Float val = getTypedValue(colIdx, Float.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double getDouble(int colIdx) throws SQLException {
+        Double val = getTypedValue(colIdx, Double.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public BigDecimal getBigDecimal(int colIdx, int scale) throws SQLException {
+        return getTypedValue(colIdx, BigDecimal.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte[] getBytes(int colIdx) throws SQLException {
+        return getTypedValue(colIdx, byte[].class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Date getDate(int colIdx) throws SQLException {
+        ensureNotClosed();
+        ensureHasCurrentRow();
+
+        try {
+            Object val = curRow.get(colIdx - 1);
+
+            wasNull = val == null;
+
+            if (val == null)
+                return null;
+            else if (val.getClass() == java.util.Date.class)
+                return new java.sql.Date(((java.util.Date)val).getTime());
+            else
+                return (Date)val;
+        }
+        catch (IndexOutOfBoundsException e) {
+            throw new SQLException("Invalid column index: " + colIdx, e);
+        }
+        catch (ClassCastException e) {
+            throw new SQLException("Value is an not instance of Date", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public Time getTime(int colIdx) throws SQLException {
+        return getTypedValue(colIdx, Time.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Timestamp getTimestamp(int colIdx) throws SQLException {
+        return getTypedValue(colIdx, Timestamp.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public InputStream getAsciiStream(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public InputStream getUnicodeStream(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public InputStream getBinaryStream(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Stream are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getString(String colLb) throws SQLException {
+        int colIdx = findColumn(colLb);
+
+        assert colIdx > 0;
+
+        return getString(colIdx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean getBoolean(String colLb) throws SQLException {
+        int colIdx = findColumn(colLb);
+
+        assert colIdx > 0;
+
+        return getBoolean(colIdx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte getByte(String colLb) throws SQLException {
+        Byte val = getTypedValue(colLb, Byte.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public short getShort(String colLb) throws SQLException {
+        Short val = getTypedValue(colLb, Short.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getInt(String colLb) throws SQLException {
+        Integer val = getTypedValue(colLb, Integer.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getLong(String colLb) throws SQLException {
+        Long val = getTypedValue(colLb, Long.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public float getFloat(String colLb) throws SQLException {
+        Float val = getTypedValue(colLb, Float.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double getDouble(String colLb) throws SQLException {
+        Double val = getTypedValue(colLb, Double.class);
+
+        return val != null ? val : 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public BigDecimal getBigDecimal(String colLb, int scale) throws SQLException {
+        return getTypedValue(colLb, BigDecimal.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte[] getBytes(String colLb) throws SQLException {
+        return getTypedValue(colLb, byte[].class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Date getDate(String colLb) throws SQLException {
+        int colIdx = findColumn(colLb);
+
+        assert colIdx > 0;
+
+        return getDate(colIdx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Time getTime(String colLb) throws SQLException {
+        return getTypedValue(colLb, Time.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Timestamp getTimestamp(String colLb) throws SQLException {
+        return getTypedValue(colLb, Timestamp.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public InputStream getAsciiStream(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public InputStream getUnicodeStream(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public InputStream getBinaryStream(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public SQLWarning getWarnings() throws SQLException {
+        ensureNotClosed();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clearWarnings() throws SQLException {
+        ensureNotClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getCursorName() throws SQLException {
+        ensureNotClosed();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ResultSetMetaData getMetaData() throws SQLException {
+        ensureNotClosed();
+
+        return new JdbcThinResultSetMetadata(meta());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getObject(int colIdx) throws SQLException {
+        return getTypedValue(colIdx, Object.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getObject(String colLb) throws SQLException {
+        return getTypedValue(colLb, Object.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int findColumn(final String colLb) throws SQLException {
+        ensureNotClosed();
+
+        Integer order = columnOrder().get(colLb.toUpperCase());
+
+        if (order == null)
+            throw new SQLException("Column not found: " + colLb);
+
+        return order + 1;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Reader getCharacterStream(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Reader getCharacterStream(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Streams are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public BigDecimal getBigDecimal(int colIdx) throws SQLException {
+        return getTypedValue(colIdx, BigDecimal.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public BigDecimal getBigDecimal(String colLb) throws SQLException {
+        return getTypedValue(colLb, BigDecimal.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isBeforeFirst() throws SQLException {
+        ensureNotClosed();
+
+        return curPos == 0 && rowsIter != null && rowsIter.hasNext();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isAfterLast() throws SQLException {
+        ensureNotClosed();
+
+        return finished && rowsIter == null && curRow == null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isFirst() throws SQLException {
+        ensureNotClosed();
+
+        return curPos == 1;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isLast() throws SQLException {
+        ensureNotClosed();
+
+        return finished && rowsIter != null && !rowsIter.hasNext() && curRow != null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void beforeFirst() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLException("Result set is forward-only.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void afterLast() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLException("Result set is forward-only.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean first() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLException("Result set is forward-only.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean last() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLException("Result set is forward-only.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getRow() throws SQLException {
+        ensureNotClosed();
+
+        return isAfterLast() ? 0 : curPos;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean absolute(int row) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLException("Result set is forward-only.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean relative(int rows) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLException("Result set is forward-only.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean previous() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLException("Result set is forward-only.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setFetchDirection(int direction) throws SQLException {
+        ensureNotClosed();
+
+        if (direction != FETCH_FORWARD)
+            throw new SQLFeatureNotSupportedException("Only forward direction is supported");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getFetchDirection() throws SQLException {
+        ensureNotClosed();
+
+        return FETCH_FORWARD;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setFetchSize(int fetchSize) throws SQLException {
+        ensureNotClosed();
+
+        if (fetchSize <= 0)
+            throw new SQLException("Fetch size must be greater than zero.");
+
+        this.fetchSize = fetchSize;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getFetchSize() throws SQLException {
+        ensureNotClosed();
+
+        return fetchSize;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getType() throws SQLException {
+        ensureNotClosed();
+
+        return stmt.getResultSetType();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getConcurrency() throws SQLException {
+        ensureNotClosed();
+
+        return CONCUR_READ_ONLY;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean rowUpdated() throws SQLException {
+        ensureNotClosed();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean rowInserted() throws SQLException {
+        ensureNotClosed();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean rowDeleted() throws SQLException {
+        ensureNotClosed();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNull(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBoolean(int colIdx, boolean x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateByte(int colIdx, byte x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateShort(int colIdx, short x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateInt(int colIdx, int x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateLong(int colIdx, long x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateFloat(int colIdx, float x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateDouble(int colIdx, double x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBigDecimal(int colIdx, BigDecimal x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateString(int colIdx, String x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBytes(int colIdx, byte[] x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateDate(int colIdx, Date x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateTime(int colIdx, Time x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateTimestamp(int colIdx, Timestamp x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateAsciiStream(int colIdx, InputStream x, int len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBinaryStream(int colIdx, InputStream x, int len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateCharacterStream(int colIdx, Reader x, int len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateObject(int colIdx, Object x, int scaleOrLen) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateObject(int colIdx, Object x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNull(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBoolean(String colLb, boolean x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateByte(String colLb, byte x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateShort(String colLb, short x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateInt(String colLb, int x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateLong(String colLb, long x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateFloat(String colLb, float x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateDouble(String colLb, double x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBigDecimal(String colLb, BigDecimal x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateString(String colLb, String x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBytes(String colLb, byte[] x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateDate(String colLb, Date x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateTime(String colLb, Time x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateTimestamp(String colLb, Timestamp x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateAsciiStream(String colLb, InputStream x, int len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBinaryStream(String colLb, InputStream x, int len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateCharacterStream(String colLb, Reader reader, int len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateObject(String colLb, Object x, int scaleOrLen) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateObject(String colLb, Object x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void insertRow() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateRow() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void deleteRow() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void refreshRow() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Row refreshing is not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void cancelRowUpdates() throws SQLException {
+        ensureNotClosed();
+
+        if (getConcurrency() == CONCUR_READ_ONLY)
+            throw new SQLException("The result set concurrency is CONCUR_READ_ONLY");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void moveToInsertRow() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void moveToCurrentRow() throws SQLException {
+        ensureNotClosed();
+
+        if (getConcurrency() == CONCUR_READ_ONLY)
+            throw new SQLException("The result set concurrency is CONCUR_READ_ONLY");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Statement getStatement() throws SQLException {
+        ensureNotClosed();
+
+        return stmt;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getObject(int colIdx, Map<String, Class<?>> map) throws SQLException {
+        throw new SQLFeatureNotSupportedException("SQL structured type are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Ref getRef(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Blob getBlob(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Clob getClob(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Array getArray(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getObject(String colLb, Map<String, Class<?>> map) throws SQLException {
+        throw new SQLFeatureNotSupportedException("SQL structured type are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Ref getRef(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Blob getBlob(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Clob getClob(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Array getArray(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Date getDate(int colIdx, Calendar cal) throws SQLException {
+        ensureNotClosed();
+        ensureHasCurrentRow();
+
+        try {
+            Object val = curRow.get(colIdx - 1);
+
+            wasNull = val == null;
+
+            if (val == null)
+                return null;
+            else if (val.getClass() == java.util.Date.class)
+                return new Date(((java.util.Date)val).getTime());
+            else
+                return (Date)val;
+        }
+        catch (IndexOutOfBoundsException e) {
+            throw new SQLException("Invalid column index: " + colIdx, e);
+        }
+        catch (ClassCastException e) {
+            throw new SQLException("Value is an not instance of Date", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public Date getDate(String colLb, Calendar cal) throws SQLException {
+        int colIdx = findColumn(colLb);
+
+        assert colIdx > 0;
+
+        return getDate(colIdx, cal);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Time getTime(int colIdx, Calendar cal) throws SQLException {
+        return getTypedValue(colIdx, Time.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Time getTime(String colLb, Calendar cal) throws SQLException {
+        return getTypedValue(colLb, Time.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Timestamp getTimestamp(int colIdx, Calendar cal) throws SQLException {
+        return getTypedValue(colIdx, Timestamp.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Timestamp getTimestamp(String colLb, Calendar cal) throws SQLException {
+        return getTypedValue(colLb, Timestamp.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public URL getURL(int colIdx) throws SQLException {
+        return getTypedValue(colIdx, URL.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public URL getURL(String colLb) throws SQLException {
+        return getTypedValue(colLb, URL.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateRef(int colIdx, Ref x) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateRef(String colLb, Ref x) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBlob(int colIdx, Blob x) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBlob(String colLb, Blob x) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateClob(int colIdx, Clob x) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateClob(String colLb, Clob x) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateArray(int colIdx, Array x) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateArray(String colLb, Array x) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public RowId getRowId(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public RowId getRowId(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateRowId(int colIdx, RowId x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateRowId(String colLb, RowId x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getHoldability() throws SQLException {
+        ensureNotClosed();
+
+        return HOLD_CURSORS_OVER_COMMIT;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isClosed() throws SQLException {
+        return stmt.isClosed() || closed;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNString(int colIdx, String nStr) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNString(String colLb, String nStr) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNClob(int colIdx, NClob nClob) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNClob(String colLb, NClob nClob) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public NClob getNClob(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public NClob getNClob(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public SQLXML getSQLXML(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public SQLXML getSQLXML(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateSQLXML(int colIdx, SQLXML xmlObj) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateSQLXML(String colLb, SQLXML xmlObj) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getNString(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getNString(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Reader getNCharacterStream(int colIdx) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Reader getNCharacterStream(String colLb) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNCharacterStream(int colIdx, Reader x, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNCharacterStream(String colLb, Reader reader, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateAsciiStream(int colIdx, InputStream x, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBinaryStream(int colIdx, InputStream x, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateCharacterStream(int colIdx, Reader x, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateAsciiStream(String colLb, InputStream x, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBinaryStream(String colLb, InputStream x, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateCharacterStream(String colLb, Reader reader, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBlob(int colIdx, InputStream inputStream, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBlob(String colLb, InputStream inputStream, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateClob(int colIdx, Reader reader, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateClob(String colLb, Reader reader, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNClob(int colIdx, Reader reader, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNClob(String colLb, Reader reader, long len) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNCharacterStream(int colIdx, Reader x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNCharacterStream(String colLb, Reader reader) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateAsciiStream(int colIdx, InputStream x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBinaryStream(int colIdx, InputStream x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateCharacterStream(int colIdx, Reader x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateAsciiStream(String colLb, InputStream x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBinaryStream(String colLb, InputStream x) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateCharacterStream(String colLb, Reader reader) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBlob(int colIdx, InputStream inputStream) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateBlob(String colLb, InputStream inputStream) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateClob(int colIdx, Reader reader) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateClob(String colLb, Reader reader) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNClob(int colIdx, Reader reader) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateNClob(String colLb, Reader reader) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> T unwrap(Class<T> iface) throws SQLException {
+        if (!isWrapperFor(iface))
+            throw new SQLException("Result set is not a wrapper for " + iface.getName());
+
+        return (T)this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        return iface != null && iface.isAssignableFrom(JdbcThinResultSet.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> T getObject(int colIdx, Class<T> type) throws SQLException {
+        return getTypedValue(colIdx, type);
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> T getObject(String colLb, Class<T> type) throws SQLException {
+        return getTypedValue(colLb, type);
+    }
+
+    /**
+     * Gets casted field value by label.
+     *
+     * @param colLb Column label.
+     * @param cls Value class.
+     * @return Casted field value.
+     * @throws SQLException In case of error.
+     */
+    private <T> T getTypedValue(String colLb, Class<T> cls) throws SQLException {
+        ensureNotClosed();
+        ensureHasCurrentRow();
+
+        int colIdx = findColumn(colLb);
+
+        assert colIdx > 0;
+
+        return getTypedValue(colIdx, cls);
+    }
+
+    /**
+     * Gets casted field value by index.
+     *
+     * @param colIdx Column index.
+     * @param cls Value class.
+     * @return Casted field value.
+     * @throws SQLException In case of error.
+     */
+    @SuppressWarnings("unchecked")
+    private <T> T getTypedValue(int colIdx, Class<T> cls) throws SQLException {
+        ensureNotClosed();
+        ensureHasCurrentRow();
+
+        try {
+            Object val = curRow.get(colIdx - 1);
+
+            wasNull = val == null;
+
+            if (val == null)
+                return null;
+            else
+                return (T)val;
+        }
+        catch (IndexOutOfBoundsException e) {
+            throw new SQLException("Invalid column index: " + colIdx, e);
+        }
+        catch (ClassCastException e) {
+            throw new SQLException("Value is an not instance of " + cls.getName(), e);
+        }
+    }
+
+    /**
+     * Ensures that result set is not closed.
+     *
+     * @throws SQLException If result set is closed.
+     */
+    private void ensureNotClosed() throws SQLException {
+        if (closed)
+            throw new SQLException("Result set is closed.");
+    }
+
+    /**
+     * Ensures that result set is positioned on a row.
+     *
+     * @throws SQLException If result set is not positioned on a row.
+     */
+    private void ensureHasCurrentRow() throws SQLException {
+        if (curRow == null)
+            throw new SQLException("Result set is not positioned on a row.");
+    }
+
+    /**
+     * @return Results metadata.
+     * @throws SQLException On error.
+     */
+    private List<JdbcColumnMeta> meta() throws SQLException {
+        if (!metaInit) {
+            try {
+                JdbcQueryMetadataResult res = stmt.connection().cliIo().queryMeta(qryId);
+
+                meta = res.meta();
+
+                metaInit = true;
+            }
+            catch (IOException e) {
+                stmt.connection().close();
+
+                throw new SQLException("Failed to get query metadata.", e);
+            }
+            catch (IgniteCheckedException e) {
+                throw new SQLException("Failed to get query metadata.", e);
+            }
+        }
+
+        return meta;
+    }
+
+    /**
+     * Init column order map.
+     * @throws SQLException On error.
+     * @return Column order map.
+     */
+    private Map<String, Integer> columnOrder() throws SQLException {
+        if(colOrder != null)
+            return colOrder;
+
+        if(!metaInit)
+            meta();
+
+        colOrder = new HashMap<>(meta.size());
+
+        for (int i = 0; i < meta.size(); ++i) {
+            String colName = meta.get(i).columnName().toUpperCase();
+
+            if(!colOrder.containsKey(colName))
+                colOrder.put(colName, i);
+        }
+
+        return colOrder;
+    }
+
+    /**
+     * @return Is query flag.
+     */
+    boolean isQuery() {
+        return isQuery;
+    }
+
+    /**
+     * @return Update count for no-SELECT queries.
+     */
+    long updatedCount() {
+        return updCnt;
+    }
+
+    /**
+     * @param val Number value.
+     * @return Boolean value.
+     */
+    private static boolean castToBoolean(Number val) {
+        if (val.intValue() == 1)
+            return true;
+        else if (val.intValue() == 0)
+            return false;
+        else
+            throw new ClassCastException("Cannot cast " + val.getClass().getName()
+                + " [val=" + val +"] to boolean");
+    }
+
+    /**
+     * @param str String value.
+     * @return Boolean value.
+     */
+    private static boolean castToBoolean(String str) {
+        try {
+            return castToBoolean(Integer.parseInt(str));
+        }
+        catch (NumberFormatException e) {
+            throw new ClassCastException("Cannot cast [val=" + str +"] to boolean");
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java
new file mode 100644
index 0000000..4c560bc
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java
@@ -0,0 +1,161 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.List;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta;
+
+/**
+ * JDBC result set metadata implementation.
+ */
+public class JdbcThinResultSetMetadata implements ResultSetMetaData {
+    /** Column width. */
+    private static final int COL_WIDTH = 30;
+
+    /** Table names. */
+    private final List<JdbcColumnMeta> meta;
+
+    /**
+     * @param meta Metadata.
+     */
+    JdbcThinResultSetMetadata(List<JdbcColumnMeta> meta) {
+        assert meta != null;
+
+        this.meta = meta;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getColumnCount() throws SQLException {
+        return meta.size();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isAutoIncrement(int col) throws SQLException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isCaseSensitive(int col) throws SQLException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSearchable(int col) throws SQLException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isCurrency(int col) throws SQLException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int isNullable(int col) throws SQLException {
+        return columnNullable;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSigned(int col) throws SQLException {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getColumnDisplaySize(int col) throws SQLException {
+        return COL_WIDTH;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getColumnLabel(int col) throws SQLException {
+        return meta.get(col - 1).columnName();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getColumnName(int col) throws SQLException {
+        return meta.get(col - 1).columnName();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSchemaName(int col) throws SQLException {
+        return meta.get(col - 1).schemaName();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getPrecision(int col) throws SQLException {
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getScale(int col) throws SQLException {
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getTableName(int col) throws SQLException {
+        return meta.get(col - 1).tableName();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getCatalogName(int col) throws SQLException {
+        return "";
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getColumnType(int col) throws SQLException {
+        return meta.get(col - 1).dataType();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getColumnTypeName(int col) throws SQLException {
+        return meta.get(col - 1).dataTypeName();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isReadOnly(int col) throws SQLException {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isWritable(int col) throws SQLException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDefinitelyWritable(int col) throws SQLException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getColumnClassName(int col) throws SQLException {
+        return meta.get(col - 1).dataTypeClass();
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> T unwrap(Class<T> iface) throws SQLException {
+        if (!isWrapperFor(iface))
+            throw new SQLException("Result set meta data is not a wrapper for " + iface.getName());
+
+        return (T)this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        return iface != null && iface.isAssignableFrom(JdbcThinResultSetMetadata.class);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
new file mode 100644
index 0000000..2bcd4d1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
@@ -0,0 +1,475 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.util.ArrayList;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.query.SqlQuery;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult;
+
+import static java.sql.ResultSet.CONCUR_READ_ONLY;
+import static java.sql.ResultSet.FETCH_FORWARD;
+import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
+import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
+
+/**
+ * JDBC statement implementation.
+ */
+public class JdbcThinStatement implements Statement {
+    /** Default queryPage size. */
+    private static final int DFLT_PAGE_SIZE = SqlQuery.DFLT_PAGE_SIZE;
+
+    /** Ignite endpoint and I/O protocol implementation. */
+    private JdbcThinConnection conn;
+
+    /** Closed flag. */
+    private boolean closed;
+
+    /** Rows limit. */
+    private int maxRows;
+
+    /** Query timeout. */
+    private int timeout;
+
+    /** Current result set. */
+    private JdbcThinResultSet rs;
+
+    /** Query arguments. */
+    protected ArrayList<Object> args;
+
+    /** Fetch size. */
+    private int pageSize = DFLT_PAGE_SIZE;
+
+    private boolean alreadyRead;
+
+    /**
+     * Creates new statement.
+     *
+     * @param conn JDBC connection.
+     */
+    JdbcThinStatement(JdbcThinConnection conn) {
+        assert conn != null;
+
+        this.conn = conn;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ResultSet executeQuery(String sql) throws SQLException {
+        JdbcThinResultSet rs = execute0(sql);
+
+        if (!rs.isQuery())
+            throw new SQLException("The query isn't SELECT query: [sql=" + sql +']');
+
+        return rs;
+    }
+
+    /**
+     * @param sql Sql query.
+     * @return Result set.
+     * @throws SQLException Onj error.
+     */
+    protected JdbcThinResultSet execute0(String sql) throws SQLException {
+        ensureNotClosed();
+
+        if (rs != null) {
+            rs.close();
+
+            rs = null;
+        }
+
+        alreadyRead = false;
+
+        if (sql == null || sql.isEmpty())
+            throw new SQLException("SQL query is empty.");
+
+        try {
+            JdbcQueryExecuteResult res = conn.cliIo().queryExecute(conn.getSchema(), pageSize, maxRows,
+                sql, args);
+
+            assert res != null;
+
+            rs = new JdbcThinResultSet(this, res.getQueryId(), pageSize, res.last(), res.items(), res.isQuery());
+
+            return rs;
+        }
+        catch (IOException e) {
+            conn.close();
+
+            throw new SQLException("Failed to query Ignite.", e);
+        }
+        catch (IgniteCheckedException e) {
+            throw new SQLException("Failed to query Ignite.", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public int executeUpdate(String sql) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void close() throws SQLException {
+        if (isClosed())
+            return;
+
+        if (rs != null)
+            rs.close();
+
+        closed = true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getMaxFieldSize() throws SQLException {
+        ensureNotClosed();
+
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setMaxFieldSize(int max) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Field size limitation is not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getMaxRows() throws SQLException {
+        ensureNotClosed();
+
+        return maxRows;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setMaxRows(int maxRows) throws SQLException {
+        ensureNotClosed();
+
+        this.maxRows = maxRows;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setEscapeProcessing(boolean enable) throws SQLException {
+        ensureNotClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getQueryTimeout() throws SQLException {
+        ensureNotClosed();
+
+        return timeout / 1000;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setQueryTimeout(int timeout) throws SQLException {
+        ensureNotClosed();
+
+        this.timeout = timeout * 1000;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void cancel() throws SQLException {
+        ensureNotClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public SQLWarning getWarnings() throws SQLException {
+        ensureNotClosed();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clearWarnings() throws SQLException {
+        ensureNotClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setCursorName(String name) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean execute(String sql) throws SQLException {
+        ensureNotClosed();
+
+        rs = execute0(sql);
+
+        return rs.isQuery();
+    }
+
+    /** {@inheritDoc} */
+    @Override public ResultSet getResultSet() throws SQLException {
+        ensureNotClosed();
+
+        if (rs == null || !rs.isQuery() || alreadyRead)
+            return null;
+
+        alreadyRead = true;
+
+        return rs;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getUpdateCount() throws SQLException {
+        ensureNotClosed();
+
+        if (rs == null || rs.isQuery() || alreadyRead)
+            return -1;
+
+        alreadyRead = true;
+
+        return (int)rs.updatedCount();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean getMoreResults() throws SQLException {
+        ensureNotClosed();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setFetchDirection(int direction) throws SQLException {
+        ensureNotClosed();
+
+        if (direction != FETCH_FORWARD)
+            throw new SQLFeatureNotSupportedException("Only forward direction is supported");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getFetchDirection() throws SQLException {
+        ensureNotClosed();
+
+        return FETCH_FORWARD;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setFetchSize(int fetchSize) throws SQLException {
+        ensureNotClosed();
+
+        if (fetchSize <= 0)
+            throw new SQLException("Fetch size must be greater than zero.");
+
+        this.pageSize = fetchSize;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getFetchSize() throws SQLException {
+        ensureNotClosed();
+
+        return pageSize;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getResultSetConcurrency() throws SQLException {
+        ensureNotClosed();
+
+        return CONCUR_READ_ONLY;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getResultSetType() throws SQLException {
+        ensureNotClosed();
+
+        return TYPE_FORWARD_ONLY;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void addBatch(String sql) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clearBatch() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int[] executeBatch() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Connection getConnection() throws SQLException {
+        ensureNotClosed();
+
+        return conn;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean getMoreResults(int curr) throws SQLException {
+        ensureNotClosed();
+
+        if (curr == KEEP_CURRENT_RESULT || curr == CLOSE_ALL_RESULTS)
+            throw new SQLFeatureNotSupportedException("Multiple open results are not supported.");
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ResultSet getGeneratedKeys() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int executeUpdate(String sql, int[] colIndexes) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int executeUpdate(String sql, String[] colNames) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
+        ensureNotClosed();
+
+        if (autoGeneratedKeys == RETURN_GENERATED_KEYS)
+            throw new SQLFeatureNotSupportedException("Updates are not supported.");
+
+        return execute(sql);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean execute(String sql, int[] colIndexes) throws SQLException {
+        ensureNotClosed();
+
+        if (colIndexes != null && colIndexes.length > 0)
+            throw new SQLFeatureNotSupportedException("Updates are not supported.");
+
+        return execute(sql);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean execute(String sql, String[] colNames) throws SQLException {
+        ensureNotClosed();
+
+        if (colNames != null && colNames.length > 0)
+            throw new SQLFeatureNotSupportedException("Updates are not supported.");
+
+        return execute(sql);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getResultSetHoldability() throws SQLException {
+        ensureNotClosed();
+
+        return HOLD_CURSORS_OVER_COMMIT;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isClosed() throws SQLException {
+        return conn.isClosed() || closed;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setPoolable(boolean poolable) throws SQLException {
+        ensureNotClosed();
+
+        if (poolable)
+            throw new SQLFeatureNotSupportedException("Pooling is not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isPoolable() throws SQLException {
+        ensureNotClosed();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> T unwrap(Class<T> iface) throws SQLException {
+        if (!isWrapperFor(iface))
+            throw new SQLException("Statement is not a wrapper for " + iface.getName());
+
+        return (T)this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        return iface != null && iface.isAssignableFrom(JdbcThinStatement.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void closeOnCompletion() throws SQLException {
+        throw new SQLFeatureNotSupportedException("closeOnCompletion is not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isCloseOnCompletion() throws SQLException {
+        ensureNotClosed();
+
+        return false;
+    }
+
+    /**
+     * Sets timeout in milliseconds.
+     *
+     * @param timeout Timeout.
+     */
+    void timeout(int timeout) {
+        this.timeout = timeout;
+    }
+
+    /**
+     * @return Connection.
+     */
+    JdbcThinConnection connection() {
+        return conn;
+    }
+
+    /**
+     * Ensures that statement is not closed.
+     *
+     * @throws SQLException If statement is closed.
+     */
+    protected void ensureNotClosed() throws SQLException {
+        if (isClosed())
+            throw new SQLException("Statement is closed.");
+    }
+}


[43/50] [abbrv] ignite git commit: IGNTIE-5379: JDBC: routed requests to new cache-independent SQL flow. This closes #2081.

Posted by sb...@apache.org.
IGNTIE-5379: JDBC: routed requests to new cache-independent SQL flow. This closes #2081.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ae4d0739
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ae4d0739
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ae4d0739

Branch: refs/heads/ignite-5075
Commit: ae4d0739bc59a034e7f9abeb6bc67c1c7c0e7c48
Parents: 3642d6c
Author: devozerov <vo...@gridgain.com>
Authored: Mon Jun 5 19:03:40 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Mon Jun 5 19:03:40 2017 +0300

----------------------------------------------------------------------
 .../odbc/jdbc/JdbcRequestHandler.java           | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ae4d0739/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
index b319293..e64e9a6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
@@ -17,15 +17,17 @@
 
 package org.apache.ignite.internal.processors.odbc.jdbc;
 
-import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cache.query.FieldsQueryCursor;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
 import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
 import org.apache.ignite.internal.processors.odbc.SqlListenerRequestHandler;
 import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
+import org.apache.ignite.internal.processors.query.QueryUtils;
 import org.apache.ignite.internal.util.GridSpinBusyLock;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 
@@ -158,20 +160,16 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler {
 
             qry.setPageSize(req.pageSize());
 
-            IgniteCache<Object, Object> cache0 = ctx.grid().cache(req.schemaName());
+            String schemaName = req.schemaName();
 
-            if (cache0 == null)
-                return new JdbcResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Cache doesn't exist (did you configure it?): " + req.schemaName());
+            if (F.isEmpty(schemaName))
+                schemaName = QueryUtils.DFLT_SCHEMA;
 
-            IgniteCache<Object, Object> cache = cache0.withKeepBinary();
+            qry.setSchema(schemaName);
 
-            if (cache == null)
-                return new JdbcResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Can not get cache with keep binary: " + req.schemaName());
+            FieldsQueryCursor<List<?>> qryCur = ctx.query().querySqlFieldsNoCache(qry, true);
 
-            JdbcQueryCursor cur = new JdbcQueryCursor(
-                qryId, req.pageSize(), req.maxRows(), (QueryCursorImpl)cache.query(qry));
+            JdbcQueryCursor cur = new JdbcQueryCursor(qryId, req.pageSize(), req.maxRows(), (QueryCursorImpl)qryCur);
 
             qryCursors.put(qryId, cur);
 


[19/50] [abbrv] ignite git commit: IGNITE-5307: Several basic tests for SQL schema operations.

Posted by sb...@apache.org.
IGNITE-5307: Several basic tests for SQL schema operations.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/6f1a900f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/6f1a900f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/6f1a900f

Branch: refs/heads/ignite-5075
Commit: 6f1a900fcf40c780769befd897742206455128ac
Parents: 43ab98b
Author: devozerov <vo...@gridgain.com>
Authored: Fri Jun 2 17:14:37 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 17:14:37 2017 +0300

----------------------------------------------------------------------
 .../query/IgniteSqlSchemaIndexingTest.java      |   3 +-
 .../query/SqlPublicSchemaSelfTest.java          | 198 +++++++++++++++++++
 .../IgniteCacheQuerySelfTestSuite.java          |   3 +
 3 files changed, 202 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/6f1a900f/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
index 3cecbc8..33e35e0 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
@@ -123,8 +123,7 @@ public class IgniteSqlSchemaIndexingTest extends GridCommonAbstractTest {
 
         IgniteCache<Integer, Fact> cache = ignite(0).createCache(cfg);
 
-        SqlFieldsQuery qry = new SqlFieldsQuery("select f.id, f.name " +
-            "from InSENSitive_Cache.Fact f");
+        SqlFieldsQuery qry = new SqlFieldsQuery("select f.id, f.name from InSENSitive_Cache.Fact f");
 
         cache.put(1, new Fact(1, "cacheInsensitive"));
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f1a900f/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlPublicSchemaSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlPublicSchemaSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlPublicSchemaSelfTest.java
new file mode 100644
index 0000000..cbd8972
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlPublicSchemaSelfTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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.processors.query;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * Tests for public schema.
+ */
+public class SqlPublicSchemaSelfTest extends GridCommonAbstractTest {
+    /** Person cache name. */
+    private static final String CACHE_PERSON = "PersonCache";
+
+    /** Person cache 2 name. */
+    private static final String CACHE_PERSON_2 = "PersonCache2";
+
+    /** Node. */
+    private IgniteEx node;
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        node = (IgniteEx)startGrid();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * Test simple query.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSchemaChange() throws Exception {
+        IgniteCache<PersonKey, Person> cache = node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON)
+            .setIndexedTypes(PersonKey.class, Person.class));
+
+        node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON_2)
+            .setIndexedTypes(PersonKey.class, Person.class));
+
+        cache.put(new PersonKey(1), new Person("Vasya", 2));
+
+        // Normal calls.
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM Person")
+        ).getAll().size());
+
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM Person").setSchema(CACHE_PERSON)
+        ).getAll().size());
+
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PersonCache\".Person")
+        ).getAll().size());
+
+        // Call from default schema.
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PersonCache\".Person").setSchema(QueryUtils.DFLT_SCHEMA)
+        ).getAll().size());
+
+        // Call from another schema.
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PersonCache\".Person").setSchema(CACHE_PERSON_2)
+        ).getAll().size());
+    }
+
+    /**
+     * Test simple query.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSchemaChangeOnCacheWithPublicSchema() throws Exception {
+        IgniteCache<PersonKey, Person> cache = node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON)
+            .setIndexedTypes(PersonKey.class, Person.class)
+            .setSqlSchema(QueryUtils.DFLT_SCHEMA));
+
+        node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON_2)
+            .setIndexedTypes(PersonKey.class, Person.class));
+
+        cache.put(new PersonKey(1), new Person("Vasya", 2));
+
+        // Normal calls.
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM Person")
+        ).getAll().size());
+
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM Person").setSchema(QueryUtils.DFLT_SCHEMA)
+        ).getAll().size());
+
+        // Call from another schema.
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM public.Person").setSchema(CACHE_PERSON_2)
+        ).getAll().size());
+
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PUBLIC\".Person").setSchema(CACHE_PERSON_2)
+        ).getAll().size());
+    }
+
+    /**
+     * Test type conflict in public schema.
+     *
+     * @throws Exception If failed.
+     */
+    public void _testTypeConflictInPublicSchema() throws Exception {
+        // TODO: IGNITE-5380: uncomment work after fix.
+        fail("Hang for now, need to fix");
+
+        node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON)
+            .setIndexedTypes(PersonKey.class, Person.class)
+            .setSqlSchema(QueryUtils.DFLT_SCHEMA));
+
+        node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON_2)
+            .setIndexedTypes(PersonKey.class, Person.class)
+            .setSqlSchema(QueryUtils.DFLT_SCHEMA));
+    }
+
+    /**
+     * Person key.
+     */
+    public static class PersonKey {
+        @QuerySqlField
+        public long id;
+
+        /**
+         * Constructor.
+         *
+         * @param id ID.
+         */
+        PersonKey(long id) {
+            this.id = id;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return (int)id;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object obj) {
+            return obj != null && obj instanceof PersonKey && (F.eq(id, ((PersonKey)obj).id));
+        }
+    }
+
+    /**
+     * Person.
+     */
+    public static class Person {
+        /** Name. */
+        @QuerySqlField
+        public String name;
+
+        /** Organization ID. */
+        @QuerySqlField(index = true)
+        public long orgId;
+
+        /**
+         * Constructor.
+         *
+         * @param name Name.
+         * @param orgId Orgainzation ID.
+         */
+        public Person(String name, long orgId) {
+            this.name = name;
+            this.orgId = orgId;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f1a900f/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
index 13dfef7..848ab49 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
@@ -115,6 +115,7 @@ import org.apache.ignite.internal.processors.query.IgniteSqlSchemaIndexingTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexMultiNodeSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSplitterSelfTest;
+import org.apache.ignite.internal.processors.query.SqlPublicSchemaSelfTest;
 import org.apache.ignite.internal.processors.query.h2.GridH2IndexingInMemSelfTest;
 import org.apache.ignite.internal.processors.query.h2.GridH2IndexingOffheapSelfTest;
 import org.apache.ignite.internal.processors.query.h2.IgniteSqlQueryMinMaxTest;
@@ -136,6 +137,8 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
     public static TestSuite suite() throws Exception {
         IgniteTestSuite suite = new IgniteTestSuite("Ignite Cache Queries Test Suite");
 
+        suite.addTestSuite(SqlPublicSchemaSelfTest.class);
+
         // Misc tests.
         // TODO: Enable when IGNITE-1094 is fixed.
         // suite.addTest(new TestSuite(QueryEntityValidationSelfTest.class));


[18/50] [abbrv] ignite git commit: Fixed GridQueryCommandHandlerTest.testNullCache

Posted by sb...@apache.org.
Fixed GridQueryCommandHandlerTest.testNullCache


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/79ab48b8
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/79ab48b8
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/79ab48b8

Branch: refs/heads/ignite-5075
Commit: 79ab48b876f2cd8c1b2fe18dea0492c9f2483694
Parents: 43ab98b
Author: sboikov <sb...@gridgain.com>
Authored: Fri Jun 2 17:14:15 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jun 2 17:14:15 2017 +0300

----------------------------------------------------------------------
 .../processors/rest/handlers/query/QueryCommandHandler.java   | 7 ++++---
 .../rest/handlers/query/GridQueryCommandHandlerTest.java      | 3 ++-
 2 files changed, 6 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/79ab48b8/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
index e7cc3dd..05ca3aa 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
@@ -315,12 +315,13 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
                         throw new IgniteException("Incorrect query type [type=" + req.queryType() + "]");
                 }
 
-                IgniteCache<Object, Object> cache = ctx.grid().cache(
-                    req.cacheName() == null ? DFLT_CACHE_NAME : req.cacheName());
+                String cacheName = req.cacheName() == null ? DFLT_CACHE_NAME : req.cacheName();
+
+                IgniteCache<Object, Object> cache = ctx.grid().cache(cacheName);
 
                 if (cache == null)
                     return new GridRestResponse(GridRestResponse.STATUS_FAILED,
-                        "Failed to find cache with name: " + req.cacheName());
+                        "Failed to find cache with name: " + cacheName);
 
                 final QueryCursor qryCur = cache.query(qry);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/79ab48b8/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/query/GridQueryCommandHandlerTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/query/GridQueryCommandHandlerTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/query/GridQueryCommandHandlerTest.java
index 130899f..cffc7b9 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/query/GridQueryCommandHandlerTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/query/GridQueryCommandHandlerTest.java
@@ -114,7 +114,8 @@ public class GridQueryCommandHandlerTest extends GridCommonAbstractTest {
         IgniteInternalFuture<GridRestResponse> resp = cmdHnd.handleAsync(req);
         resp.get();
 
-        assertEquals("Ouch! Argument is invalid: Cache name must not be null or empty.", resp.result().getError());
+        // If cache name is not set server uses name 'default'.
+        assertEquals("Failed to find cache with name: default", resp.result().getError());
         assertEquals(GridRestResponse.STATUS_FAILED, resp.result().getSuccessStatus());
         assertNull(resp.result().getResponse());
     }


[30/50] [abbrv] ignite git commit: IGNITE-5388 Added support to configuration of Ignite 2.x and Ignite 1.x.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/ConfigurationGenerator.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/ConfigurationGenerator.js b/modules/web-console/frontend/app/modules/configuration/generator/ConfigurationGenerator.js
index 8bc74a9..39ebced 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/ConfigurationGenerator.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/ConfigurationGenerator.js
@@ -20,18 +20,22 @@ import DFLT_DIALECTS from 'app/data/dialects.json';
 import { EmptyBean, Bean } from './Beans';
 
 import IgniteClusterDefaults from './defaults/Cluster.service';
+import IgniteEventGroups from './defaults/Event-groups.service';
 import IgniteCacheDefaults from './defaults/Cache.service';
 import IgniteIGFSDefaults from './defaults/IGFS.service';
 
 import JavaTypes from '../../../services/JavaTypes.service';
+import VersionService from 'app/modules/configuration/Version.service';
 
 const clusterDflts = new IgniteClusterDefaults();
 const cacheDflts = new IgniteCacheDefaults();
 const igfsDflts = new IgniteIGFSDefaults();
-
 const javaTypes = new JavaTypes(clusterDflts, cacheDflts, igfsDflts);
+const versionService = new VersionService();
 
 export default class IgniteConfigurationGenerator {
+    static eventGrps = new IgniteEventGroups();
+
     static igniteConfigurationBean(cluster) {
         return new Bean('org.apache.ignite.configuration.IgniteConfiguration', 'cfg', cluster, clusterDflts);
     }
@@ -60,13 +64,16 @@ export default class IgniteConfigurationGenerator {
      * Function to generate ignite configuration.
      *
      * @param {Object} cluster Cluster to process.
-     * @param {Boolean} client
+     * @param {String} version Target version of configuration.
+     * @param {Boolean} client Is client configuration.
      * @return {Bean} Generated ignite configuration.
      */
-    static igniteConfiguration(cluster, client) {
+    static igniteConfiguration(cluster, version, client) {
+        const available = versionService.since.bind(versionService, version);
+
         const cfg = this.igniteConfigurationBean(cluster);
 
-        this.clusterGeneral(cluster, cfg, client);
+        this.clusterGeneral(cluster, available, cfg, client);
         this.clusterAtomics(cluster.atomicConfiguration, cfg);
         this.clusterBinary(cluster.binaryConfiguration, cfg);
         this.clusterCacheKeyConfiguration(cluster.cacheKeyConfiguration, cfg);
@@ -74,24 +81,37 @@ export default class IgniteConfigurationGenerator {
         this.clusterCollision(cluster.collision, cfg);
         this.clusterCommunication(cluster, cfg);
         this.clusterConnector(cluster.connector, cfg);
-        this.clusterDeployment(cluster, cfg);
-        this.clusterEvents(cluster, cfg);
-        this.clusterFailover(cluster, cfg);
+        this.clusterDeployment(cluster, available, cfg);
+        this.clusterEvents(cluster, available, cfg);
+        this.clusterFailover(cluster, available, cfg);
+        this.clusterHadoop(cluster.hadoopConfiguration, cfg);
         this.clusterLoadBalancing(cluster, cfg);
         this.clusterLogger(cluster.logger, cfg);
+        this.clusterMarshaller(cluster, available, cfg);
+
+        // Since ignite 2.0
+        if (available('2.0.0'))
+            this.clusterMemory(cluster.memoryConfiguration, cfg);
+
+        this.clusterMisc(cluster, available, cfg);
+        this.clusterMetrics(cluster, available, cfg);
         this.clusterODBC(cluster.odbc, cfg);
-        this.clusterMarshaller(cluster, cfg);
-        this.clusterMetrics(cluster, cfg);
-        this.clusterTime(cluster, cfg);
-        this.clusterPools(cluster, cfg);
-        this.clusterTransactions(cluster.transactionConfiguration, cfg);
+        this.clusterServiceConfiguration(cluster.serviceConfigurations, cluster.caches, cfg);
         this.clusterSsl(cluster, cfg);
+
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0']))
+            this.clusterSwap(cluster, cfg);
+
+        this.clusterPools(cluster, available, cfg);
+        this.clusterTime(cluster, available, cfg);
+        this.clusterTransactions(cluster.transactionConfiguration, cfg);
         this.clusterUserAttributes(cluster, cfg);
 
-        this.clusterCaches(cluster, cluster.caches, cluster.igfss, client, cfg);
+        this.clusterCaches(cluster, cluster.caches, cluster.igfss, available, client, cfg);
 
         if (!client)
-            this.clusterIgfss(cluster.igfss, cfg);
+            this.clusterIgfss(cluster.igfss, available, cfg);
 
         return cfg;
     }
@@ -154,12 +174,16 @@ export default class IgniteConfigurationGenerator {
     }
 
     // Generate general section.
-    static clusterGeneral(cluster, cfg = this.igniteConfigurationBean(cluster), client = false) {
+    static clusterGeneral(cluster, available, cfg = this.igniteConfigurationBean(cluster), client = false) {
         if (client)
             cfg.prop('boolean', 'clientMode', true);
 
-        cfg.stringProperty('name', 'igniteInstanceName')
-            .stringProperty('localHost');
+        if (available('2.0.0'))
+            cfg.stringProperty('name', 'igniteInstanceName');
+        else
+            cfg.stringProperty('name', 'gridName');
+
+        cfg.stringProperty('localHost');
 
         if (_.isNil(cluster.discovery))
             return cfg;
@@ -338,12 +362,12 @@ export default class IgniteConfigurationGenerator {
         if (ipFinder)
             discovery.beanProperty('ipFinder', ipFinder);
 
-        this.clusterDiscovery(cluster.discovery, cfg, discovery);
+        this.clusterDiscovery(cluster.discovery, available, cfg, discovery);
 
         return cfg;
     }
 
-    static igfsDataCache(igfs) {
+    static igfsDataCache(igfs, available) {
         return this.cacheConfiguration({
             name: igfs.name + '-data',
             cacheMode: 'PARTITIONED',
@@ -351,25 +375,25 @@ export default class IgniteConfigurationGenerator {
             writeSynchronizationMode: 'FULL_SYNC',
             backups: 0,
             igfsAffinnityGroupSize: igfs.affinnityGroupSize || 512
-        });
+        }, available);
     }
 
-    static igfsMetaCache(igfs) {
+    static igfsMetaCache(igfs, available) {
         return this.cacheConfiguration({
             name: igfs.name + '-meta',
             cacheMode: 'REPLICATED',
             atomicityMode: 'TRANSACTIONAL',
             writeSynchronizationMode: 'FULL_SYNC'
-        });
+        }, available);
     }
 
-    static clusterCaches(cluster, caches, igfss, client, cfg = this.igniteConfigurationBean(cluster)) {
-        const ccfgs = _.map(caches, (cache) => this.cacheConfiguration(cache));
+    static clusterCaches(cluster, caches, igfss, available, client, cfg = this.igniteConfigurationBean(cluster)) {
+        const ccfgs = _.map(caches, (cache) => this.cacheConfiguration(cache, available));
 
         if (!client) {
             _.forEach(igfss, (igfs) => {
-                ccfgs.push(this.igfsDataCache(igfs));
-                ccfgs.push(this.igfsMetaCache(igfs));
+                ccfgs.push(this.igfsDataCache(igfs, available));
+                ccfgs.push(this.igfsMetaCache(igfs, available));
             });
         }
 
@@ -850,7 +874,7 @@ export default class IgniteConfigurationGenerator {
     }
 
     // Generate deployment group.
-    static clusterDeployment(cluster, cfg = this.igniteConfigurationBean(cluster)) {
+    static clusterDeployment(cluster, available, cfg = this.igniteConfigurationBean(cluster)) {
         cfg.enumProperty('deploymentMode')
             .boolProperty('peerClassLoadingEnabled');
 
@@ -861,6 +885,10 @@ export default class IgniteConfigurationGenerator {
                    cluster.peerClassLoadingLocalClassPathExclude);
         }
 
+        // Since ignite 2.0
+        if (available('2.0.0'))
+            cfg.emptyBeanProperty('classLoader');
+
         let deploymentBean = null;
 
         switch (_.get(cluster, 'deploymentSpi.kind')) {
@@ -905,9 +933,7 @@ export default class IgniteConfigurationGenerator {
     }
 
     // Generate discovery group.
-    static clusterDiscovery(discovery, cfg = this.igniteConfigurationBean(), discoSpi = this.discoveryConfigurationBean(discovery)) {
-        // TODO IGNITE-4988 cfg.intProperty('metricsUpdateFrequency')
-
+    static clusterDiscovery(discovery, available, cfg = this.igniteConfigurationBean(), discoSpi = this.discoveryConfigurationBean(discovery)) {
         discoSpi.stringProperty('localAddress')
             .intProperty('localPort')
             .intProperty('localPortRange')
@@ -917,8 +943,16 @@ export default class IgniteConfigurationGenerator {
             .intProperty('maxAckTimeout')
             .intProperty('networkTimeout')
             .intProperty('joinTimeout')
-            .intProperty('threadPriority')
-            .intProperty('topHistorySize')
+            .intProperty('threadPriority');
+
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0'])) {
+            discoSpi.intProperty('heartbeatFrequency')
+                .intProperty('maxMissedHeartbeats')
+                .intProperty('maxMissedClientHeartbeats');
+        }
+
+        discoSpi.intProperty('topHistorySize')
             .emptyBeanProperty('listener')
             .emptyBeanProperty('dataExchange')
             .emptyBeanProperty('metricsProvider')
@@ -936,7 +970,7 @@ export default class IgniteConfigurationGenerator {
     }
 
     // Generate events group.
-    static clusterEvents(cluster, cfg = this.igniteConfigurationBean(cluster)) {
+    static clusterEvents(cluster, available, cfg = this.igniteConfigurationBean(cluster)) {
         const eventStorage = cluster.eventStorage;
 
         let eventStorageBean = null;
@@ -963,19 +997,56 @@ export default class IgniteConfigurationGenerator {
                 // No-op.
         }
 
-        if (eventStorageBean && eventStorageBean.nonEmpty())
-            cfg.beanProperty('eventStorageSpi', eventStorageBean);
+        if (eventStorageBean) {
+            if (!eventStorageBean.isEmpty() || !available(['1.0.0', '2.0.0']))
+                cfg.beanProperty('eventStorageSpi', eventStorageBean);
+
+            if (_.nonEmpty(cluster.includeEventTypes)) {
+                const eventGrps = _.filter(this.eventGrps, ({value}) => _.includes(cluster.includeEventTypes, value));
+
+                if (available('2.0.0')) {
+                    const events = _.reduce(eventGrps, (acc, eventGrp) => {
+                        switch (eventGrp.value) {
+                            case 'EVTS_SWAPSPACE':
+                                // Removed.
+
+                                break;
+                            case 'EVTS_CACHE':
+                                const eventGrpX2 = _.cloneDeep(eventGrp);
+
+                                eventGrpX2.events = _.filter(eventGrpX2.events, (ev) =>
+                                    !_.includes(['EVT_CACHE_OBJECT_SWAPPED', 'EVT_CACHE_OBJECT_UNSWAPPED'], ev));
+
+                                acc.push(eventGrpX2);
 
-        if (_.nonEmpty(cluster.includeEventTypes))
-            cfg.eventTypes('evts', 'includeEventTypes', cluster.includeEventTypes);
+                                break;
+                            default:
+                                acc.push(eventGrp);
+                        }
+
+                        return acc;
+                    }, []);
+
+                    cfg.eventTypes('evts', 'includeEventTypes', events);
+                }
+                else
+                    cfg.eventTypes('evts', 'includeEventTypes', eventGrps);
+            }
+        }
 
         return cfg;
     }
 
     // Generate failover group.
-    static clusterFailover(cluster, cfg = this.igniteConfigurationBean(cluster)) {
+    static clusterFailover(cluster, available, cfg = this.igniteConfigurationBean(cluster)) {
         const spis = [];
 
+        // Since ignite 2.0
+        if (available('2.0.0')) {
+            cfg.intProperty('failureDetectionTimeout')
+                .intProperty('clientFailureDetectionTimeout');
+        }
+
         _.forEach(cluster.failoverSpi, (spi) => {
             let failoverSpi;
 
@@ -1020,6 +1091,51 @@ export default class IgniteConfigurationGenerator {
         return cfg;
     }
 
+    // Generate failover group.
+    static clusterHadoop(hadoop, cfg = this.igniteConfigurationBean()) {
+        const hadoopBean = new Bean('org.apache.ignite.configuration.HadoopConfiguration', 'hadoop', hadoop, clusterDflts.hadoopConfiguration);
+
+        let plannerBean;
+
+        switch (_.get(hadoop, 'mapReducePlanner.kind')) {
+            case 'Weighted':
+                plannerBean = new Bean('org.apache.ignite.hadoop.mapreduce.IgniteHadoopWeightedMapReducePlanner', 'planner',
+                    _.get(hadoop, 'mapReducePlanner.Weighted'), clusterDflts.hadoopConfiguration.mapReducePlanner.Weighted);
+
+                plannerBean.intProperty('localMapperWeight')
+                    .intProperty('remoteMapperWeight')
+                    .intProperty('localReducerWeight')
+                    .intProperty('remoteReducerWeight')
+                    .intProperty('preferLocalReducerThresholdWeight');
+
+                break;
+
+            case 'Custom':
+                const clsName = _.get(hadoop, 'mapReducePlanner.Custom.className');
+
+                if (clsName)
+                    plannerBean = new EmptyBean(clsName);
+
+                break;
+
+            default:
+                // No-op.
+        }
+
+        if (plannerBean)
+            hadoopBean.beanProperty('mapReducePlanner', plannerBean);
+
+        hadoopBean.intProperty('finishedJobInfoTtl')
+            .intProperty('maxParallelTasks')
+            .intProperty('maxTaskQueueSize')
+            .arrayProperty('nativeLibraryNames', 'nativeLibraryNames', _.get(hadoop, 'nativeLibraryNames'));
+
+        if (!hadoopBean.isEmpty())
+            cfg.beanProperty('hadoopConfiguration', hadoopBean);
+
+        return cfg;
+    }
+
     // Generate load balancing configuration group.
     static clusterLoadBalancing(cluster, cfg = this.igniteConfigurationBean(cluster)) {
         const spis = [];
@@ -1161,15 +1277,78 @@ export default class IgniteConfigurationGenerator {
         return cfg;
     }
 
+    // Generate logger group.
+    static clusterMemory(memoryConfiguration, cfg = this.igniteConfigurationBean()) {
+        const memoryBean = new Bean('org.apache.ignite.configuration.MemoryConfiguration', 'memoryConfiguration', memoryConfiguration, clusterDflts.memoryConfiguration);
+
+        memoryBean.intProperty('pageSize')
+            .intProperty('concurrencyLevel')
+            .intProperty('systemCacheInitialSize')
+            .intProperty('systemCacheMaxSize')
+            .stringProperty('defaultMemoryPolicyName');
+
+        if (memoryBean.valueOf('defaultMemoryPolicyName') === 'default')
+            memoryBean.intProperty('defaultMemoryPolicySize');
+
+        const policies = [];
+
+        _.forEach(_.get(memoryConfiguration, 'memoryPolicies'), (plc) => {
+            const plcBean = new Bean('org.apache.ignite.configuration.MemoryPolicyConfiguration', 'policy', plc, clusterDflts.memoryConfiguration.memoryPolicies);
+
+            plcBean.stringProperty('name')
+                .intProperty('initialSize')
+                .intProperty('maxSize')
+                .stringProperty('swapFilePath')
+                .enumProperty('pageEvictionMode')
+                .intProperty('evictionThreshold')
+                .intProperty('emptyPagesPoolSize')
+                .boolProperty('metricsEnabled');
+
+            policies.push(plcBean);
+        });
+
+        if (!_.isEmpty(policies))
+            memoryBean.arrayProperty('memoryPolicies', 'memoryPolicies', policies, 'org.apache.ignite.configuration.MemoryPolicyConfiguration');
+
+        if (memoryBean.isEmpty())
+            return cfg;
+
+        cfg.beanProperty('memoryConfiguration', memoryBean);
+
+        return cfg;
+    }
+
+    // Generate miscellaneous configuration.
+    static clusterMisc(cluster, available, cfg = this.igniteConfigurationBean(cluster)) {
+        cfg.stringProperty('workDirectory');
+
+        // Since Ignite 2.0
+        if (available('2.0.0')) {
+            cfg.stringProperty('consistentId')
+                .emptyBeanProperty('warmupClosure')
+                .boolProperty('activeOnStart')
+                .boolProperty('cacheSanityCheckEnabled');
+        }
+
+        cfg.boolProperty('lateAffinityAssignment');
+
+        return cfg;
+    }
+
     // Generate IGFSs configs.
-    static clusterIgfss(igfss, cfg = this.igniteConfigurationBean()) {
+    static clusterIgfss(igfss, available, cfg = this.igniteConfigurationBean()) {
         const igfsCfgs = _.map(igfss, (igfs) => {
-            const igfsCfg = this.igfsGeneral(igfs);
+            const igfsCfg = this.igfsGeneral(igfs, available);
 
             this.igfsIPC(igfs, igfsCfg);
             this.igfsFragmentizer(igfs, igfsCfg);
+
+            // Removed in ignite 2.0
+            if (available(['1.0.0', '2.0.0']))
+                this.igfsDualMode(igfs, igfsCfg);
+
             this.igfsSecondFS(igfs, igfsCfg);
-            this.igfsMisc(igfs, igfsCfg);
+            this.igfsMisc(igfs, available, igfsCfg);
 
             return igfsCfg;
         });
@@ -1180,7 +1359,7 @@ export default class IgniteConfigurationGenerator {
     }
 
     // Generate marshaller group.
-    static clusterMarshaller(cluster, cfg = this.igniteConfigurationBean(cluster)) {
+    static clusterMarshaller(cluster, available, cfg = this.igniteConfigurationBean(cluster)) {
         const kind = _.get(cluster.marshaller, 'kind');
         const settings = _.get(cluster.marshaller, kind);
 
@@ -1188,7 +1367,7 @@ export default class IgniteConfigurationGenerator {
 
         switch (kind) {
             case 'OptimizedMarshaller':
-                bean = new Bean('org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller', 'marshaller', settings)
+                bean = new Bean('org.apache.ignite.marshaller.optimized.OptimizedMarshaller', 'marshaller', settings)
                     .intProperty('poolSize')
                     .intProperty('requireSerializable');
 
@@ -1208,15 +1387,24 @@ export default class IgniteConfigurationGenerator {
 
         cfg.intProperty('marshalLocalJobs');
 
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0'])) {
+            cfg.intProperty('marshallerCacheKeepAliveTime')
+                .intProperty('marshallerCacheThreadPoolSize', 'marshallerCachePoolSize');
+        }
+
         return cfg;
     }
 
     // Generate metrics group.
-    static clusterMetrics(cluster, cfg = this.igniteConfigurationBean(cluster)) {
+    static clusterMetrics(cluster, available, cfg = this.igniteConfigurationBean(cluster)) {
         cfg.intProperty('metricsExpireTime')
             .intProperty('metricsHistorySize')
-            .intProperty('metricsLogFrequency')
-            .intProperty('metricsUpdateFrequency');
+            .intProperty('metricsLogFrequency');
+
+        // Since ignite 2.0
+        if (available('2.0.0'))
+            cfg.intProperty('metricsUpdateFrequency');
 
         return cfg;
     }
@@ -1237,20 +1425,43 @@ export default class IgniteConfigurationGenerator {
         return cfg;
     }
 
+    // Java code generator for cluster's service configurations.
+    static clusterServiceConfiguration(srvs, caches, cfg = this.igniteConfigurationBean()) {
+        const srvBeans = [];
+
+        _.forEach(srvs, (srv) => {
+            const bean = new Bean('org.apache.ignite.services.ServiceConfiguration', 'service', srv, clusterDflts.serviceConfigurations);
+
+            bean.stringProperty('name')
+                .emptyBeanProperty('service')
+                .intProperty('maxPerNodeCount')
+                .intProperty('totalCount')
+                .stringProperty('cache', 'cacheName', (_id) => _id ? _.find(caches, {_id}).name : null)
+                .stringProperty('affinityKey');
+
+            srvBeans.push(bean);
+        });
+
+        if (!_.isEmpty(srvBeans))
+            cfg.arrayProperty('services', 'serviceConfiguration', srvBeans, 'org.apache.ignite.services.ServiceConfiguration');
+
+        return cfg;
+    }
+
     // Java code generator for cluster's SSL configuration.
     static clusterSsl(cluster, cfg = this.igniteConfigurationBean(cluster)) {
         if (cluster.sslEnabled && _.nonNil(cluster.sslContextFactory)) {
             const bean = new Bean('org.apache.ignite.ssl.SslContextFactory', 'sslCtxFactory',
                 cluster.sslContextFactory);
 
-            bean.stringProperty('keyAlgorithm')
+            bean.intProperty('keyAlgorithm')
                 .pathProperty('keyStoreFilePath');
 
             if (_.nonEmpty(bean.valueOf('keyStoreFilePath')))
                 bean.propertyChar('keyStorePassword', 'ssl.key.storage.password', 'YOUR_SSL_KEY_STORAGE_PASSWORD');
 
-            bean.stringProperty('keyStoreType')
-                .stringProperty('protocol');
+            bean.intProperty('keyStoreType')
+                .intProperty('protocol');
 
             if (_.nonEmpty(cluster.sslContextFactory.trustManagers)) {
                 bean.arrayProperty('trustManagers', 'trustManagers',
@@ -1263,7 +1474,7 @@ export default class IgniteConfigurationGenerator {
                 if (_.nonEmpty(bean.valueOf('trustStoreFilePath')))
                     bean.propertyChar('trustStorePassword', 'ssl.trust.storage.password', 'YOUR_SSL_TRUST_STORAGE_PASSWORD');
 
-                bean.stringProperty('trustStoreType');
+                bean.intProperty('trustStoreType');
             }
 
             cfg.beanProperty('sslContextFactory', bean);
@@ -1272,8 +1483,31 @@ export default class IgniteConfigurationGenerator {
         return cfg;
     }
 
+    // Generate swap group.
+    static clusterSwap(cluster, cfg = this.igniteConfigurationBean(cluster)) {
+        if (_.get(cluster.swapSpaceSpi, 'kind') === 'FileSwapSpaceSpi') {
+            const bean = new Bean('org.apache.ignite.spi.swapspace.file.FileSwapSpaceSpi', 'swapSpaceSpi',
+                cluster.swapSpaceSpi.FileSwapSpaceSpi);
+
+            bean.pathProperty('baseDirectory')
+                .intProperty('readStripesNumber')
+                .floatProperty('maximumSparsity')
+                .intProperty('maxWriteQueueSize')
+                .intProperty('writeBufferSize');
+
+            cfg.beanProperty('swapSpaceSpi', bean);
+        }
+
+        return cfg;
+    }
+
     // Generate time group.
-    static clusterTime(cluster, cfg = this.igniteConfigurationBean(cluster)) {
+    static clusterTime(cluster, available, cfg = this.igniteConfigurationBean(cluster)) {
+        if (available(['1.0.0', '2.0.0'])) {
+            cfg.intProperty('clockSyncSamples')
+                .intProperty('clockSyncFrequency');
+        }
+
         cfg.intProperty('timeServerPortBase')
             .intProperty('timeServerPortRange');
 
@@ -1281,12 +1515,38 @@ export default class IgniteConfigurationGenerator {
     }
 
     // Generate thread pools group.
-    static clusterPools(cluster, cfg = this.igniteConfigurationBean(cluster)) {
+    static clusterPools(cluster, available, cfg = this.igniteConfigurationBean(cluster)) {
         cfg.intProperty('publicThreadPoolSize')
             .intProperty('systemThreadPoolSize')
+            .intProperty('serviceThreadPoolSize')
             .intProperty('managementThreadPoolSize')
             .intProperty('igfsThreadPoolSize')
-            .intProperty('rebalanceThreadPoolSize');
+            .intProperty('rebalanceThreadPoolSize')
+            .intProperty('utilityCacheThreadPoolSize', 'utilityCachePoolSize')
+            .intProperty('utilityCacheKeepAliveTime')
+            .intProperty('asyncCallbackPoolSize')
+            .intProperty('stripedPoolSize');
+
+        // Since ignite 2.0
+        if (available('2.0.0')) {
+            cfg.intProperty('dataStreamerThreadPoolSize')
+                .intProperty('queryThreadPoolSize');
+
+            const executors = [];
+
+            _.forEach(cluster.executorConfiguration, (exec) => {
+                const execBean = new Bean('org.apache.ignite.configuration.ExecutorConfiguration', 'executor', exec);
+
+                execBean.stringProperty('name')
+                    .intProperty('size');
+
+                if (!execBean.isEmpty())
+                    executors.push(execBean);
+            });
+
+            if (!_.isEmpty(executors))
+                cfg.arrayProperty('executors', 'executorConfiguration', executors, 'org.apache.ignite.configuration.ExecutorConfiguration');
+        }
 
         return cfg;
     }
@@ -1427,7 +1687,7 @@ export default class IgniteConfigurationGenerator {
     }
 
     // Generate cache general group.
-    static cacheGeneral(cache, ccfg = this.cacheConfigurationBean(cache)) {
+    static cacheGeneral(cache, available, ccfg = this.cacheConfigurationBean(cache)) {
         ccfg.stringProperty('name')
             .enumProperty('cacheMode')
             .enumProperty('atomicityMode');
@@ -1437,7 +1697,9 @@ export default class IgniteConfigurationGenerator {
                 .intProperty('readFromBackup');
         }
 
-        ccfg.enumProperty('partitionLossPolicy');
+        // Since ignite 2.0
+        if (available('2.0.0'))
+            ccfg.enumProperty('partitionLossPolicy');
 
         ccfg.intProperty('copyOnRead');
 
@@ -1459,7 +1721,7 @@ export default class IgniteConfigurationGenerator {
     }
 
     // Generate cache memory group.
-    static cacheAffinity(cache, ccfg = this.cacheConfigurationBean(cache)) {
+    static cacheAffinity(cache, available, ccfg = this.cacheConfigurationBean(cache)) {
         switch (_.get(cache, 'affinity.kind')) {
             case 'Rendezvous':
                 ccfg.beanProperty('affinity', this.cacheAffinityFunction('org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction', cache.affinity.Rendezvous));
@@ -1479,18 +1741,46 @@ export default class IgniteConfigurationGenerator {
 
         ccfg.emptyBeanProperty('affinityMapper');
 
+        // Since ignite 2.0
+        if (available('2.0.0'))
+            ccfg.emptyBeanProperty('topologyValidator');
+
         return ccfg;
     }
 
     // Generate cache memory group.
-    static cacheMemory(cache, ccfg = this.cacheConfigurationBean(cache)) {
+    static cacheMemory(cache, available, ccfg = this.cacheConfigurationBean(cache)) {
+        // Since ignite 2.0
+        if (available('2.0.0'))
+            ccfg.stringProperty('memoryPolicyName');
+
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0'])) {
+            ccfg.enumProperty('memoryMode');
+
+            if (ccfg.valueOf('memoryMode') !== 'OFFHEAP_VALUES')
+                ccfg.intProperty('offHeapMaxMemory');
+        }
+
+        // Since ignite 2.0
+        if (available('2.0.0')) {
+            ccfg.boolProperty('onheapCacheEnabled')
+                .emptyBeanProperty('evictionFilter');
+        }
+
         this._evictionPolicy(ccfg, 'evictionPolicy', cache.evictionPolicy, cacheDflts.evictionPolicy);
 
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0'])) {
+            ccfg.intProperty('startSize')
+                .boolProperty('swapEnabled');
+        }
+
         return ccfg;
     }
 
     // Generate cache queries & Indexing group.
-    static cacheQuery(cache, domains, ccfg = this.cacheConfigurationBean(cache)) {
+    static cacheQuery(cache, domains, available, ccfg = this.cacheConfigurationBean(cache)) {
         const indexedTypes = _.reduce(domains, (acc, domain) => {
             if (domain.queryMetadata === 'Annotations')
                 acc.push(domain.keyType, domain.valueType);
@@ -1498,19 +1788,34 @@ export default class IgniteConfigurationGenerator {
             return acc;
         }, []);
 
-        ccfg.stringProperty('sqlSchema')
-            .intProperty('longQueryWarningTimeout')
+        ccfg.stringProperty('sqlSchema');
+
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0']))
+            ccfg.intProperty('sqlOnheapRowCacheSize');
+
+        ccfg.intProperty('longQueryWarningTimeout')
             .arrayProperty('indexedTypes', 'indexedTypes', indexedTypes, 'java.lang.Class')
             .intProperty('queryDetailMetricsSize')
-            .intProperty('queryParallelism')
-            .arrayProperty('sqlFunctionClasses', 'sqlFunctionClasses', cache.sqlFunctionClasses, 'java.lang.Class')
-            .intProperty('sqlEscapeAll');
+            .arrayProperty('sqlFunctionClasses', 'sqlFunctionClasses', cache.sqlFunctionClasses, 'java.lang.Class');
+
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0']))
+            ccfg.intProperty('snapshotableIndex');
+
+        ccfg.intProperty('sqlEscapeAll');
+
+        // Since ignite 2.0
+        if (available('2.0.0')) {
+            ccfg.intProperty('queryParallelism')
+                .intProperty('sqlIndexMaxInlineSize');
+        }
 
         return ccfg;
     }
 
     // Generate cache store group.
-    static cacheStore(cache, domains, ccfg = this.cacheConfigurationBean(cache)) {
+    static cacheStore(cache, domains, available, ccfg = this.cacheConfigurationBean(cache)) {
         const kind = _.get(cache, 'cacheStoreFactory.kind');
 
         if (kind && cache.cacheStoreFactory[kind]) {
@@ -1611,52 +1916,66 @@ export default class IgniteConfigurationGenerator {
                 .intProperty('writeBehindFlushSize')
                 .intProperty('writeBehindFlushFrequency')
                 .intProperty('writeBehindFlushThreadCount');
+
+            // Since ignite 2.0
+            if (available('2.0.0'))
+                ccfg.boolProperty('writeBehindCoalescing');
         }
 
         return ccfg;
     }
 
     // Generate cache concurrency control group.
-    static cacheConcurrency(cache, ccfg = this.cacheConfigurationBean(cache)) {
+    static cacheConcurrency(cache, available, ccfg = this.cacheConfigurationBean(cache)) {
         ccfg.intProperty('maxConcurrentAsyncOperations')
-            .intProperty('defaultLockTimeout')
-            .enumProperty('writeSynchronizationMode');
+            .intProperty('defaultLockTimeout');
 
-        return ccfg;
-    }
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0']))
+            ccfg.enumProperty('atomicWriteOrderMode');
 
-    // Generate cache node filter group.
-    static cacheNodeFilter(cache, igfss, ccfg = this.cacheConfigurationBean(cache)) {
-        const kind = _.get(cache, 'nodeFilter.kind');
+        ccfg.enumProperty('writeSynchronizationMode');
 
-        const settings = _.get(cache.nodeFilter, kind);
+        return ccfg;
+    }
 
-        if (_.isNil(settings))
-            return ccfg;
+    static nodeFilter(filter, igfss) {
+        const kind = _.get(filter, 'kind');
 
-        let bean = null;
+        const settings = _.get(filter, kind);
 
-        switch (kind) {
-            case 'IGFS':
-                const foundIgfs = _.find(igfss, {_id: settings.igfs});
+        if (!_.isNil(settings)) {
+            switch (kind) {
+                case 'IGFS':
+                    const foundIgfs = _.find(igfss, {_id: settings.igfs});
 
-                if (foundIgfs) {
-                    bean = new Bean('org.apache.ignite.internal.processors.igfs.IgfsNodePredicate', 'nodeFilter', foundIgfs)
-                        .stringConstructorArgument('name');
-                }
+                    if (foundIgfs) {
+                        return new Bean('org.apache.ignite.internal.processors.igfs.IgfsNodePredicate', 'nodeFilter', foundIgfs)
+                            .stringConstructorArgument('name');
+                    }
 
-                break;
-            case 'Custom':
-                if (_.nonEmpty(settings.className))
-                    bean = new EmptyBean(settings.className);
+                    break;
+                case 'Custom':
+                    if (_.nonEmpty(settings.className))
+                        return new EmptyBean(settings.className);
 
-                break;
-            default:
+                    break;
+                default:
                 // No-op.
+            }
         }
 
-        if (bean)
-            ccfg.beanProperty('nodeFilter', bean);
+        return null;
+    }
+
+    // Generate cache node filter group.
+    static cacheNodeFilter(cache, igfss, ccfg = this.cacheConfigurationBean(cache)) {
+        const filter = _.get(cache, 'nodeFilter');
+
+        const filterBean = this.nodeFilter(filter, igfss);
+
+        if (filterBean)
+            ccfg.beanProperty('nodeFilter', filterBean);
 
         return ccfg;
     }
@@ -1744,16 +2063,16 @@ export default class IgniteConfigurationGenerator {
         ccfg.collectionProperty('qryEntities', 'queryEntities', qryEntities, 'org.apache.ignite.cache.QueryEntity');
     }
 
-    static cacheConfiguration(cache, ccfg = this.cacheConfigurationBean(cache)) {
-        this.cacheGeneral(cache, ccfg);
-        this.cacheAffinity(cache, ccfg);
-        this.cacheMemory(cache, ccfg);
-        this.cacheQuery(cache, cache.domains, ccfg);
-        this.cacheStore(cache, cache.domains, ccfg);
+    static cacheConfiguration(cache, available, ccfg = this.cacheConfigurationBean(cache)) {
+        this.cacheGeneral(cache, available, ccfg);
+        this.cacheAffinity(cache, available, ccfg);
+        this.cacheMemory(cache, available, ccfg);
+        this.cacheQuery(cache, cache.domains, available, ccfg);
+        this.cacheStore(cache, cache.domains, available, ccfg);
 
         const igfs = _.get(cache, 'nodeFilter.IGFS.instance');
         this.cacheNodeFilter(cache, igfs ? [igfs] : [], ccfg);
-        this.cacheConcurrency(cache, ccfg);
+        this.cacheConcurrency(cache, available, ccfg);
         this.cacheRebalance(cache, ccfg);
         this.cacheNearServer(cache, ccfg);
         this.cacheStatistics(cache, ccfg);
@@ -1763,12 +2082,19 @@ export default class IgniteConfigurationGenerator {
     }
 
     // Generate IGFS general group.
-    static igfsGeneral(igfs, cfg = this.igfsConfigurationBean(igfs)) {
+    static igfsGeneral(igfs, available, cfg = this.igfsConfigurationBean(igfs)) {
         if (_.isEmpty(igfs.name))
             return cfg;
 
-        cfg.stringProperty('name')
-            .enumProperty('defaultMode');
+        cfg.stringProperty('name');
+
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0'])) {
+            cfg.stringProperty('name', 'dataCacheName', (name) => name + '-data')
+                .stringProperty('name', 'metaCacheName', (name) => name + '-meta');
+        }
+
+        cfg.enumProperty('defaultMode');
 
         return cfg;
     }
@@ -1830,20 +2156,50 @@ export default class IgniteConfigurationGenerator {
         return cfg;
     }
 
+    // Generate IGFS Dual mode group.
+    static igfsDualMode(igfs, cfg = this.igfsConfigurationBean(igfs)) {
+        cfg.intProperty('dualModeMaxPendingPutsSize')
+            .emptyBeanProperty('dualModePutExecutorService')
+            .intProperty('dualModePutExecutorServiceShutdown');
+
+        return cfg;
+    }
+
     // Generate IGFS miscellaneous group.
-    static igfsMisc(igfs, cfg = this.igfsConfigurationBean(igfs)) {
-        cfg.intProperty('blockSize')
-            .intProperty('bufferSize')
-            .intProperty('maximumTaskRangeLength')
+    static igfsMisc(igfs, available, cfg = this.igfsConfigurationBean(igfs)) {
+        cfg.intProperty('blockSize');
+
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0']))
+            cfg.intProperty('streamBufferSize');
+
+        // Since ignite 2.0
+        if (available('2.0.0'))
+            cfg.intProperty('streamBufferSize', 'bufferSize');
+
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0']))
+            cfg.intProperty('maxSpaceSize');
+
+        cfg.intProperty('maximumTaskRangeLength')
             .intProperty('managementPort')
             .intProperty('perNodeBatchSize')
             .intProperty('perNodeParallelBatchCount')
             .intProperty('prefetchBlocks')
-            .intProperty('sequentialReadsBeforePrefetch')
-            .intProperty('colocateMetadata')
+            .intProperty('sequentialReadsBeforePrefetch');
+
+        // Removed in ignite 2.0
+        if (available(['1.0.0', '2.0.0']))
+            cfg.intProperty('trashPurgeTimeout');
+
+        cfg.intProperty('colocateMetadata')
             .intProperty('relaxedConsistency')
             .mapProperty('pathModes', 'pathModes');
 
+        // Since ignite 2.0
+        if (available('2.0.0'))
+            cfg.boolProperty('updateFileLengthOnFlush');
+
         return cfg;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/Docker.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/Docker.service.js b/modules/web-console/frontend/app/modules/configuration/generator/Docker.service.js
index bcfa2e2..91457e8 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/Docker.service.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/Docker.service.js
@@ -23,13 +23,13 @@ export default class IgniteDockerGenerator {
      * Generate from section.
      *
      * @param {Object} cluster Cluster.
-     * @param {String} ver Ignite version.
+     * @param {Object} targetVer Target version.
      * @returns {String}
      */
-    from(cluster, ver) {
+    from(cluster, targetVer) {
         return [
             '# Start from Apache Ignite image.',
-            `FROM apacheignite/ignite:${ver}`
+            `FROM apacheignite/ignite:${targetVer.ignite}`
         ].join('\n');
     }
 
@@ -37,11 +37,11 @@ export default class IgniteDockerGenerator {
      * Generate Docker file for cluster.
      *
      * @param {Object} cluster Cluster.
-     * @param {String} ver Ignite version.
+     * @param {Object} targetVer Target version.
      */
-    generate(cluster, ver) {
+    generate(cluster, targetVer) {
         return [
-            this.from(cluster, ver),
+            this.from(cluster, targetVer),
             '',
             '# Set config uri for node.',
             `ENV CONFIG_URI config/${cluster.name}-server.xml`,

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js b/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js
index df10b23..bf1a667 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js
@@ -568,12 +568,17 @@ export default class IgniteJavaTransformer extends AbstractTransformer {
 
                     break;
                 case 'EVENT_TYPES':
-                    if (prop.eventTypes.length === 1)
-                        this._setProperty(sb, id, prop.name, _.head(prop.eventTypes));
+                    if (prop.eventTypes.length === 1) {
+                        const evtGrp = _.head(prop.eventTypes);
+
+                        this._setProperty(sb, id, prop.name, evtGrp.label);
+                    }
                     else {
-                        sb.append(`int[] ${prop.id} = new int[${_.head(prop.eventTypes)}.length`);
+                        const evtGrp = _.map(prop.eventTypes, 'label');
 
-                        _.forEach(_.tail(prop.eventTypes), (evtGrp) => {
+                        sb.append(`int[] ${prop.id} = new int[${_.head(evtGrp)}.length`);
+
+                        _.forEach(_.tail(evtGrp), (evtGrp) => {
                             sb.append(`    + ${evtGrp}.length`);
                         });
 
@@ -583,12 +588,12 @@ export default class IgniteJavaTransformer extends AbstractTransformer {
 
                         sb.append('int k = 0;');
 
-                        _.forEach(prop.eventTypes, (evtGrp, evtIdx) => {
+                        _.forEach(evtGrp, (evtGrp, evtIdx) => {
                             sb.emptyLine();
 
                             sb.append(`System.arraycopy(${evtGrp}, 0, ${prop.id}, k, ${evtGrp}.length);`);
 
-                            if (evtIdx < prop.eventTypes.length - 1)
+                            if (evtIdx < evtGrp.length - 1)
                                 sb.append(`k += ${evtGrp}.length;`);
                         });
 
@@ -810,7 +815,7 @@ export default class IgniteJavaTransformer extends AbstractTransformer {
     }
 
     static _prepareImports(imports) {
-        return _.sortedUniq(_.sortBy(_.filter(imports, (cls) => !cls.startsWith('java.lang.') && _.includes(cls, '.'))));
+        return _.sortedUniq(_.sortBy(_.filter(imports, (cls) => !_.startsWith(cls, 'java.lang.') && _.includes(cls, '.'))));
     }
 
     /**
@@ -823,10 +828,8 @@ export default class IgniteJavaTransformer extends AbstractTransformer {
         _.forEach(bean.properties, (prop) => {
             switch (prop.clsName) {
                 case 'EVENT_TYPES':
-                    _.forEach(prop.eventTypes, (value) => {
-                        const evtGrp = _.find(this.eventGroups, {value});
-
-                        imports.push(`${evtGrp.class}.${evtGrp.value}`);
+                    _.forEach(prop.eventTypes, (grp) => {
+                        imports.push(`${grp.class}.${grp.value}`);
                     });
 
                     break;
@@ -1035,10 +1038,11 @@ export default class IgniteJavaTransformer extends AbstractTransformer {
         return sb;
     }
 
-    static cluster(cluster, pkg, clsName, client) {
-        const cfg = this.generator.igniteConfiguration(cluster, client);
+    static cluster(cluster, targetVer, pkg, clsName, client) {
+        const cfg = this.generator.igniteConfiguration(cluster, targetVer, client);
 
-        const clientNearCaches = client ? _.filter(cluster.caches, (cache) => _.get(cache, 'clientNearConfiguration.enabled')) : [];
+        const clientNearCaches = client ? _.filter(cluster.caches, (cache) =>
+            cache.mode === 'PARTITIONED' && _.get(cache, 'clientNearConfiguration.enabled')) : [];
 
         return this.igniteConfiguration(cfg, pkg, clsName, clientNearCaches);
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/Maven.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/Maven.service.js b/modules/web-console/frontend/app/modules/configuration/generator/Maven.service.js
index 23a9c4e..f6f6a80 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/Maven.service.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/Maven.service.js
@@ -16,7 +16,6 @@
  */
 
 import StringBuilder from './StringBuilder';
-import IgniteVersion from 'app/modules/configuration/Version.service';
 
 // Java built-in class names.
 import POM_DEPENDENCIES from 'app/data/pom-dependencies.json';
@@ -142,11 +141,11 @@ export default class IgniteMavenGenerator {
     /**
      * Generate pom.xml.
      *
-     * @param cluster Cluster  to take info about dependencies.
-     * @param version Version for Ignite dependencies.
-     * @returns {string} Generated content.
+     * @param {Object} cluster Cluster  to take info about dependencies.
+     * @param {Object} targetVer Target version for dependencies.
+     * @returns {String} Generated content.
      */
-    generate(cluster, version = IgniteVersion.ignite) {
+    generate(cluster, targetVer) {
         const caches = cluster.caches;
         const deps = [];
         const storeDeps = [];
@@ -154,12 +153,14 @@ export default class IgniteMavenGenerator {
 
         const blobStoreFactory = {cacheStoreFactory: {kind: 'CacheHibernateBlobStoreFactory'}};
 
+        const igniteVer = targetVer.ignite;
+
         _.forEach(caches, (cache) => {
             if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind)
                 this.storeFactoryDependency(storeDeps, cache.cacheStoreFactory[cache.cacheStoreFactory.kind]);
 
             if (_.get(cache, 'nodeFilter.kind') === 'Exclude')
-                this.addDependency(deps, 'org.apache.ignite', 'ignite-extdata-p2p', version);
+                this.addDependency(deps, 'org.apache.ignite', 'ignite-extdata-p2p', igniteVer);
         });
 
         const sb = new StringBuilder();
@@ -178,21 +179,21 @@ export default class IgniteMavenGenerator {
 
         sb.emptyLine();
 
-        this.artifact(sb, cluster, version);
+        this.artifact(sb, cluster, igniteVer);
 
-        this.addDependency(deps, 'org.apache.ignite', 'ignite-core', version);
+        this.addDependency(deps, 'org.apache.ignite', 'ignite-core', igniteVer);
 
-        this.addDependency(deps, 'org.apache.ignite', 'ignite-spring', version);
-        this.addDependency(deps, 'org.apache.ignite', 'ignite-indexing', version);
-        this.addDependency(deps, 'org.apache.ignite', 'ignite-rest-http', version);
+        this.addDependency(deps, 'org.apache.ignite', 'ignite-spring', igniteVer);
+        this.addDependency(deps, 'org.apache.ignite', 'ignite-indexing', igniteVer);
+        this.addDependency(deps, 'org.apache.ignite', 'ignite-rest-http', igniteVer);
 
         if (_.get(cluster, 'deploymentSpi.kind') === 'URI')
-            this.addDependency(deps, 'org.apache.ignite', 'ignite-urideploy', version);
+            this.addDependency(deps, 'org.apache.ignite', 'ignite-urideploy', igniteVer);
 
         let dep = POM_DEPENDENCIES[cluster.discovery.kind];
 
         if (dep)
-            this.addDependency(deps, 'org.apache.ignite', dep.artifactId, version);
+            this.addDependency(deps, 'org.apache.ignite', dep.artifactId, igniteVer);
 
         if (cluster.discovery.kind === 'Jdbc') {
             const store = cluster.discovery.Jdbc;
@@ -206,23 +207,24 @@ export default class IgniteMavenGenerator {
                 dep = POM_DEPENDENCIES.S3;
 
                 if (dep)
-                    this.addDependency(deps, 'org.apache.ignite', dep.artifactId, version);
+                    this.addDependency(deps, 'org.apache.ignite', dep.artifactId, igniteVer);
             }
             else if (spi.kind === 'JDBC')
                 this.storeFactoryDependency(storeDeps, spi.JDBC);
         });
 
-        if (_.find(cluster.igfss, (igfs) => igfs.secondaryFileSystemEnabled))
-            this.addDependency(deps, 'org.apache.ignite', 'ignite-hadoop', version);
+        if (_.get(cluster, 'hadoopConfiguration.mapReducePlanner.kind') === 'Weighted' ||
+            _.find(cluster.igfss, (igfs) => igfs.secondaryFileSystemEnabled))
+            this.addDependency(deps, 'org.apache.ignite', 'ignite-hadoop', igniteVer);
 
         if (_.find(caches, blobStoreFactory))
-            this.addDependency(deps, 'org.apache.ignite', 'ignite-hibernate', version);
+            this.addDependency(deps, 'org.apache.ignite', 'ignite-hibernate', igniteVer);
 
         if (cluster.logger && cluster.logger.kind) {
             dep = POM_DEPENDENCIES[cluster.logger.kind];
 
             if (dep)
-                this.addDependency(deps, 'org.apache.ignite', dep.artifactId, version);
+                this.addDependency(deps, 'org.apache.ignite', dep.artifactId, igniteVer);
         }
 
         this.dependencies(sb, cluster, deps.concat(storeDeps));

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/PlatformGenerator.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/PlatformGenerator.js b/modules/web-console/frontend/app/modules/configuration/generator/PlatformGenerator.js
index d1a9092..b076193 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/PlatformGenerator.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/PlatformGenerator.js
@@ -184,8 +184,6 @@ export default ['JavaTypes', 'igniteClusterPlatformDefaults', 'igniteCachePlatfo
         // Generate discovery group.
         static clusterDiscovery(discovery, cfg = this.igniteConfigurationBean()) {
             if (discovery) {
-                // TODO IGNITE-4988 cfg.intProperty('metricsUpdateFrequency')
-
                 let discoveryCfg = cfg.findProperty('discovery');
 
                 if (_.isNil(discoveryCfg)) {
@@ -202,6 +200,9 @@ export default ['JavaTypes', 'igniteClusterPlatformDefaults', 'igniteCachePlatfo
                     .intProperty('networkTimeout')
                     .intProperty('joinTimeout')
                     .intProperty('threadPriority')
+                    .intProperty('heartbeatFrequency')
+                    .intProperty('maxMissedHeartbeats')
+                    .intProperty('maxMissedClientHeartbeats')
                     .intProperty('topHistorySize')
                     .intProperty('reconnectCount')
                     .intProperty('statisticsPrintFrequency')
@@ -281,8 +282,6 @@ export default ['JavaTypes', 'igniteClusterPlatformDefaults', 'igniteCachePlatfo
                     .intProperty('readFromBackup');
             }
 
-            ccfg.enumProperty('partitionLossPolicy');
-
             ccfg.intProperty('copyOnRead');
 
             if (ccfg.valueOf('cacheMode') === 'PARTITIONED' && ccfg.valueOf('atomicityMode') === 'TRANSACTIONAL')
@@ -293,14 +292,23 @@ export default ['JavaTypes', 'igniteClusterPlatformDefaults', 'igniteCachePlatfo
 
         // Generate cache memory group.
         static cacheMemory(cache, ccfg = this.cacheConfigurationBean(cache)) {
+            ccfg.enumProperty('memoryMode');
+
+            if (ccfg.valueOf('memoryMode') !== 'OFFHEAP_VALUES')
+                ccfg.intProperty('offHeapMaxMemory');
+
             // this._evictionPolicy(ccfg, 'evictionPolicy', cache.evictionPolicy, cacheDflts.evictionPolicy);
 
+            ccfg.intProperty('startSize')
+                .boolProperty('swapEnabled', 'EnableSwap');
+
             return ccfg;
         }
 
         // Generate cache queries & Indexing group.
         static cacheQuery(cache, domains, ccfg = this.cacheConfigurationBean(cache)) {
-            ccfg.intProperty('longQueryWarningTimeout');
+            ccfg.intProperty('sqlOnheapRowCacheSize')
+                .intProperty('longQueryWarningTimeout');
 
             return ccfg;
         }
@@ -406,6 +414,7 @@ export default ['JavaTypes', 'igniteClusterPlatformDefaults', 'igniteCachePlatfo
         static cacheConcurrency(cache, ccfg = this.cacheConfigurationBean(cache)) {
             ccfg.intProperty('maxConcurrentAsyncOperations')
                 .intProperty('defaultLockTimeout')
+                .enumProperty('atomicWriteOrderMode')
                 .enumProperty('writeSynchronizationMode');
 
             return ccfg;

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/SpringTransformer.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/SpringTransformer.service.js b/modules/web-console/frontend/app/modules/configuration/generator/SpringTransformer.service.js
index b234575..41aea0a 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/SpringTransformer.service.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/SpringTransformer.service.js
@@ -183,24 +183,20 @@ export default class IgniteSpringTransformer extends AbstractTransformer {
                     sb.startBlock(`<property name="${prop.name}">`);
 
                     if (prop.eventTypes.length === 1) {
-                        const evtGrp = _.find(this.eventGroups, {value: _.head(prop.eventTypes)});
+                        const evtGrp = _.head(prop.eventTypes);
 
-                        evtGrp && sb.append(`<util:constant static-field="${evtGrp.class}.${evtGrp.value}"/>`);
+                        sb.append(`<util:constant static-field="${evtGrp.class}.${evtGrp.label}"/>`);
                     }
                     else {
                         sb.startBlock('<list>');
 
-                        _.forEach(prop.eventTypes, (item, ix) => {
+                        _.forEach(prop.eventTypes, (evtGrp, ix) => {
                             ix > 0 && sb.emptyLine();
 
-                            const evtGrp = _.find(this.eventGroups, {value: item});
+                            sb.append(`<!-- EventType.${evtGrp.label} -->`);
 
-                            if (evtGrp) {
-                                sb.append(`<!-- EventType.${item} -->`);
-
-                                _.forEach(evtGrp.events, (event) =>
-                                    sb.append(`<util:constant static-field="${evtGrp.class}.${event}"/>`));
-                            }
+                            _.forEach(evtGrp.events, (event) =>
+                                sb.append(`<util:constant static-field="${evtGrp.class}.${event}"/>`));
                         });
 
                         sb.endBlock('</list>');
@@ -320,10 +316,11 @@ export default class IgniteSpringTransformer extends AbstractTransformer {
         return sb;
     }
 
-    static cluster(cluster, client) {
-        const cfg = this.generator.igniteConfiguration(cluster, client);
+    static cluster(cluster, targetVer, client) {
+        const cfg = this.generator.igniteConfiguration(cluster, targetVer, client);
 
-        const clientNearCaches = client ? _.filter(cluster.caches, (cache) => _.get(cache, 'clientNearConfiguration.enabled')) : [];
+        const clientNearCaches = client ? _.filter(cluster.caches, (cache) =>
+            cache.mode === 'PARTITIONED' && _.get(cache, 'clientNearConfiguration.enabled')) : [];
 
         return this.igniteConfiguration(cfg, clientNearCaches);
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cache.platform.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cache.platform.service.js b/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cache.platform.service.js
index c9720cd..eeac3a0 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cache.platform.service.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cache.platform.service.js
@@ -28,6 +28,15 @@ const DFLT_CACHE = {
         clsName: 'Apache.Ignite.Core.Cache.Configuration.CacheAtomicityMode',
         mapper: enumValueMapper
     },
+    memoryMode: {
+        clsName: 'Apache.Ignite.Core.Cache.Configuration.CacheMemoryMode',
+        value: 'ONHEAP_TIERED',
+        mapper: enumValueMapper
+    },
+    atomicWriteOrderMode: {
+        clsName: 'org.apache.ignite.cache.CacheAtomicWriteOrderMode',
+        mapper: enumValueMapper
+    },
     writeSynchronizationMode: {
         clsName: 'org.apache.ignite.cache.CacheWriteSynchronizationMode',
         value: 'PRIMARY_SYNC',

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cache.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cache.service.js b/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cache.service.js
index 390233b..ad5b88a 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cache.service.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cache.service.js
@@ -19,14 +19,24 @@ const DFLT_CACHE = {
     cacheMode: {
         clsName: 'org.apache.ignite.cache.CacheMode'
     },
-    atomicityMode: {
-        clsName: 'org.apache.ignite.cache.CacheAtomicityMode'
-    },
     partitionLossPolicy: {
         clsName: 'org.apache.ignite.cache.PartitionLossPolicy',
         value: 'IGNORE'
     },
+    atomicityMode: {
+        clsName: 'org.apache.ignite.cache.CacheAtomicityMode'
+    },
+    memoryMode: {
+        clsName: 'org.apache.ignite.cache.CacheMemoryMode',
+        value: 'ONHEAP_TIERED'
+    },
+    onheapCacheEnabled: false,
+    offHeapMaxMemory: -1,
+    startSize: 1500000,
+    swapEnabled: false,
+    sqlOnheapRowCacheSize: 10240,
     longQueryWarningTimeout: 3000,
+    snapshotableIndex: false,
     sqlEscapeAll: false,
     storeKeepBinary: false,
     loadPreviousValue: false,
@@ -45,8 +55,12 @@ const DFLT_CACHE = {
     writeBehindFlushSize: 10240,
     writeBehindFlushFrequency: 5000,
     writeBehindFlushThreadCount: 1,
+    writeBehindCoalescing: true,
     maxConcurrentAsyncOperations: 500,
     defaultLockTimeout: 0,
+    atomicWriteOrderMode: {
+        clsName: 'org.apache.ignite.cache.CacheAtomicWriteOrderMode'
+    },
     writeSynchronizationMode: {
         clsName: 'org.apache.ignite.cache.CacheWriteSynchronizationMode',
         value: 'PRIMARY_SYNC'
@@ -115,7 +129,8 @@ const DFLT_CACHE = {
         databaseFieldType: {
             clsName: 'java.sql.Types'
         }
-    }
+    },
+    memoryPolicyName: 'default'
 };
 
 export default class IgniteCacheDefaults {

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cluster.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cluster.service.js b/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cluster.service.js
index 5ed90c5..2c86667 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cluster.service.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/defaults/Cluster.service.js
@@ -17,6 +17,8 @@
 
 const DFLT_CLUSTER = {
     localHost: '0.0.0.0',
+    activeOnStart: true,
+    cacheSanityCheckEnabled: true,
     discovery: {
         localPort: 47500,
         localPortRange: 100,
@@ -26,7 +28,9 @@ const DFLT_CLUSTER = {
         networkTimeout: 5000,
         joinTimeout: 0,
         threadPriority: 10,
-        metricsUpdateFrequency: 2000,
+        heartbeatFrequency: 2000,
+        maxMissedHeartbeats: 1,
+        maxMissedClientHeartbeats: 5,
         topHistorySize: 1000,
         reconnectCount: 10,
         statisticsPrintFrequency: 0,
@@ -168,6 +172,8 @@ const DFLT_CLUSTER = {
             maximumFailoverAttempts: 5
         }
     },
+    failureDetectionTimeout: 10000,
+    clientFailureDetectionTimeout: 30000,
     logger: {
         Log4j: {
             level: {
@@ -181,9 +187,12 @@ const DFLT_CLUSTER = {
         }
     },
     marshalLocalJobs: false,
+    marshallerCacheKeepAliveTime: 10000,
     metricsHistorySize: 10000,
     metricsLogFrequency: 60000,
     metricsUpdateFrequency: 2000,
+    clockSyncSamples: 8,
+    clockSyncFrequency: 120000,
     timeServerPortBase: 31100,
     timeServerPortRange: 100,
     transactionConfiguration: {
@@ -280,6 +289,41 @@ const DFLT_CLUSTER = {
             nodeWeight: 10,
             useWeights: false
         }
+    },
+    memoryConfiguration: {
+        systemCacheInitialSize: 41943040,
+        systemCacheMaxSize: 104857600,
+        pageSize: 2048,
+        defaultMemoryPolicyName: 'default',
+        memoryPolicies: {
+            name: 'default',
+            initialSize: 268435456,
+            pageEvictionMode: {
+                clsName: 'org.apache.ignite.configuration.DataPageEvictionMode',
+                value: 'DISABLED'
+            },
+            evictionThreshold: 0.9,
+            emptyPagesPoolSize: 100,
+            metricsEnabled: false
+        }
+    },
+    utilityCacheKeepAliveTime: 60000,
+    hadoopConfiguration: {
+        mapReducePlanner: {
+            Weighted: {
+                localMapperWeight: 100,
+                remoteMapperWeight: 100,
+                localReducerWeight: 100,
+                remoteReducerWeight: 100,
+                preferLocalReducerThresholdWeight: 200
+            }
+        },
+        finishedJobInfoTtl: 30000,
+        maxTaskQueueSize: 8192
+    },
+    serviceConfigurations: {
+        maxPerNodeCount: 0,
+        totalCount: 0
     }
 };
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/configuration/generator/defaults/IGFS.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/defaults/IGFS.service.js b/modules/web-console/frontend/app/modules/configuration/generator/defaults/IGFS.service.js
index 49699bc..ff72d50 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/defaults/IGFS.service.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/defaults/IGFS.service.js
@@ -35,14 +35,18 @@ const DFLT_IGFS = {
     fragmentizerConcurrentFiles: 0,
     fragmentizerThrottlingBlockLength: 16777216,
     fragmentizerThrottlingDelay: 200,
+    dualModeMaxPendingPutsSize: 0,
+    dualModePutExecutorServiceShutdown: false,
     blockSize: 65536,
-    bufferSize: 65536,
+    streamBufferSize: 65536,
+    maxSpaceSize: 0,
     maximumTaskRangeLength: 0,
     managementPort: 11400,
     perNodeBatchSize: 100,
     perNodeParallelBatchCount: 8,
     prefetchBlocks: 0,
     sequentialReadsBeforePrefetch: 0,
+    trashPurgeTimeout: 1000,
     colocateMetadata: true,
     relaxedConsistency: true,
     pathModes: {
@@ -50,7 +54,8 @@ const DFLT_IGFS = {
         keyField: 'path',
         valClsName: 'org.apache.ignite.igfs.IgfsMode',
         valField: 'mode'
-    }
+    },
+    updateFileLengthOnFlush: false
 };
 
 export default class IgniteIGFSDefaults {

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/sql/sql.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js
index cf9f917..c8fcf8f 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js
@@ -1348,7 +1348,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
         const _tryStartRefresh = function(paragraph) {
             _tryStopRefresh(paragraph);
 
-            if (paragraph.rate && paragraph.rate.installed && paragraph.queryArgs) {
+            if (_.get(paragraph, 'rate.installed') && paragraph.queryExecuted()) {
                 $scope.chartAcceptKeyColumn(paragraph, TIME_LINE);
 
                 _executeRefresh(paragraph);
@@ -1377,7 +1377,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             const cache = _.find($scope.caches, {name: paragraph.cacheName});
 
             if (cache)
-                return !!_.find(cache.nodes, (node) => Version.includes(node.version, ...ENFORCE_JOIN_VERS));
+                return !!_.find(cache.nodes, (node) => Version.since(node.version, ...ENFORCE_JOIN_VERS));
 
             return false;
         };
@@ -1663,7 +1663,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             paragraph.rate.unit = unit;
             paragraph.rate.installed = true;
 
-            if (paragraph.queryExecuted())
+            if (paragraph.queryExecuted() && !paragraph.scanExplain())
                 _tryStartRefresh(paragraph);
         };
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration.state.js b/modules/web-console/frontend/app/modules/states/configuration.state.js
index 624cf5f..03a312f 100644
--- a/modules/web-console/frontend/app/modules/states/configuration.state.js
+++ b/modules/web-console/frontend/app/modules/states/configuration.state.js
@@ -34,6 +34,11 @@ import igfsTpl from 'views/configuration/igfs.tpl.pug';
 import summaryTpl from 'views/configuration/summary.tpl.pug';
 import summaryTabsTemplateUrl from 'views/configuration/summary-tabs.pug';
 
+import clustersCtrl from 'Controllers/clusters-controller';
+import domainsCtrl from 'Controllers/domains-controller';
+import cachesCtrl from 'Controllers/caches-controller';
+import igfsCtrl from 'Controllers/igfs-controller';
+
 angular.module('ignite-console.states.configuration', ['ui.router'])
     .directive(...previewPanel)
     // Summary screen
@@ -62,7 +67,9 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
                 onEnter: AclRoute.checkAccess('configuration'),
                 metaTags: {
                     title: 'Configure Clusters'
-                }
+                },
+                controller: clustersCtrl,
+                controllerAs: '$ctrl'
             })
             .state('base.configuration.caches', {
                 url: '/caches',
@@ -70,7 +77,9 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
                 onEnter: AclRoute.checkAccess('configuration'),
                 metaTags: {
                     title: 'Configure Caches'
-                }
+                },
+                controller: cachesCtrl,
+                controllerAs: '$ctrl'
             })
             .state('base.configuration.domains', {
                 url: '/domains',
@@ -78,7 +87,9 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
                 onEnter: AclRoute.checkAccess('configuration'),
                 metaTags: {
                     title: 'Configure Domain Model'
-                }
+                },
+                controller: domainsCtrl,
+                controllerAs: '$ctrl'
             })
             .state('base.configuration.igfs', {
                 url: '/igfs',
@@ -86,7 +97,9 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
                 onEnter: AclRoute.checkAccess('configuration'),
                 metaTags: {
                     title: 'Configure IGFS'
-                }
+                },
+                controller: igfsCtrl,
+                controllerAs: '$ctrl'
             })
             .state('base.configuration.summary', {
                 url: '/summary',

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.pug b/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.pug
index 14857fc..cb333ac 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.pug
@@ -38,14 +38,8 @@ include /app/helpers/jade/mixins
     .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
         .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
             .col-sm-6
-                .settings-row
-                    +dropdown('Function:', `${affModel}.kind`, '"AffinityKind"', 'true', 'Default',
-                        '[\
-                            {value: "Rendezvous", label: "Rendezvous"},\
-                            {value: "Fair", label: "Fair"},\
-                            {value: "Custom", label: "Custom"},\
-                            {value: undefined, label: "Default"}\
-                        ]',
+                .settings-row(ng-if='$ctrl.available(["1.0.0", "2.0.0"])')
+                    +dropdown('Function:', `${affModel}.kind`, '"AffinityKind"', 'true', 'Default', 'affinityFunction',
                         'Key topology resolver to provide mapping from keys to nodes\
                         <ul>\
                             <li>Rendezvous - Based on Highest Random Weight algorithm<br/></li>\
@@ -53,6 +47,14 @@ include /app/helpers/jade/mixins
                             <li>Custom - Custom implementation of key affinity fynction<br/></li>\
                             <li>Default - By default rendezvous affinity function  with 1024 partitions is used<br/></li>\
                         </ul>')
+                .settings-row(ng-if='$ctrl.available("2.0.0")')
+                    +dropdown('Function:', `${affModel}.kind`, '"AffinityKind"', 'true', 'Default', 'affinityFunction',
+                        'Key topology resolver to provide mapping from keys to nodes\
+                        <ul>\
+                            <li>Rendezvous - Based on Highest Random Weight algorithm<br/></li>\
+                            <li>Custom - Custom implementation of key affinity fynction<br/></li>\
+                            <li>Default - By default rendezvous affinity function  with 1024 partitions is used<br/></li>\
+                        </ul>')
                 .panel-details(ng-if=rendezvousAff)
                     .details-row
                         +number-required('Partitions', `${affModel}.Rendezvous.partitions`, '"RendPartitions"', 'true', rendPartitionsRequired, '1024', '1', 'Number of partitions')
@@ -78,5 +80,10 @@ include /app/helpers/jade/mixins
                 .settings-row
                     +java-class('Mapper:', model + '.affinityMapper', '"AffMapCustomClassName"', 'true', 'false',
                         'Provide custom affinity key for any given key')
+
+                //- Since ignite 2.0
+                .settings-row(ng-if='$ctrl.available("2.0.0")')
+                    +java-class('Topology validator:', model + '.topologyValidator', '"topologyValidator"', 'true', 'false', 'Topology validator')
+
             .col-sm-6
                 +preview-xml-java(model, 'cacheAffinity')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/caches/concurrency.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/concurrency.pug b/modules/web-console/frontend/app/modules/states/configuration/caches/concurrency.pug
index 92bc8ab..b24bf47 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/concurrency.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/concurrency.pug
@@ -37,6 +37,20 @@ include /app/helpers/jade/mixins
                     +number('Default lock timeout:', `${model}.defaultLockTimeout`, '"defaultLockTimeout"', 'true', '0', '0',
                         'Default lock acquisition timeout in milliseconds<br/>\
                         If <b>0</b> then lock acquisition will never timeout')
+
+                //- Removed in ignite 2.0
+                .settings-row(ng-if='$ctrl.available(["1.0.0", "2.0.0"])' ng-hide=`${model}.atomicityMode === 'TRANSACTIONAL'`)
+                    +dropdown('Entry versioning:', `${model}.atomicWriteOrderMode`, '"atomicWriteOrderMode"', 'true', 'Choose versioning',
+                        '[\
+                            {value: "CLOCK", label: "CLOCK"},\
+                            {value: "PRIMARY", label: "PRIMARY"}\
+                        ]',
+                        'Write ordering mode determines which node assigns the write version, sender or the primary node\
+                        <ul>\
+                            <li>CLOCK - in this mode write versions are assigned on a sender node which generally leads to better performance</li>\
+                            <li>PRIMARY - in this mode version is assigned only on primary node. This means that sender will only send write request to primary node, which in turn will assign write version and forward it to backups</li>\
+                        </ul>')
+
                 .settings-row
                     +dropdown('Write synchronization mode:', `${model}.writeSynchronizationMode`, '"writeSynchronizationMode"', 'true', 'PRIMARY_SYNC',
                         '[\

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/caches/general.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/general.pug b/modules/web-console/frontend/app/modules/states/configuration/caches/general.pug
index 2be5c53..8eda4a1 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/general.pug
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/general.pug
@@ -40,6 +40,26 @@ include /app/helpers/jade/mixins
                         'Select domain models to describe types in cache')
                 .settings-row
                     +cacheMode('Mode:', `${model}.cacheMode`, '"cacheMode"', 'PARTITIONED')
+
+                //- Since ignite 2.0
+                .settings-row(ng-if='$ctrl.available("2.0.0")')
+                    +dropdown('Partition loss policy:', model + '.partitionLossPolicy', '"partitionLossPolicy"', 'true', 'IGNORE',
+                        '[\
+                            {value: "READ_ONLY_SAFE", label: "READ_ONLY_SAFE"},\
+                            {value: "READ_ONLY_ALL", label: "READ_ONLY_ALL"},\
+                            {value: "READ_WRITE_SAFE", label: "READ_WRITE_SAFE"},\
+                            {value: "READ_WRITE_ALL", label: "READ_WRITE_ALL"},\
+                            {value: "IGNORE", label: "IGNORE"}\
+                        ]',
+                        'Defines how cache will behave in a case when one or more partitions are lost:\
+                        <ul>\
+                            <li>READ_ONLY_SAFE - all writes to the cache will be failed with an exception, reads will only be allowed for keys in non-lost partitions</li>\
+                            <li>READ_ONLY_ALL - all writes to the cache will be failed with an exception, all reads will proceed as if all partitions were in a consistent state</li>\
+                            <li>READ_WRITE_SAFE - all reads and writes will be allowed for keys in valid partitions</li>\
+                            <li>READ_WRITE_ALL - all reads and writes will proceed as if all partitions were in a consistent state</li>\
+                            <li>IGNORE - if partition is lost, reset its state and do not clear intermediate data</li>\
+                        </ul>')
+
                 .settings-row
                     +dropdown('Atomicity:', `${model}.atomicityMode`, '"atomicityMode"', 'true', 'ATOMIC',
                         '[\
@@ -57,31 +77,32 @@ include /app/helpers/jade/mixins
                     +checkbox('Read from backup', `${model}.readFromBackup`, '"readFromBackup"',
                         'Flag indicating whether data can be read from backup<br/>\
                         If not set then always get data from primary node (never from backup)')
-                .settings-row
-                    +dropdown('Partition loss policy:', `${model}.partitionLossPolicy`, '"partitionLossPolicy"', 'true', 'IGNORE',
-                    '[\
-                        {value: "READ_ONLY_SAFE", label: "READ_ONLY_SAFE"},\
-                        {value: "READ_ONLY_ALL", label: "READ_ONLY_ALL"},\
-                        {value: "READ_WRITE_SAFE", label: "READ_WRITE_SAFE"},\
-                        {value: "READ_WRITE_ALL", label: "READ_WRITE_ALL"},\
-                        {value: "IGNORE", label: "IGNORE"}\
-                    ]',
-                    'Partition loss policies:\
-                    <ul>\
-                        <li>READ_ONLY_SAFE - in this mode all writes to the cache will be failed with an exception,\
-                            reads will only be allowed for keys in  non-lost partitions.\
-                            Reads from lost partitions will be failed with an exception.</li>\
-                        <li>READ_ONLY_ALL - in this mode фll writes to the cache will be failed with an exception.\
-                            All reads will proceed as if all partitions were in a consistent state.\
-                            The result of reading from a lost partition is undefined and may be different on different nodes in the cluster.</li>\
-                        <li>READ_WRITE_SAFE - in this mode Aall reads and writes will be allowed for keys in valid partitions.\
-                            All reads and writes for keys in lost partitions will be failed with an exception.</li>\
-                        <li>READ_WRITE_ALL - in this mode all reads and writes will proceed as if all partitions were in a consistent state.\
-                            The result of reading from a lost partition is undefined and may be different on different nodes in the cluster.</li>\
-                        <li>IGNORE - in this mode if partition is lost, reset it state and do not clear intermediate data.\
-                            The result of reading from a previously lost and not cleared partition is undefined and may be different\
-                            on different nodes in the cluster.</li>\
-                    </ul>')
+                //- Since ignite 2.0
+                    .settings-row(ng-if='$ctrl.available("2.0.0")')
+                        +dropdown('Partition loss policy:', `${model}.partitionLossPolicy`, '"partitionLossPolicy"', 'true', 'IGNORE',
+                        '[\
+                            {value: "READ_ONLY_SAFE", label: "READ_ONLY_SAFE"},\
+                            {value: "READ_ONLY_ALL", label: "READ_ONLY_ALL"},\
+                            {value: "READ_WRITE_SAFE", label: "READ_WRITE_SAFE"},\
+                            {value: "READ_WRITE_ALL", label: "READ_WRITE_ALL"},\
+                            {value: "IGNORE", label: "IGNORE"}\
+                        ]',
+                        'Partition loss policies:\
+                        <ul>\
+                            <li>READ_ONLY_SAFE - in this mode all writes to the cache will be failed with an exception,\
+                                reads will only be allowed for keys in  non-lost partitions.\
+                                Reads from lost partitions will be failed with an exception.</li>\
+                            <li>READ_ONLY_ALL - in this mode фll writes to the cache will be failed with an exception.\
+                                All reads will proceed as if all partitions were in a consistent state.\
+                                The result of reading from a lost partition is undefined and may be different on different nodes in the cluster.</li>\
+                            <li>READ_WRITE_SAFE - in this mode Aall reads and writes will be allowed for keys in valid partitions.\
+                                All reads and writes for keys in lost partitions will be failed with an exception.</li>\
+                            <li>READ_WRITE_ALL - in this mode all reads and writes will proceed as if all partitions were in a consistent state.\
+                                The result of reading from a lost partition is undefined and may be different on different nodes in the cluster.</li>\
+                            <li>IGNORE - in this mode if partition is lost, reset it state and do not clear intermediate data.\
+                                The result of reading from a previously lost and not cleared partition is undefined and may be different\
+                                on different nodes in the cluster.</li>\
+                        </ul>')
                 .settings-row
                     +checkbox('Copy on read', `${model}.copyOnRead`, '"copyOnRead"',
                         'Flag indicating whether copy of the value stored in cache should be created for cache operation implying return value<br/>\


[48/50] [abbrv] ignite git commit: IgniteCacheNoClassQuerySelfTest: stop node if test fails.

Posted by sb...@apache.org.
IgniteCacheNoClassQuerySelfTest: stop node if test fails.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/eaf8e14a
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/eaf8e14a
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/eaf8e14a

Branch: refs/heads/ignite-5075
Commit: eaf8e14ad44d69471fd6c1561b14a2ec849b4252
Parents: 986c07a
Author: sboikov <sb...@gridgain.com>
Authored: Tue Jun 6 10:38:58 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Jun 6 10:38:58 2017 +0300

----------------------------------------------------------------------
 .../processors/cache/IgniteCacheNoClassQuerySelfTest.java       | 5 +++++
 1 file changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/eaf8e14a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheNoClassQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheNoClassQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheNoClassQuerySelfTest.java
index e0148b3..b03e948 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheNoClassQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheNoClassQuerySelfTest.java
@@ -114,9 +114,14 @@ public class IgniteCacheNoClassQuerySelfTest extends GridCommonAbstractTest {
     public void testNoClass() throws Exception {
         try {
             startGrid();
+
+            fail();
         }
         catch (Exception e) {
             assertTrue(e.getMessage().contains("default marshaller"));
         }
+        finally {
+            stopAllGrids();
+        }
     }
 }


[45/50] [abbrv] ignite git commit: IGNITE-5408: Added enabled service loading for JDBC drivers. This closes #2087.

Posted by sb...@apache.org.
IGNITE-5408: Added enabled service loading for JDBC drivers. This closes #2087.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f0605829
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f0605829
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f0605829

Branch: refs/heads/ignite-5075
Commit: f0605829e3846ac9afff0fcf0352cb3878fea58b
Parents: de658ca
Author: devozerov <pp...@gmail.com>
Authored: Mon Jun 5 22:17:40 2017 +0300
Committer: devozerov <pp...@gmail.com>
Committed: Mon Jun 5 22:17:40 2017 +0300

----------------------------------------------------------------------
 .../jdbc2/JdbcAbstractDmlStatementSelfTest.java     |  2 --
 .../internal/jdbc2/JdbcComplexQuerySelfTest.java    |  2 --
 .../internal/jdbc2/JdbcConnectionSelfTest.java      |  2 --
 .../jdbc2/JdbcDistributedJoinsQueryTest.java        |  2 --
 .../internal/jdbc2/JdbcEmptyCacheSelfTest.java      |  2 --
 .../internal/jdbc2/JdbcLocalCachesSelfTest.java     |  2 --
 .../ignite/internal/jdbc2/JdbcMetadataSelfTest.java |  2 --
 .../internal/jdbc2/JdbcNoDefaultCacheTest.java      |  2 --
 .../jdbc2/JdbcPreparedStatementSelfTest.java        |  2 --
 .../internal/jdbc2/JdbcResultSetSelfTest.java       |  2 --
 .../ignite/internal/jdbc2/JdbcSpringSelfTest.java   |  2 --
 .../internal/jdbc2/JdbcStatementSelfTest.java       |  2 --
 .../internal/jdbc2/JdbcStreamingSelfTest.java       |  2 --
 .../ignite/jdbc/AbstractJdbcPojoQuerySelfTest.java  |  2 --
 .../ignite/jdbc/JdbcComplexQuerySelfTest.java       |  2 --
 .../apache/ignite/jdbc/JdbcConnectionSelfTest.java  |  2 --
 .../apache/ignite/jdbc/JdbcEmptyCacheSelfTest.java  |  2 --
 .../apache/ignite/jdbc/JdbcLocalCachesSelfTest.java |  2 --
 .../apache/ignite/jdbc/JdbcMetadataSelfTest.java    |  2 --
 .../apache/ignite/jdbc/JdbcNoDefaultCacheTest.java  |  2 --
 .../ignite/jdbc/JdbcPreparedStatementSelfTest.java  |  2 --
 .../apache/ignite/jdbc/JdbcResultSetSelfTest.java   |  2 --
 .../apache/ignite/jdbc/JdbcStatementSelfTest.java   |  2 --
 .../thin/JdbcThinAbstractDmlStatementSelfTest.java  |  2 --
 .../ignite/jdbc/thin/JdbcThinAbstractSelfTest.java  |  5 +----
 .../jdbc/thin/JdbcThinNoDefaultSchemaTest.java      |  2 --
 .../src/main/java/META-INF/services/java.sql.Driver |  2 ++
 .../java/org/apache/ignite/IgniteJdbcDriver.java    |  9 +++------
 .../org/apache/ignite/IgniteJdbcThinDriver.java     | 16 +++++++++++++---
 ...SqlConnectorConfigurationValidationSelfTest.java |  5 -----
 30 files changed, 19 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractDmlStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractDmlStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractDmlStatementSelfTest.java
index 82f9cd2..e055ee3 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractDmlStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractDmlStatementSelfTest.java
@@ -60,8 +60,6 @@ public abstract class JdbcAbstractDmlStatementSelfTest extends GridCommonAbstrac
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         startGridsMultiThreaded(3);
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcComplexQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcComplexQuerySelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcComplexQuerySelfTest.java
index 725ec3a..1163723 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcComplexQuerySelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcComplexQuerySelfTest.java
@@ -108,8 +108,6 @@ public class JdbcComplexQuerySelfTest extends GridCommonAbstractTest {
         personCache.put(new AffinityKey<>("p1", "o1"), new Person(1, "John White", 25, 1));
         personCache.put(new AffinityKey<>("p2", "o1"), new Person(2, "Joe Black", 35, 1));
         personCache.put(new AffinityKey<>("p3", "o2"), new Person(3, "Mike Green", 40, 2));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcConnectionSelfTest.java
index 39a3648..bd5c8e9 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcConnectionSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcConnectionSelfTest.java
@@ -96,8 +96,6 @@ public class JdbcConnectionSelfTest extends GridCommonAbstractTest {
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         startGridsMultiThreaded(GRID_CNT);
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java
index 6756a97..63f5a5c 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java
@@ -93,8 +93,6 @@ public class JdbcDistributedJoinsQueryTest extends GridCommonAbstractTest {
         personCache.put("p1", new Person(1, "John White", 25, 1));
         personCache.put("p2", new Person(2, "Joe Black", 35, 1));
         personCache.put("p3", new Person(3, "Mike Green", 40, 2));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcEmptyCacheSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcEmptyCacheSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcEmptyCacheSelfTest.java
index 6d5181b..615658a 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcEmptyCacheSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcEmptyCacheSelfTest.java
@@ -76,8 +76,6 @@ public class JdbcEmptyCacheSelfTest extends GridCommonAbstractTest {
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         startGrid();
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcLocalCachesSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcLocalCachesSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcLocalCachesSelfTest.java
index 645f7b1..f096e69 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcLocalCachesSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcLocalCachesSelfTest.java
@@ -93,8 +93,6 @@ public class JdbcLocalCachesSelfTest extends GridCommonAbstractTest {
 
         cache2.put("key1", 3);
         cache2.put("key2", 4);
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
index 736e343..52e68c9 100755
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
@@ -109,8 +109,6 @@ public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
         personCache.put(new AffinityKey<>("p1", "o1"), new Person("John White", 25, 1));
         personCache.put(new AffinityKey<>("p2", "o1"), new Person("Joe Black", 35, 1));
         personCache.put(new AffinityKey<>("p3", "o2"), new Person("Mike Green", 40, 2));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcNoDefaultCacheTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcNoDefaultCacheTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcNoDefaultCacheTest.java
index 545286c..e851319 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcNoDefaultCacheTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcNoDefaultCacheTest.java
@@ -88,8 +88,6 @@ public class JdbcNoDefaultCacheTest extends GridCommonAbstractTest {
     @Override protected void beforeTestsStarted() throws Exception {
         startGridsMultiThreaded(GRID_CNT);
 
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
-
         Ignite ignite = ignite(0);
 
         IgniteCache<Integer, Integer> cache1 = ignite.cache(CACHE1_NAME);

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatementSelfTest.java
index 30bd018..e2939e6 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcPreparedStatementSelfTest.java
@@ -126,8 +126,6 @@ public class JdbcPreparedStatementSelfTest extends GridCommonAbstractTest {
 
         cache.put(1, o);
         cache.put(2, new TestObject(2));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
index 54514c7..42134e7 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
@@ -111,8 +111,6 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
         cache.put(1, o);
         cache.put(2, new TestObject(2));
         cache.put(3, new TestObject(3));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcSpringSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcSpringSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcSpringSelfTest.java
index fb03ae8..7a29b13 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcSpringSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcSpringSelfTest.java
@@ -58,8 +58,6 @@ public class JdbcSpringSelfTest extends JdbcConnectionSelfTest {
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         startGridsWithSpringCtx(GRID_CNT, false, configURL());
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcStatementSelfTest.java
index 99e813d..138eef5 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcStatementSelfTest.java
@@ -93,8 +93,6 @@ public class JdbcStatementSelfTest extends GridCommonAbstractTest {
         cache.put("p1", new Person(1, "John", "White", 25));
         cache.put("p2", new Person(2, "Joe", "Black", 35));
         cache.put("p3", new Person(3, "Mike", "Green", 40));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcStreamingSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcStreamingSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcStreamingSelfTest.java
index 5c98b1a..5418ca0 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcStreamingSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcStreamingSelfTest.java
@@ -91,8 +91,6 @@ public class JdbcStreamingSelfTest extends GridCommonAbstractTest {
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         startGrids(2);
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/AbstractJdbcPojoQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/AbstractJdbcPojoQuerySelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/AbstractJdbcPojoQuerySelfTest.java
index 6492eb0..892812f 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/AbstractJdbcPojoQuerySelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/AbstractJdbcPojoQuerySelfTest.java
@@ -111,8 +111,6 @@ public abstract class AbstractJdbcPojoQuerySelfTest extends GridCommonAbstractTe
         IgniteCache<String, BinaryObject> cache = grid(0).cache(DEFAULT_CACHE_NAME);
 
         cache.put("0", binObj);
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcComplexQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcComplexQuerySelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcComplexQuerySelfTest.java
index dd035b2..99bc361 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcComplexQuerySelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcComplexQuerySelfTest.java
@@ -103,8 +103,6 @@ public class JdbcComplexQuerySelfTest extends GridCommonAbstractTest {
         personCache.put(new AffinityKey<>("p1", "o1"), new Person(1, "John White", 25, 1));
         personCache.put(new AffinityKey<>("p2", "o1"), new Person(2, "Joe Black", 35, 1));
         personCache.put(new AffinityKey<>("p3", "o2"), new Person(3, "Mike Green", 40, 2));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcConnectionSelfTest.java
index a2a83ee..466bf5d 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcConnectionSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcConnectionSelfTest.java
@@ -91,8 +91,6 @@ public class JdbcConnectionSelfTest extends GridCommonAbstractTest {
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         startGridsMultiThreaded(2);
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcEmptyCacheSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcEmptyCacheSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcEmptyCacheSelfTest.java
index 42e307f..c883aa0 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcEmptyCacheSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcEmptyCacheSelfTest.java
@@ -77,8 +77,6 @@ public class JdbcEmptyCacheSelfTest extends GridCommonAbstractTest {
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         startGrid();
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcLocalCachesSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcLocalCachesSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcLocalCachesSelfTest.java
index d959f3f..ad65434 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcLocalCachesSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcLocalCachesSelfTest.java
@@ -90,8 +90,6 @@ public class JdbcLocalCachesSelfTest extends GridCommonAbstractTest {
 
         cache2.put("key1", 3);
         cache2.put("key2", 4);
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcMetadataSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcMetadataSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcMetadataSelfTest.java
index be148c4..2d1443b 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcMetadataSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcMetadataSelfTest.java
@@ -103,8 +103,6 @@ public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
         personCache.put(new AffinityKey<>("p1", "o1"), new Person("John White", 25, 1));
         personCache.put(new AffinityKey<>("p2", "o1"), new Person("Joe Black", 35, 1));
         personCache.put(new AffinityKey<>("p3", "o2"), new Person("Mike Green", 40, 2));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcNoDefaultCacheTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcNoDefaultCacheTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcNoDefaultCacheTest.java
index 2d27637..d3d8454 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcNoDefaultCacheTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcNoDefaultCacheTest.java
@@ -89,8 +89,6 @@ public class JdbcNoDefaultCacheTest extends GridCommonAbstractTest {
     @Override protected void beforeTestsStarted() throws Exception {
         startGridsMultiThreaded(GRID_CNT);
 
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
-
         Ignite ignite = ignite(0);
 
         IgniteCache<Integer, Integer> cache1 = ignite.cache(CACHE1_NAME);

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcPreparedStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcPreparedStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcPreparedStatementSelfTest.java
index 67ccdb1..0dfa0fd 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcPreparedStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcPreparedStatementSelfTest.java
@@ -123,8 +123,6 @@ public class JdbcPreparedStatementSelfTest extends GridCommonAbstractTest {
 
         cache.put(1, o);
         cache.put(2, new TestObject(2));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcResultSetSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcResultSetSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcResultSetSelfTest.java
index 2dac8b7..b407f3e 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcResultSetSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcResultSetSelfTest.java
@@ -106,8 +106,6 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
 
         cache.put(1, o);
         cache.put(2, new TestObject(2));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcStatementSelfTest.java
index 360d118..be685cc 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcStatementSelfTest.java
@@ -92,8 +92,6 @@ public class JdbcStatementSelfTest extends GridCommonAbstractTest {
         cache.put("p1", new Person(1, "John", "White", 25));
         cache.put("p2", new Person(2, "Joe", "Black", 35));
         cache.put("p3", new Person(3, "Mike", "Green", 40));
-
-        Class.forName("org.apache.ignite.IgniteJdbcDriver");
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
index b5760dd..607f557 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
@@ -55,8 +55,6 @@ public abstract class JdbcThinAbstractDmlStatementSelfTest extends JdbcThinAbstr
     @Override protected void beforeTestsStarted() throws Exception {
         super.beforeTestsStarted();
 
-        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
-
         startGridsMultiThreaded(3);
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
index 99b79ea..6655ed8 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
@@ -23,8 +23,5 @@ import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
  * Connection test.
  */
 public class JdbcThinAbstractSelfTest extends GridCommonAbstractTest {
-    /** {@inheritDoc} */
-    @Override protected void beforeTestsStarted() throws Exception {
-        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
-    }
+    // No-op.
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
index cea176e..ff49742 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
@@ -86,8 +86,6 @@ public class JdbcThinNoDefaultSchemaTest extends JdbcThinAbstractSelfTest {
 
         startGridsMultiThreaded(GRID_CNT);
 
-        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
-
         Ignite ignite = ignite(0);
 
         IgniteCache<Integer, Integer> cache1 = ignite.cache(CACHE1_NAME);

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/core/src/main/java/META-INF/services/java.sql.Driver
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/META-INF/services/java.sql.Driver b/modules/core/src/main/java/META-INF/services/java.sql.Driver
new file mode 100644
index 0000000..c2f62e9
--- /dev/null
+++ b/modules/core/src/main/java/META-INF/services/java.sql.Driver
@@ -0,0 +1,2 @@
+org.apache.ignite.IgniteJdbcDriver
+org.apache.ignite.IgniteJdbcThinDriver
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
index 345bbc3..47fe982 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
@@ -243,10 +243,7 @@ import org.apache.ignite.logger.java.JavaLogger;
  * </table>
  * <h1 class="header">Example</h1>
  * <pre name="code" class="java">
- * // Register JDBC driver.
- * Class.forName("org.apache.ignite.IgniteJdbcDriver");
- *
- * // Open JDBC connection.
+  * // Open JDBC connection.
  * Connection conn = DriverManager.getConnection("jdbc:ignite:cfg//cache=persons@file:///etc/configs/ignite-jdbc.xml");
  *
  * // Query persons' names
@@ -371,8 +368,8 @@ public class IgniteJdbcDriver implements Driver {
     /** Logger. */
     private static final IgniteLogger LOG = new JavaLogger();
 
-    /**
-     * Register driver.
+    /*
+     * Static initializer.
      */
     static {
         try {

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
index 3e3511b..7766d98 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
@@ -26,6 +26,7 @@ import java.sql.SQLFeatureNotSupportedException;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Properties;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.apache.ignite.cache.affinity.AffinityKey;
 import org.apache.ignite.internal.IgniteVersionUtils;
@@ -101,9 +102,6 @@ import org.apache.ignite.internal.util.typedef.F;
  * </table>
  * <h1 class="header">Example</h1>
  * <pre name="code" class="java">
- * // Register JDBC driver.
- * Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
- *
  * // Open JDBC connection.
  * Connection conn = DriverManager.getConnection("jdbc:ignite:thin//localhost:10800");
  *
@@ -133,6 +131,18 @@ import org.apache.ignite.internal.util.typedef.F;
  */
 @SuppressWarnings("JavadocReference")
 public class IgniteJdbcThinDriver implements Driver {
+    /*
+     * Static initializer.
+     */
+    static {
+        try {
+            DriverManager.registerDriver(new IgniteJdbcThinDriver());
+        }
+        catch (SQLException e) {
+            throw new RuntimeException("Failed to register " + IgniteJdbcThinDriver.class.getName(), e);
+        }
+    }
+
     /** Major version. */
     private static final int MAJOR_VER = IgniteVersionUtils.VER.major();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0605829/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java
index dedc5fd..da46b70 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java
@@ -48,11 +48,6 @@ public class SqlConnectorConfigurationValidationSelfTest extends GridCommonAbstr
     private static final String CACHE_NAME = "CACHE";
 
     /** {@inheritDoc} */
-    @Override protected void beforeTestsStarted() throws Exception {
-        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
-    }
-
-    /** {@inheritDoc} */
     @Override protected void afterTest() throws Exception {
         stopAllGrids();
     }


[49/50] [abbrv] ignite git commit: Merge remote-tracking branch 'remotes/origin/master' into ignite-5075

Posted by sb...@apache.org.
Merge remote-tracking branch 'remotes/origin/master' into ignite-5075


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/d1a8d5c4
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/d1a8d5c4
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/d1a8d5c4

Branch: refs/heads/ignite-5075
Commit: d1a8d5c493c0ef85dbe58fb0c7de6ebcba910dd3
Parents: 54b6935 eaf8e14
Author: sboikov <sb...@gridgain.com>
Authored: Tue Jun 6 11:55:28 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Jun 6 11:55:28 2017 +0300

----------------------------------------------------------------------
 assembly/libs/README.txt                        |    1 +
 .../jdbc2/JdbcAbstractDmlStatementSelfTest.java |    2 -
 .../jdbc2/JdbcComplexQuerySelfTest.java         |    2 -
 .../internal/jdbc2/JdbcConnectionSelfTest.java  |    2 -
 .../jdbc2/JdbcDistributedJoinsQueryTest.java    |    2 -
 .../jdbc2/JdbcDynamicIndexAbstractSelfTest.java |    2 +
 .../internal/jdbc2/JdbcEmptyCacheSelfTest.java  |    2 -
 .../internal/jdbc2/JdbcLocalCachesSelfTest.java |    2 -
 .../internal/jdbc2/JdbcMetadataSelfTest.java    |    2 -
 .../internal/jdbc2/JdbcNoDefaultCacheTest.java  |    2 -
 .../jdbc2/JdbcPreparedStatementSelfTest.java    |    2 -
 .../internal/jdbc2/JdbcResultSetSelfTest.java   |    2 -
 .../internal/jdbc2/JdbcSpringSelfTest.java      |    2 -
 .../internal/jdbc2/JdbcStatementSelfTest.java   |    2 -
 .../internal/jdbc2/JdbcStreamingSelfTest.java   |    2 -
 .../jdbc/AbstractJdbcPojoQuerySelfTest.java     |    2 -
 .../ignite/jdbc/JdbcComplexQuerySelfTest.java   |    2 -
 .../ignite/jdbc/JdbcConnectionSelfTest.java     |    2 -
 .../ignite/jdbc/JdbcEmptyCacheSelfTest.java     |    2 -
 .../ignite/jdbc/JdbcLocalCachesSelfTest.java    |    2 -
 .../ignite/jdbc/JdbcMetadataSelfTest.java       |    2 -
 .../ignite/jdbc/JdbcNoDefaultCacheTest.java     |    2 -
 .../jdbc/JdbcPreparedStatementSelfTest.java     |    2 -
 .../ignite/jdbc/JdbcResultSetSelfTest.java      |    2 -
 .../ignite/jdbc/JdbcStatementSelfTest.java      |    2 -
 .../jdbc/suite/IgniteJdbcDriverTestSuite.java   |   40 +-
 .../jdbc/thin/JdbcConnectionSelfTest.java       |  195 --
 .../JdbcThinAbstractDmlStatementSelfTest.java   |  246 +++
 .../jdbc/thin/JdbcThinAbstractSelfTest.java     |   27 +
 ...JdbcThinAbstractUpdateStatementSelfTest.java |   40 +
 .../jdbc/thin/JdbcThinComplexQuerySelfTest.java |  330 ++++
 .../jdbc/thin/JdbcThinConnectionSelfTest.java   |  295 +++
 .../thin/JdbcThinDeleteStatementSelfTest.java   |   49 +
 .../JdbcThinDynamicIndexAbstractSelfTest.java   |  328 ++++
 ...namicIndexAtomicPartitionedNearSelfTest.java |   26 +
 ...inDynamicIndexAtomicPartitionedSelfTest.java |   39 +
 ...hinDynamicIndexAtomicReplicatedSelfTest.java |   39 +
 ...dexTransactionalPartitionedNearSelfTest.java |   26 +
 ...icIndexTransactionalPartitionedSelfTest.java |   39 +
 ...micIndexTransactionalReplicatedSelfTest.java |   39 +
 .../jdbc/thin/JdbcThinEmptyCacheSelfTest.java   |  143 ++
 .../thin/JdbcThinInsertStatementSelfTest.java   |  185 ++
 .../thin/JdbcThinMergeStatementSelfTest.java    |  130 ++
 .../jdbc/thin/JdbcThinMetadataSelfTest.java     |  357 ++++
 .../jdbc/thin/JdbcThinNoDefaultSchemaTest.java  |  158 ++
 .../thin/JdbcThinPreparedStatementSelfTest.java |  768 ++++++++
 .../jdbc/thin/JdbcThinResultSetSelfTest.java    |  762 ++++++++
 .../jdbc/thin/JdbcThinStatementSelfTest.java    |  340 ++++
 .../thin/JdbcThinUpdateStatementSelfTest.java   |   50 +
 .../main/java/META-INF/services/java.sql.Driver |    2 +
 .../org/apache/ignite/IgniteJdbcDriver.java     |   12 +-
 .../org/apache/ignite/IgniteJdbcThinDriver.java |  155 +-
 .../ignite/cache/query/SqlFieldsQuery.java      |   12 +-
 .../cache/store/jdbc/CacheJdbcBlobStore.java    |    5 +-
 .../configuration/IgniteConfiguration.java      |   30 +
 .../ignite/configuration/OdbcConfiguration.java |    4 +
 .../SqlConnectorConfiguration.java              |  275 +++
 .../ignite/internal/binary/BinaryFieldImpl.java |   10 +-
 .../internal/binary/BinaryObjectImpl.java       |   10 +-
 .../binary/BinaryObjectOffheapImpl.java         |   10 +-
 .../ignite/internal/binary/BinaryTypeProxy.java |    3 +
 .../stream/v2/DirectByteBufferStreamImplV2.java |    1 +
 .../internal/jdbc/thin/JdbcConnection.java      |  529 ------
 .../ignite/internal/jdbc/thin/JdbcTcpIo.java    |  207 ---
 .../internal/jdbc/thin/JdbcThinConnection.java  |  661 +++++++
 .../jdbc/thin/JdbcThinPreparedStatement.java    |  485 +++++
 .../internal/jdbc/thin/JdbcThinResultSet.java   | 1704 ++++++++++++++++++
 .../jdbc/thin/JdbcThinResultSetMetadata.java    |  161 ++
 .../internal/jdbc/thin/JdbcThinStatement.java   |  495 +++++
 .../internal/jdbc/thin/JdbcThinTcpIo.java       |  404 +++++
 .../internal/jdbc/thin/JdbcThinUtils.java       |  221 +++
 .../checkpoint/GridCheckpointManager.java       |   45 +-
 .../checkpoint/GridCheckpointRequest.java       |    2 +
 .../processors/cache/ClusterCachesInfo.java     |   11 +
 .../processors/cache/GridCacheAdapter.java      |   51 +-
 .../cache/GridCacheDeploymentManager.java       |   12 +-
 .../processors/cache/GridCacheUtils.java        |    3 +
 .../processors/cache/IgniteCacheFutureImpl.java |    8 +-
 .../distributed/dht/GridDhtCacheAdapter.java    |    6 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java |    9 +-
 ...arOptimisticSerializableTxPrepareFuture.java |    6 +-
 .../query/GridCacheQueryFutureAdapter.java      |   18 +-
 .../cache/query/GridCacheSqlQuery.java          |   23 +
 .../store/GridCacheStoreManagerAdapter.java     |    4 +-
 .../cache/store/GridCacheWriteBehindStore.java  |   13 +-
 .../cache/transactions/TxDeadlock.java          |   11 +-
 .../odbc/OdbcQueryGetColumnsMetaRequest.java    |   74 -
 .../odbc/OdbcQueryGetColumnsMetaResult.java     |   42 -
 .../odbc/OdbcQueryGetParamsMetaRequest.java     |   60 -
 .../odbc/OdbcQueryGetParamsMetaResult.java      |   40 -
 .../odbc/OdbcQueryGetTablesMetaRequest.java     |   85 -
 .../odbc/OdbcQueryGetTablesMetaResult.java      |   42 -
 .../internal/processors/odbc/OdbcTableMeta.java |   88 -
 .../internal/processors/odbc/OdbcTypes.java     |  131 --
 .../internal/processors/odbc/OdbcUtils.java     |  141 --
 .../odbc/SqlListenerAbstractMessageParser.java  |  265 ---
 .../odbc/SqlListenerAbstractObjectReader.java   |  137 --
 .../odbc/SqlListenerAbstractObjectWriter.java   |  111 --
 .../processors/odbc/SqlListenerColumnMeta.java  |  110 --
 .../processors/odbc/SqlListenerDataTypes.java   |   30 +-
 .../processors/odbc/SqlListenerNioListener.java |   47 +-
 .../processors/odbc/SqlListenerProcessor.java   |  188 +-
 .../odbc/SqlListenerQueryCloseRequest.java      |   49 -
 .../odbc/SqlListenerQueryCloseResult.java       |   40 -
 .../odbc/SqlListenerQueryExecuteRequest.java    |   78 -
 .../odbc/SqlListenerQueryExecuteResult.java     |   54 -
 .../odbc/SqlListenerQueryFetchRequest.java      |   61 -
 .../odbc/SqlListenerQueryFetchResult.java       |   66 -
 .../processors/odbc/SqlListenerRequest.java     |   37 +-
 .../odbc/SqlListenerRequestHandler.java         |    8 +
 .../odbc/SqlListenerRequestHandlerImpl.java     |  494 -----
 .../processors/odbc/SqlListenerResponse.java    |   42 +-
 .../processors/odbc/SqlListenerUtils.java       |  250 +++
 .../processors/odbc/jdbc/JdbcColumnMeta.java    |  129 ++
 .../processors/odbc/jdbc/JdbcMessageParser.java |   53 +-
 .../processors/odbc/jdbc/JdbcObjectReader.java  |   33 -
 .../processors/odbc/jdbc/JdbcObjectWriter.java  |   33 -
 .../odbc/jdbc/JdbcQueryCloseRequest.java        |   72 +
 .../processors/odbc/jdbc/JdbcQueryCursor.java   |  132 ++
 .../odbc/jdbc/JdbcQueryExecuteRequest.java      |  147 ++
 .../odbc/jdbc/JdbcQueryExecuteResult.java       |  150 ++
 .../odbc/jdbc/JdbcQueryFetchRequest.java        |   87 +
 .../odbc/jdbc/JdbcQueryFetchResult.java         |   84 +
 .../odbc/jdbc/JdbcQueryMetadataRequest.java     |   73 +
 .../odbc/jdbc/JdbcQueryMetadataResult.java      |   93 +
 .../odbc/jdbc/JdbcRawBinarylizable.java         |   44 +
 .../processors/odbc/jdbc/JdbcRequest.java       |  108 ++
 .../odbc/jdbc/JdbcRequestHandler.java           |  295 +++
 .../processors/odbc/jdbc/JdbcResponse.java      |  104 ++
 .../processors/odbc/jdbc/JdbcResult.java        |   91 +
 .../processors/odbc/jdbc/JdbcUtils.java         |   73 +
 .../processors/odbc/odbc/OdbcColumnMeta.java    |  110 ++
 .../processors/odbc/odbc/OdbcMessageParser.java |  213 ++-
 .../processors/odbc/odbc/OdbcObjectReader.java  |   33 -
 .../processors/odbc/odbc/OdbcObjectWriter.java  |   32 -
 .../odbc/odbc/OdbcQueryCloseRequest.java        |   49 +
 .../odbc/odbc/OdbcQueryCloseResult.java         |   40 +
 .../odbc/odbc/OdbcQueryExecuteRequest.java      |   78 +
 .../odbc/odbc/OdbcQueryExecuteResult.java       |   54 +
 .../odbc/odbc/OdbcQueryFetchRequest.java        |   61 +
 .../odbc/odbc/OdbcQueryFetchResult.java         |   66 +
 .../odbc/OdbcQueryGetColumnsMetaRequest.java    |   74 +
 .../odbc/OdbcQueryGetColumnsMetaResult.java     |   42 +
 .../odbc/OdbcQueryGetParamsMetaRequest.java     |   61 +
 .../odbc/odbc/OdbcQueryGetParamsMetaResult.java |   40 +
 .../odbc/OdbcQueryGetTablesMetaRequest.java     |   85 +
 .../odbc/odbc/OdbcQueryGetTablesMetaResult.java |   42 +
 .../processors/odbc/odbc/OdbcRequest.java       |   63 +
 .../odbc/odbc/OdbcRequestHandler.java           |  506 ++++++
 .../processors/odbc/odbc/OdbcResponse.java      |   69 +
 .../processors/odbc/odbc/OdbcTableMeta.java     |   88 +
 .../processors/odbc/odbc/OdbcTypes.java         |  131 ++
 .../processors/odbc/odbc/OdbcUtils.java         |  142 ++
 .../odbc/odbc/escape/OdbcEscapeUtils.java       |    2 +-
 .../platform/cache/PlatformCache.java           |    4 +-
 .../processors/query/GridQueryProcessor.java    |   67 +-
 .../internal/processors/query/QueryUtils.java   |   50 +
 .../resource/GridResourceProcessor.java         |    9 +-
 .../handlers/query/QueryCommandHandler.java     |    7 +-
 .../service/GridServiceProcessor.java           |   86 +-
 .../processors/task/GridTaskWorker.java         |    4 +-
 .../util/future/AsyncFutureListener.java        |   57 +
 .../internal/util/future/IgniteFutureImpl.java  |   33 +-
 .../util/tostring/GridToStringBuilder.java      |  419 +++++
 .../util/tostring/GridToStringThreadLocal.java  |    6 +-
 .../org/apache/ignite/lang/IgniteFuture.java    |   24 +-
 .../internal/SensitiveInfoTestLoggerProxy.java  |  493 +++++
 .../SensitiveInfoTestLoggerProxy_Exclude.txt    |   20 +
 .../SensitiveInfoTestLoggerProxy_Include.txt    |   18 +
 .../binary/BinaryFieldExtractionSelfTest.java   |   52 +
 .../binary/BinaryMarshallerSelfTest.java        |   36 +-
 ...gniteCacheInvokeReadThroughAbstractTest.java |   92 +-
 .../OdbcConfigurationValidationSelfTest.java    |  186 ++
 .../SqlListenerProcessorValidationSelfTest.java |  184 --
 .../query/GridQueryCommandHandlerTest.java      |    3 +-
 .../util/future/IgniteCacheFutureImplTest.java  |   46 +
 .../util/future/IgniteFutureImplTest.java       |  466 ++++-
 .../tostring/IncludeSensitiveAtomicTest.java    |   29 +
 .../util/tostring/IncludeSensitiveTest.java     |  149 ++
 .../IncludeSensitiveTransactionalTest.java      |   43 +
 .../testframework/junits/GridAbstractTest.java  |   24 +
 .../ignite/testframework/junits/IgniteMock.java |   11 +-
 .../junits/IgniteTestResources.java             |   61 +-
 .../cache/GridAbstractCacheStoreSelfTest.java   |    5 +-
 .../ignite/testsuites/IgniteBasicTestSuite.java |    4 +-
 .../testsuites/IgniteLangSelfTestSuite.java     |    3 +
 modules/flink/pom.xml                           |    2 +-
 .../query/h2/H2IndexingAbstractGeoSelfTest.java |   27 +-
 .../cache/query/CacheQueryPartitionInfo.java    |  110 ++
 .../cache/query/GridCacheTwoStepQuery.java      |   19 +
 .../processors/query/h2/IgniteH2Indexing.java   |   71 +-
 .../query/h2/ddl/DdlStatementsProcessor.java    |   59 +-
 .../query/h2/sql/GridSqlCreateTable.java        |   48 +-
 .../query/h2/sql/GridSqlQueryParser.java        |  105 +-
 .../query/h2/sql/GridSqlQuerySplitter.java      |  228 ++-
 .../query/h2/twostep/GridMapQueryExecutor.java  |   75 +-
 .../h2/twostep/GridReduceQueryExecutor.java     |   28 +-
 .../h2/twostep/msg/GridH2QueryRequest.java      |   37 +-
 .../cache/IgniteCacheAbstractQuerySelfTest.java |    4 +
 .../cache/IgniteCacheNoClassQuerySelfTest.java  |    2 +
 .../DynamicIndexAbstractBasicSelfTest.java      |   22 +-
 .../cache/index/H2DynamicTableSelfTest.java     |  292 ++-
 .../processors/query/IgniteSqlRoutingTest.java  |  552 ++++++
 .../query/IgniteSqlSchemaIndexingTest.java      |    3 +-
 .../processors/query/SqlSchemaSelfTest.java     |  263 +++
 .../query/h2/sql/GridQueryParsingTest.java      |   23 +-
 ...onnectorConfigurationValidationSelfTest.java |  240 +++
 .../IgniteCacheQuerySelfTestSuite.java          |    9 +-
 .../impls/storage/matrix/MapWrapperStorage.java |   17 +
 .../ml/math/impls/vector/MapWrapperVector.java  |   17 +
 .../ml/clustering/ClusteringTesetSuite.java     |   17 +
 .../core-test/config/cache-query-default.xml    |   27 +-
 .../cpp/core-test/src/cache_query_test.cpp      |   47 +-
 .../ignite/cache/query/query_sql_fields.h       |   53 +-
 .../odbc-example/config/example-odbc.xml        |    6 -
 .../odbc-test/config/queries-test-default.xml   |    9 +-
 .../odbc-test/config/queries-test-noodbc-32.xml |    4 +
 .../odbc-test/config/queries-test-noodbc.xml    |    6 +-
 .../project/vs/odbc-test.vcxproj.filters        |    4 +-
 .../cpp/odbc-test/src/api_robustness_test.cpp   |   54 +-
 .../cpp/odbc-test/src/configuration_test.cpp    |   32 +-
 .../cpp/odbc-test/src/queries_test.cpp          |   34 +-
 .../odbc-test/src/sql_test_suite_fixture.cpp    |    2 +-
 .../include/ignite/odbc/config/configuration.h  |   24 +-
 .../cpp/odbc/include/ignite/odbc/connection.h   |    6 +-
 .../cpp/odbc/include/ignite/odbc/message.h      |   30 +-
 .../odbc/system/ui/dsn_configuration_window.h   |   12 +-
 .../src/system/ui/dsn_configuration_window.cpp  |   18 +-
 .../cpp/odbc/src/config/configuration.cpp       |    4 +-
 modules/platforms/cpp/odbc/src/connection.cpp   |    4 +-
 modules/platforms/cpp/odbc/src/dsn_config.cpp   |    4 +-
 .../odbc/src/query/column_metadata_query.cpp    |    2 +-
 .../platforms/cpp/odbc/src/query/data_query.cpp |   14 +-
 modules/platforms/cpp/odbc/src/statement.cpp    |   12 +-
 .../Apache.Ignite.Core.Tests.NuGet/NuGet.config |    2 +-
 .../StartupTest.cs                              |    1 -
 .../install-package.ps1                         |   31 +-
 .../Apache.Ignite.Core.Tests.TestDll.csproj     |    1 +
 .../TestExtensions.cs                           |   35 +
 .../Apache.Ignite.Core.Tests.csproj             |    2 +
 .../Binary/BinarySelfTest.cs                    |    2 +-
 .../Binary/EnumsTest.cs                         |  299 ++-
 .../Binary/EnumsTestOnline.cs                   |   45 +
 .../Cache/Query/CacheLinqTest.cs                |   12 +-
 .../Cache/Query/CacheQueriesTest.cs             |   32 +
 .../Deployment/PeerAssemblyLoadingTest.cs       |   13 +
 .../Deployment/RuntimeDependencyFunc.cs         |   34 +
 .../Cache/Query/SqlFieldsQuery.cs               |   12 +-
 .../Impl/Binary/BinaryReader.cs                 |    9 +-
 .../Impl/Binary/BinaryReflectiveActions.cs      |   11 +-
 .../Impl/Binary/BinaryUtils.cs                  |    2 +
 .../Impl/Binary/BinaryWriter.cs                 |    4 +-
 .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs  |    1 +
 .../Impl/Compute/ComputeJobHolder.cs            |    6 +-
 .../Impl/Deployment/GetAssemblyFunc.cs          |   28 +
 .../Impl/Deployment/PeerAssemblyResolver.cs     |   26 +-
 .../Apache.Ignite.Core/Impl/ExceptionUtils.cs   |    1 +
 modules/platforms/dotnet/build.ps1              |   33 +-
 .../processors/schedule/ScheduleFutureImpl.java |   51 +-
 .../schedule/GridScheduleSelfTest.java          |   84 +-
 modules/web-console/backend/app/mongo.js        |   79 +-
 modules/web-console/backend/services/caches.js  |    2 +
 modules/web-console/backend/services/igfss.js   |    5 +
 modules/web-console/frontend/app/app.config.js  |    3 +-
 modules/web-console/frontend/app/app.js         |   12 +-
 .../cluster-select/cluster-select.pug           |    2 +-
 .../list-of-registered-users.column-defs.js     |    2 +-
 .../app/components/version-picker/component.js  |   52 +
 .../app/components/version-picker/index.js      |   25 +
 .../app/components/version-picker/style.scss    |   41 +
 .../app/components/version-picker/template.pug  |   33 +
 .../frontend/app/data/event-groups.json         |   14 +
 .../ui-ace-docker/ui-ace-docker.controller.js   |    8 +-
 .../ui-ace-java/ui-ace-java.controller.js       |   29 +-
 .../ui-ace-java/ui-ace-java.directive.js        |   12 +-
 .../ui-ace-pom/ui-ace-pom.controller.js         |    8 +-
 .../ui-ace-spring/ui-ace-spring.controller.js   |   29 +-
 .../ui-ace-spring/ui-ace-spring.directive.js    |   12 +-
 .../frontend/app/helpers/jade/mixins.pug        |    4 +-
 .../app/modules/agent/AgentManager.service.js   |   15 +-
 .../frontend/app/modules/cluster/Cache.js       |    4 +
 .../app/modules/cluster/CacheMetrics.js         |    4 +
 .../modules/configuration/Version.service.js    |  180 +-
 .../generator/AbstractTransformer.js            |  110 +-
 .../generator/ConfigurationGenerator.js         |  570 ++++--
 .../configuration/generator/Docker.service.js   |   12 +-
 .../generator/JavaTransformer.service.js        |   32 +-
 .../configuration/generator/Maven.service.js    |   38 +-
 .../generator/PlatformGenerator.js              |   19 +-
 .../generator/SpringTransformer.service.js      |   23 +-
 .../defaults/Cache.platform.service.js          |    9 +
 .../generator/defaults/Cache.service.js         |   23 +-
 .../generator/defaults/Cluster.service.js       |   46 +-
 .../generator/defaults/IGFS.service.js          |    9 +-
 .../frontend/app/modules/sql/sql.controller.js  |    6 +-
 .../app/modules/states/configuration.state.js   |   21 +-
 .../states/configuration/caches/affinity.pug    |   23 +-
 .../states/configuration/caches/concurrency.pug |   14 +
 .../states/configuration/caches/general.pug     |   71 +-
 .../states/configuration/caches/memory.pug      |   99 +-
 .../states/configuration/caches/node-filter.pug |   27 +-
 .../states/configuration/caches/query.pug       |   25 +-
 .../states/configuration/caches/store.pug       |    5 +
 .../configuration/clusters/deployment.pug       |    8 +-
 .../states/configuration/clusters/discovery.pug |   14 +-
 .../states/configuration/clusters/events.pug    |   26 +-
 .../states/configuration/clusters/failover.pug  |    9 +
 .../states/configuration/clusters/general.pug   |    2 +-
 .../states/configuration/clusters/hadoop.pug    |  119 ++
 .../configuration/clusters/marshaller.pug       |   37 +-
 .../states/configuration/clusters/memory.pug    |  114 ++
 .../states/configuration/clusters/metrics.pug   |    2 +-
 .../states/configuration/clusters/misc.pug      |   60 +
 .../states/configuration/clusters/service.pug   |   88 +
 .../states/configuration/clusters/swap.pug      |   72 +
 .../states/configuration/clusters/thread.pug    |   54 +-
 .../states/configuration/clusters/time.pug      |   13 +-
 .../states/configuration/domains/query.pug      |    2 +-
 .../modules/states/configuration/igfs/dual.pug  |   42 +
 .../modules/states/configuration/igfs/misc.pug  |   25 +-
 .../summary/summary-zipper.service.js           |    4 +-
 .../configuration/summary/summary.controller.js |    2 +-
 .../configuration/summary/summary.worker.js     |   13 +-
 .../frontend/app/primitives/btn-group/index.pug |   12 +-
 .../frontend/app/primitives/btn/index.scss      |    6 +
 .../frontend/app/primitives/dropdown/index.pug  |    3 +-
 .../frontend/app/primitives/dropdown/index.scss |   19 +-
 .../frontend/controllers/caches-controller.js   |   71 +-
 .../frontend/controllers/clusters-controller.js |  190 +-
 .../frontend/controllers/domains-controller.js  |    7 +-
 .../frontend/controllers/igfs-controller.js     |    9 +-
 .../frontend/public/stylesheets/style.scss      |   19 +-
 .../frontend/test/unit/Version.test.js          |   95 +-
 .../frontend/views/configuration/caches.tpl.pug |    2 +-
 .../views/configuration/clusters.tpl.pug        |   13 +-
 .../views/configuration/domains.tpl.pug         |    2 +-
 .../frontend/views/configuration/igfs.tpl.pug   |    6 +-
 .../views/configuration/sidebar.tpl.pug         |    4 +-
 .../frontend/views/includes/header-left.pug     |    3 -
 .../frontend/views/includes/header-right.pug    |    1 -
 .../frontend/views/settings/admin.tpl.pug       |    2 +-
 .../frontend/views/settings/profile.tpl.pug     |    2 +-
 .../web-console/frontend/views/signin.tpl.pug   |    6 +-
 .../web-console/frontend/views/sql/sql.tpl.pug  |    8 +-
 .../frontend/webpack/webpack.common.js          |    8 +-
 .../frontend/webpack/webpack.dev.babel.js       |    5 +-
 .../console/agent/handlers/ClusterListener.java |   12 +-
 347 files changed, 21066 insertions(+), 5018 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d1a8d5c4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1a8d5c4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1a8d5c4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1a8d5c4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1a8d5c4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1a8d5c4/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1a8d5c4/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1a8d5c4/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1a8d5c4/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1a8d5c4/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheNoClassQuerySelfTest.java
----------------------------------------------------------------------


[33/50] [abbrv] ignite git commit: Updated Apache Flink version to 1.3.0.

Posted by sb...@apache.org.
Updated Apache Flink version to 1.3.0.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e273f2e5
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e273f2e5
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e273f2e5

Branch: refs/heads/ignite-5075
Commit: e273f2e5523c3b599379b6abde9b3e7f19b8b4cb
Parents: 0d5a35a
Author: shroman <rs...@yahoo.com>
Authored: Mon Jun 5 16:14:30 2017 +0900
Committer: shroman <rs...@yahoo.com>
Committed: Mon Jun 5 16:14:30 2017 +0900

----------------------------------------------------------------------
 modules/flink/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e273f2e5/modules/flink/pom.xml
----------------------------------------------------------------------
diff --git a/modules/flink/pom.xml b/modules/flink/pom.xml
index 44c79e5..439fe20 100644
--- a/modules/flink/pom.xml
+++ b/modules/flink/pom.xml
@@ -35,7 +35,7 @@
     <url>http://ignite.apache.org</url>
 
     <properties>
-        <flink.version>1.2.0</flink.version>
+        <flink.version>1.3.0</flink.version>
     </properties>
 
     <dependencies>


[23/50] [abbrv] ignite git commit: IGNITE-5255: Implement update methods for JDBC thin driver. This closes #2050. This closes #2068.

Posted by sb...@apache.org.
IGNITE-5255: Implement update methods for JDBC thin driver. This closes #2050. This closes #2068.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/9d2ec1cc
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/9d2ec1cc
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/9d2ec1cc

Branch: refs/heads/ignite-5075
Commit: 9d2ec1cc24652a14f5c37c0ba36ca5f7c19d2209
Parents: 4024cd3
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Fri Jun 2 18:06:58 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 18:06:58 2017 +0300

----------------------------------------------------------------------
 .../jdbc/suite/IgniteJdbcDriverTestSuite.java   |  25 +-
 .../JdbcThinAbstractDmlStatementSelfTest.java   | 251 ++++++++++++++
 ...JdbcThinAbstractUpdateStatementSelfTest.java |  40 +++
 .../thin/JdbcThinDeleteStatementSelfTest.java   |  49 +++
 .../JdbcThinDynamicIndexAbstractSelfTest.java   | 326 +++++++++++++++++++
 ...namicIndexAtomicPartitionedNearSelfTest.java |  26 ++
 ...inDynamicIndexAtomicPartitionedSelfTest.java |  39 +++
 ...hinDynamicIndexAtomicReplicatedSelfTest.java |  39 +++
 ...dexTransactionalPartitionedNearSelfTest.java |  26 ++
 ...icIndexTransactionalPartitionedSelfTest.java |  39 +++
 ...micIndexTransactionalReplicatedSelfTest.java |  39 +++
 .../thin/JdbcThinInsertStatementSelfTest.java   | 185 +++++++++++
 .../thin/JdbcThinMergeStatementSelfTest.java    | 130 ++++++++
 .../thin/JdbcThinUpdateStatementSelfTest.java   |  50 +++
 .../jdbc/thin/JdbcThinPreparedStatement.java    |  34 +-
 .../internal/jdbc/thin/JdbcThinResultSet.java   |  16 +-
 .../internal/jdbc/thin/JdbcThinStatement.java   |  86 +++--
 17 files changed, 1356 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
index e0e6f31..121b8df 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
@@ -32,13 +32,23 @@ import org.apache.ignite.jdbc.JdbcPreparedStatementSelfTest;
 import org.apache.ignite.jdbc.JdbcResultSetSelfTest;
 import org.apache.ignite.jdbc.JdbcStatementSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinComplexQuerySelfTest;
-import org.apache.ignite.jdbc.thin.JdbcThinConnectionSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinDeleteStatementSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexAtomicPartitionedNearSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexAtomicPartitionedSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexAtomicReplicatedSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexTransactionalPartitionedNearSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexTransactionalPartitionedSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexTransactionalReplicatedSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinEmptyCacheSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinInsertStatementSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinMergeStatementSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinMetadataSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinNoDefaultSchemaTest;
 import org.apache.ignite.jdbc.thin.JdbcThinPreparedStatementSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinResultSetSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinStatementSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinConnectionSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinUpdateStatementSelfTest;
 
 /**
  * JDBC driver test suite.
@@ -102,6 +112,19 @@ public class IgniteJdbcDriverTestSuite extends TestSuite {
         suite.addTest(new TestSuite(JdbcThinEmptyCacheSelfTest.class));
         suite.addTest(new TestSuite(JdbcThinMetadataSelfTest.class));
 
+        suite.addTest(new TestSuite(JdbcThinInsertStatementSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinUpdateStatementSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinMergeStatementSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinDeleteStatementSelfTest.class));
+
+        // New thin JDBC driver, DDL tests
+        suite.addTest(new TestSuite(JdbcThinDynamicIndexAtomicPartitionedNearSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinDynamicIndexAtomicPartitionedSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinDynamicIndexAtomicReplicatedSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinDynamicIndexTransactionalPartitionedNearSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinDynamicIndexTransactionalPartitionedSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinDynamicIndexTransactionalReplicatedSelfTest.class));
+
         return suite;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
new file mode 100644
index 0000000..eddf61b
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
@@ -0,0 +1,251 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.Serializable;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.Collections;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.ConnectorConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Statement test.
+ */
+public abstract class JdbcThinAbstractDmlStatementSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** SQL SELECT query for verification. */
+    static final String SQL_SELECT = "select _key, id, firstName, lastName, age from Person";
+
+    /** Connection. */
+    protected Connection conn;
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
+
+        startGridsMultiThreaded(3);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        ignite(0).getOrCreateCache(cacheConfig());
+
+        conn = DriverManager.getConnection(URL);
+
+        conn.setSchema(DEFAULT_CACHE_NAME);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        grid(0).destroyCache(DEFAULT_CACHE_NAME);
+
+        conn.close();
+
+        assertTrue(conn.isClosed());
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        return getConfiguration0(igniteInstanceName);
+    }
+
+    /**
+     * @param igniteInstanceName Ignite instance name.
+     * @return Grid configuration used for starting the grid.
+     * @throws Exception If failed.
+     */
+    private IgniteConfiguration getConfiguration0(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        cfg.setConnectorConfiguration(new ConnectorConfiguration());
+
+        cfg.setOdbcConfiguration(new OdbcConfiguration());
+
+        return cfg;
+    }
+
+    /**
+     * @param igniteInstanceName Ignite instance name.
+     * @return Grid configuration used for starting the grid ready for manipulating binary objects.
+     * @throws Exception If failed.
+     */
+    IgniteConfiguration getBinaryConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = getConfiguration0(igniteInstanceName);
+
+        cfg.setMarshaller(new BinaryMarshaller());
+
+        CacheConfiguration ccfg = cfg.getCacheConfiguration()[0];
+
+        ccfg.getQueryEntities().clear();
+
+        QueryEntity e = new QueryEntity();
+
+        e.setKeyType(String.class.getName());
+        e.setValueType("Person");
+
+        e.addQueryField("id", Integer.class.getName(), null);
+        e.addQueryField("age", Integer.class.getName(), null);
+        e.addQueryField("firstName", String.class.getName(), null);
+        e.addQueryField("lastName", String.class.getName(), null);
+
+        ccfg.setQueryEntities(Collections.singletonList(e));
+
+        return cfg;
+    }
+
+    /**
+     * @return Cache configuration for non binary marshaller tests.
+     */
+    private CacheConfiguration nonBinCacheConfig() {
+        CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+        cache.setIndexedTypes(
+            String.class, Person.class
+        );
+
+        return cache;
+    }
+
+    /**
+     * @return Cache configuration for binary marshaller tests.
+     */
+    final CacheConfiguration binaryCacheConfig() {
+        CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+
+        QueryEntity e = new QueryEntity();
+
+        e.setKeyType(String.class.getName());
+        e.setValueType("Person");
+
+        e.addQueryField("id", Integer.class.getName(), null);
+        e.addQueryField("age", Integer.class.getName(), null);
+        e.addQueryField("firstName", String.class.getName(), null);
+        e.addQueryField("lastName", String.class.getName(), null);
+
+        cache.setQueryEntities(Collections.singletonList(e));
+
+        return cache;
+    }
+
+    /**
+     * @return Configuration of cache to create.
+     */
+    CacheConfiguration cacheConfig() {
+        return nonBinCacheConfig();
+    }
+
+    /**
+     * Person.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    static class Person implements Serializable {
+        /** ID. */
+        @QuerySqlField
+        private final int id;
+
+        /** First name. */
+        @QuerySqlField
+        private final String firstName;
+
+        /** Last name. */
+        @QuerySqlField
+        private final String lastName;
+
+        /** Age. */
+        @QuerySqlField
+        private final int age;
+
+        /**
+         * @param id ID.
+         * @param firstName First name.
+         * @param lastName Last name.
+         * @param age Age.
+         */
+        Person(int id, String firstName, String lastName, int age) {
+            assert !F.isEmpty(firstName);
+            assert !F.isEmpty(lastName);
+            assert age > 0;
+
+            this.id = id;
+            this.firstName = firstName;
+            this.lastName = lastName;
+            this.age = age;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Person person = (Person) o;
+
+            if (id != person.id) return false;
+            if (age != person.age) return false;
+            if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) return false;
+            return lastName != null ? lastName.equals(person.lastName) : person.lastName == null;
+
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            int result = id;
+            result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
+            result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
+            result = 31 * result + age;
+            return result;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractUpdateStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractUpdateStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractUpdateStatementSelfTest.java
new file mode 100644
index 0000000..f71d18a
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractUpdateStatementSelfTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.Statement;
+
+/**
+ *
+ */
+public abstract class JdbcThinAbstractUpdateStatementSelfTest extends JdbcThinAbstractDmlStatementSelfTest {
+    /** SQL query to populate cache. */
+    private static final String ITEMS_SQL = "insert into Person(_key, id, firstName, lastName, age) values " +
+        "('p1', 1, 'John', 'White', 25), " +
+        "('p2', 2, 'Joe', 'Black', 35), " +
+        "('p3', 3, 'Mike', 'Green', 40)";
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+        jcache(0).clear();
+        try (Statement s = conn.createStatement()) {
+            s.executeUpdate(ITEMS_SQL);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDeleteStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDeleteStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDeleteStatementSelfTest.java
new file mode 100644
index 0000000..9d0665b
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDeleteStatementSelfTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ *
+ */
+public class JdbcThinDeleteStatementSelfTest extends JdbcThinAbstractUpdateStatementSelfTest {
+    /**
+     * @throws SQLException If failed.
+     */
+    public void testExecute() throws SQLException {
+        conn.createStatement().execute("delete from Person where cast(substring(_key, 2, 1) as int) % 2 = 0");
+
+        assertFalse(jcache(0).containsKey("p2"));
+        assertTrue(jcache(0).containsKeys(new HashSet<Object>(Arrays.asList("p1", "p3"))));
+    }
+
+    /**
+     * @throws SQLException If failed.
+     */
+    public void testExecuteUpdate() throws SQLException {
+        int res =
+            conn.createStatement().executeUpdate("delete from Person where cast(substring(_key, 2, 1) as int) % 2 = 0");
+
+        assertEquals(1, res);
+        assertFalse(jcache(0).containsKey("p2"));
+        assertTrue(jcache(0).containsKeys(new HashSet<Object>(Arrays.asList("p1", "p3"))));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
new file mode 100644
index 0000000..3f762fc
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
@@ -0,0 +1,326 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.NearCacheConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/**
+ * Test that checks indexes handling with JDBC.
+ */
+public abstract class JdbcThinDynamicIndexAbstractSelfTest extends JdbcThinAbstractDmlStatementSelfTest {
+    /** */
+    private static final String CREATE_INDEX = "create index idx on Person (id desc)";
+
+    /** */
+    private static final String DROP_INDEX = "drop index idx";
+
+    /** */
+    private static final String CREATE_INDEX_IF_NOT_EXISTS = "create index if not exists idx on Person (id desc)";
+
+    /** */
+    private static final String DROP_INDEX_IF_EXISTS = "drop index idx if exists";
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        try (PreparedStatement ps =
+            conn.prepareStatement("INSERT INTO Person (_key, id, age, firstName, lastName) values (?, ?, ?, ?, ?)")) {
+
+            ps.setString(1, "j");
+            ps.setInt(2, 1);
+            ps.setInt(3, 10);
+            ps.setString(4, "John");
+            ps.setString(5, "Smith");
+            ps.executeUpdate();
+
+            ps.setString(1, "m");
+            ps.setInt(2, 2);
+            ps.setInt(3, 20);
+            ps.setString(4, "Mark");
+            ps.setString(5, "Stone");
+            ps.executeUpdate();
+
+            ps.setString(1, "s");
+            ps.setInt(2, 3);
+            ps.setInt(3, 30);
+            ps.setString(4, "Sarah");
+            ps.setString(5, "Pazzi");
+            ps.executeUpdate();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override CacheConfiguration cacheConfig() {
+        CacheConfiguration ccfg = super.cacheConfig();
+
+        ccfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
+
+        ccfg.setCacheMode(cacheMode());
+        ccfg.setAtomicityMode(atomicityMode());
+
+        if (nearCache())
+            ccfg.setNearConfiguration(new NearCacheConfiguration());
+
+        return ccfg;
+    }
+
+    /**
+     * @return Cache mode to use.
+     */
+    protected abstract CacheMode cacheMode();
+
+    /**
+     * @return Cache atomicity mode to use.
+     */
+    protected abstract CacheAtomicityMode atomicityMode();
+
+    /**
+     * @return Whether to use near cache.
+     */
+    protected abstract boolean nearCache();
+
+    /**
+     * Execute given SQL statement.
+     * @param sql Statement.
+     * @throws SQLException if failed.
+     */
+    private void jdbcRun(String sql) throws SQLException {
+        try (Statement stmt = conn.createStatement()) {
+            stmt.execute(sql);
+        }
+    }
+
+    /**
+     * @param rs Result set.
+     * @return The value of the first column at the first row from result set.
+     * @throws SQLException If failed.
+     */
+    private Object getSingleValue(ResultSet rs) throws SQLException {
+        assertEquals(1, rs.getMetaData().getColumnCount());
+
+        assertTrue(rs.next());
+
+        Object res = rs.getObject(1);
+
+        assertTrue(rs.isLast());
+
+        return res;
+    }
+
+    /**
+     * Test that after index creation index is used by queries.
+     * @throws SQLException If failed.
+     */
+    public void testCreateIndex() throws SQLException {
+        assertSize(3);
+
+        assertColumnValues(30, 20, 10);
+
+        jdbcRun(CREATE_INDEX);
+
+        // Test that local queries on all server nodes use new index.
+        for (int i = 0 ; i < 3; i++) {
+            List<List<?>> locRes = ignite(i).cache(DEFAULT_CACHE_NAME).query(new SqlFieldsQuery("explain select id from " +
+                "Person where id = 5").setLocal(true)).getAll();
+
+            assertEquals(F.asList(
+                Collections.singletonList("SELECT\n" +
+                    "    ID\n" +
+                    "FROM \"" + DEFAULT_CACHE_NAME + "\".PERSON\n" +
+                    "    /* \"" + DEFAULT_CACHE_NAME + "\".IDX: ID = 5 */\n" +
+                    "WHERE ID = 5")
+            ), locRes);
+        }
+
+        assertSize(3);
+
+        assertColumnValues(30, 20, 10);
+    }
+
+    /**
+     * Test that creating an index with duplicate name yields an error.
+     * @throws SQLException If failed.
+     */
+    public void testCreateIndexWithDuplicateName() throws SQLException {
+        jdbcRun(CREATE_INDEX);
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                jdbcRun(CREATE_INDEX);
+
+                return null;
+            }
+        }, IgniteCheckedException.class, "Index already exists: IDX");
+    }
+
+    /**
+     * Test that creating an index with duplicate name does not yield an error with {@code IF NOT EXISTS}.
+     * @throws SQLException If failed.
+     */
+    public void testCreateIndexIfNotExists() throws SQLException {
+        jdbcRun(CREATE_INDEX);
+
+        // Despite duplicate name, this does not yield an error.
+        jdbcRun(CREATE_INDEX_IF_NOT_EXISTS);
+    }
+
+    /**
+     * Test that after index drop there are no attempts to use it, and data state remains intact.
+     * @throws SQLException If failed.
+     */
+    public void testDropIndex() throws SQLException {
+        assertSize(3);
+
+        jdbcRun(CREATE_INDEX);
+
+        assertSize(3);
+
+        jdbcRun(DROP_INDEX);
+
+        // Test that no local queries on server nodes use new index.
+        for (int i = 0 ; i < 3; i++) {
+            List<List<?>> locRes = ignite(i).cache(DEFAULT_CACHE_NAME).query(new SqlFieldsQuery("explain select id from " +
+                "Person where id = 5").setLocal(true)).getAll();
+
+            assertEquals(F.asList(
+                Collections.singletonList("SELECT\n" +
+                    "    ID\n" +
+                    "FROM \"" + DEFAULT_CACHE_NAME + "\".PERSON\n" +
+                    "    /* \"" + DEFAULT_CACHE_NAME + "\".PERSON.__SCAN_ */\n" +
+                    "WHERE ID = 5")
+            ), locRes);
+        }
+
+        assertSize(3);
+    }
+
+    /**
+     * Test that dropping a non-existent index yields an error.
+     */
+    public void testDropMissingIndex() {
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                jdbcRun(DROP_INDEX);
+
+                return null;
+            }
+        }, IgniteCheckedException.class, "Index doesn't exist: IDX");
+    }
+
+    /**
+     * Test that dropping a non-existent index does not yield an error with {@code IF EXISTS}.
+     * @throws SQLException If failed.
+     */
+    public void testDropMissingIndexIfExists() throws SQLException {
+        // Despite index missing, this does not yield an error.
+        jdbcRun(DROP_INDEX_IF_EXISTS);
+    }
+
+    /**
+     * Test that changes in cache affect index, and vice versa.
+     * @throws SQLException If failed.
+     */
+    public void testIndexState() throws SQLException {
+        IgniteCache<String, Person> cache = cache();
+
+        assertSize(3);
+
+        assertColumnValues(30, 20, 10);
+
+        jdbcRun(CREATE_INDEX);
+
+        assertSize(3);
+
+        assertColumnValues(30, 20, 10);
+
+        cache.remove("m");
+
+        assertColumnValues(30, 10);
+
+        cache.put("a", new Person(4, "someVal", "a", 5));
+
+        assertColumnValues(5, 30, 10);
+
+        jdbcRun(DROP_INDEX);
+
+        assertColumnValues(5, 30, 10);
+    }
+
+    /**
+     * Check that values of {@code field1} match what we expect.
+     * @param vals Expected values.
+     * @throws SQLException If failed.
+     */
+    private void assertColumnValues(int... vals) throws SQLException {
+        try (Statement stmt = conn.createStatement()) {
+            try (ResultSet rs = stmt.executeQuery("SELECT age FROM Person ORDER BY id desc")) {
+                assertEquals(1, rs.getMetaData().getColumnCount());
+
+                for (int i = 0; i < vals.length; i++) {
+                    assertTrue("Result set must have " + vals.length + " rows, got " + i, rs.next());
+
+                    assertEquals(vals[i], rs.getInt(1));
+                }
+
+                assertFalse("Result set must have exactly " + vals.length + " rows", rs.next());
+            }
+        }
+    }
+
+    /**
+     * Do a {@code SELECT COUNT(*)} query to check index state correctness.
+     * @param expSize Expected number of items in table.
+     * @throws SQLException If failed.
+     */
+    private void assertSize(long expSize) throws SQLException {
+        assertEquals(expSize, cache().size());
+
+        try (Statement stmt = conn.createStatement()) {
+            conn.setSchema(DEFAULT_CACHE_NAME);
+
+            try (ResultSet rs = stmt.executeQuery("SELECT COUNT(*) from Person")) {
+                assertEquals(expSize, getSingleValue(rs));
+            }
+        }
+    }
+
+    /**
+     * @return Cache.
+     */
+    private IgniteCache<String, Person> cache() {
+        return grid(0).cache(DEFAULT_CACHE_NAME);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicPartitionedNearSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicPartitionedNearSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicPartitionedNearSelfTest.java
new file mode 100644
index 0000000..e6bf0cb
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicPartitionedNearSelfTest.java
@@ -0,0 +1,26 @@
+/*
+ * 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.jdbc.thin;
+
+/** */
+public class JdbcThinDynamicIndexAtomicPartitionedNearSelfTest extends JdbcThinDynamicIndexAtomicPartitionedSelfTest {
+    /** {@inheritDoc} */
+    @Override protected boolean nearCache() {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicPartitionedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicPartitionedSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicPartitionedSelfTest.java
new file mode 100644
index 0000000..826fc6b
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicPartitionedSelfTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.jdbc.thin;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+
+/** */
+public class JdbcThinDynamicIndexAtomicPartitionedSelfTest extends JdbcThinDynamicIndexAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return CacheMode.PARTITIONED;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicityMode atomicityMode() {
+        return CacheAtomicityMode.ATOMIC;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean nearCache() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicReplicatedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicReplicatedSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicReplicatedSelfTest.java
new file mode 100644
index 0000000..7729d2e
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAtomicReplicatedSelfTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.jdbc.thin;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+
+/** */
+public class JdbcThinDynamicIndexAtomicReplicatedSelfTest extends JdbcThinDynamicIndexAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return CacheMode.REPLICATED;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicityMode atomicityMode() {
+        return CacheAtomicityMode.ATOMIC;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean nearCache() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalPartitionedNearSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalPartitionedNearSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalPartitionedNearSelfTest.java
new file mode 100644
index 0000000..2f72108
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalPartitionedNearSelfTest.java
@@ -0,0 +1,26 @@
+/*
+ * 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.jdbc.thin;
+
+/** */
+public class JdbcThinDynamicIndexTransactionalPartitionedNearSelfTest extends JdbcThinDynamicIndexTransactionalPartitionedSelfTest {
+    /** {@inheritDoc} */
+    @Override protected boolean nearCache() {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalPartitionedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalPartitionedSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalPartitionedSelfTest.java
new file mode 100644
index 0000000..e2c56d7
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalPartitionedSelfTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.jdbc.thin;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+
+/** */
+public class JdbcThinDynamicIndexTransactionalPartitionedSelfTest extends JdbcThinDynamicIndexAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return CacheMode.PARTITIONED;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicityMode atomicityMode() {
+        return CacheAtomicityMode.TRANSACTIONAL;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean nearCache() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalReplicatedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalReplicatedSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalReplicatedSelfTest.java
new file mode 100644
index 0000000..ba6e1b6
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexTransactionalReplicatedSelfTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.jdbc.thin;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+
+/** */
+public class JdbcThinDynamicIndexTransactionalReplicatedSelfTest extends JdbcThinDynamicIndexAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return CacheMode.REPLICATED;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicityMode atomicityMode() {
+        return CacheAtomicityMode.TRANSACTIONAL;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean nearCache() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
new file mode 100644
index 0000000..3b86757
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
@@ -0,0 +1,185 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.concurrent.Callable;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/**
+ * Statement test.
+ */
+public class JdbcThinInsertStatementSelfTest extends JdbcThinAbstractDmlStatementSelfTest {
+    /** SQL query. */
+    private static final String SQL = "insert into Person(_key, id, firstName, lastName, age) values " +
+        "('p1', 1, 'John', 'White', 25), " +
+        "('p2', 2, 'Joe', 'Black', 35), " +
+        "('p3', 3, 'Mike', 'Green', 40)";
+
+    /** SQL query. */
+    private static final String SQL_PREPARED = "insert into Person(_key, id, firstName, lastName, age) values " +
+        "(?, ?, ?, ?, ?), (?, ?, ?, ?, ?), (?, ?, ?, ?, ?)";
+
+    /** Arguments for prepared statement. */
+    private final Object [][] args = new Object[][] {
+        {"p1", 1, "John", "White", 25},
+        {"p3", 3, "Mike", "Green", 40},
+        {"p2", 2, "Joe", "Black", 35}
+    };
+
+    /** Statement. */
+    private Statement stmt;
+
+    /** Prepared statement. */
+    private PreparedStatement prepStmt;
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        stmt = conn.createStatement();
+
+        prepStmt = conn.prepareStatement(SQL_PREPARED);
+
+        assertNotNull(stmt);
+        assertFalse(stmt.isClosed());
+
+        assertNotNull(prepStmt);
+        assertFalse(prepStmt.isClosed());
+
+        int paramCnt = 1;
+
+        for (Object[] arg : args) {
+            prepStmt.setString(paramCnt++, (String)arg[0]);
+            prepStmt.setInt(paramCnt++, (Integer)arg[1]);
+            prepStmt.setString(paramCnt++, (String)arg[2]);
+            prepStmt.setString(paramCnt++, (String)arg[3]);
+            prepStmt.setInt(paramCnt++, (Integer)arg[4]);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        try (Statement selStmt = conn.createStatement()) {
+            assertTrue(selStmt.execute(SQL_SELECT));
+
+            ResultSet rs = selStmt.getResultSet();
+
+            assert rs != null;
+
+            while (rs.next()) {
+                int id = rs.getInt("id");
+
+                switch (id) {
+                    case 1:
+                        assertEquals("p1", rs.getString("_key"));
+                        assertEquals("John", rs.getString("firstName"));
+                        assertEquals("White", rs.getString("lastName"));
+                        assertEquals(25, rs.getInt("age"));
+                        break;
+
+                    case 2:
+                        assertEquals("p2", rs.getString("_key"));
+                        assertEquals("Joe", rs.getString("firstName"));
+                        assertEquals("Black", rs.getString("lastName"));
+                        assertEquals(35, rs.getInt("age"));
+                        break;
+
+                    case 3:
+                        assertEquals("p3", rs.getString("_key"));
+                        assertEquals("Mike", rs.getString("firstName"));
+                        assertEquals("Green", rs.getString("lastName"));
+                        assertEquals(40, rs.getInt("age"));
+                        break;
+
+                    case 4:
+                        assertEquals("p4", rs.getString("_key"));
+                        assertEquals("Leah", rs.getString("firstName"));
+                        assertEquals("Grey", rs.getString("lastName"));
+                        assertEquals(22, rs.getInt("age"));
+                        break;
+
+                    default:
+                        assert false : "Invalid ID: " + id;
+                }
+            }
+        }
+
+        if (stmt != null && !stmt.isClosed())
+            stmt.close();
+
+        if (prepStmt != null && !prepStmt.isClosed())
+            prepStmt.close();
+
+        assertTrue(prepStmt.isClosed());
+        assertTrue(stmt.isClosed());
+
+        super.afterTest();
+    }
+
+    /**
+     * @throws SQLException If failed.
+     */
+    public void testExecuteUpdate() throws SQLException {
+        assertEquals(3, stmt.executeUpdate(SQL));
+    }
+
+    /**
+     * @throws SQLException If failed.
+     */
+    public void testPreparedExecuteUpdate() throws SQLException {
+        assertEquals(3, prepStmt.executeUpdate());
+    }
+
+    /**
+     * @throws SQLException If failed.
+     */
+    public void testExecute() throws SQLException {
+        assertFalse(stmt.execute(SQL));
+    }
+
+    /**
+     * @throws SQLException If failed.
+     */
+    public void testPreparedExecute() throws SQLException {
+        assertFalse(prepStmt.execute());
+    }
+
+    /**
+     *
+     */
+    public void testDuplicateKeys() {
+        jcache(0).put("p2", new Person(2, "Joe", "Black", 35));
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+            /** {@inheritDoc} */
+            @Override public Object call() throws Exception {
+                return stmt.execute(SQL);
+            }
+        }, IgniteCheckedException.class,
+            "Failed to INSERT some keys because they are already in cache [keys=[p2]]");
+
+        assertEquals(3, jcache(0).withKeepBinary().getAll(new HashSet<>(Arrays.asList("p1", "p2", "p3"))).size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMergeStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMergeStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMergeStatementSelfTest.java
new file mode 100644
index 0000000..9d9467f
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMergeStatementSelfTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+/**
+ * MERGE statement test.
+ */
+public class JdbcThinMergeStatementSelfTest extends JdbcThinAbstractDmlStatementSelfTest {
+    /** SQL query. */
+    private static final String SQL = "merge into Person(_key, id, firstName, lastName, age) values " +
+        "('p1', 1, 'John', 'White', 25), " +
+        "('p2', 2, 'Joe', 'Black', 35), " +
+        "('p3', 3, 'Mike', 'Green', 40)";
+
+    /** SQL query. */
+    protected static final String SQL_PREPARED = "merge into Person(_key, id, firstName, lastName, age) values " +
+        "(?, ?, ?, ?, ?), (?, ?, ?, ?, ?)";
+
+    /** Statement. */
+    protected Statement stmt;
+
+    /** Prepared statement. */
+    protected PreparedStatement prepStmt;
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+        stmt = conn.createStatement();
+        prepStmt = conn.prepareStatement(SQL_PREPARED);
+
+        assertNotNull(stmt);
+        assertFalse(stmt.isClosed());
+
+        assertNotNull(prepStmt);
+        assertFalse(prepStmt.isClosed());
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        try (Statement selStmt = conn.createStatement()) {
+            assertTrue(selStmt.execute(SQL_SELECT));
+
+            ResultSet rs = selStmt.getResultSet();
+
+            assert rs != null;
+
+            while (rs.next()) {
+                int id = rs.getInt("id");
+
+                switch (id) {
+                    case 1:
+                        assertEquals("p1", rs.getString("_key"));
+                        assertEquals("John", rs.getString("firstName"));
+                        assertEquals("White", rs.getString("lastName"));
+                        assertEquals(25, rs.getInt("age"));
+                        break;
+
+                    case 2:
+                        assertEquals("p2", rs.getString("_key"));
+                        assertEquals("Joe", rs.getString("firstName"));
+                        assertEquals("Black", rs.getString("lastName"));
+                        assertEquals(35, rs.getInt("age"));
+                        break;
+
+                    case 3:
+                        assertEquals("p3", rs.getString("_key"));
+                        assertEquals("Mike", rs.getString("firstName"));
+                        assertEquals("Green", rs.getString("lastName"));
+                        assertEquals(40, rs.getInt("age"));
+                        break;
+
+                    case 4:
+                        assertEquals("p4", rs.getString("_key"));
+                        assertEquals("Leah", rs.getString("firstName"));
+                        assertEquals("Grey", rs.getString("lastName"));
+                        assertEquals(22, rs.getInt("age"));
+                        break;
+
+                    default:
+                        assert false : "Invalid ID: " + id;
+                }
+            }
+        }
+
+        if (stmt != null && !stmt.isClosed())
+            stmt.close();
+
+        if (prepStmt != null && !prepStmt.isClosed())
+            prepStmt.close();
+
+        assertTrue(prepStmt.isClosed());
+        assertTrue(stmt.isClosed());
+
+        super.afterTest();
+    }
+
+    /**
+     * @throws SQLException If failed.
+     */
+    public void testExecuteUpdate() throws SQLException {
+        assertEquals(3, stmt.executeUpdate(SQL));
+    }
+
+    /**
+     * @throws SQLException If failed.
+     */
+    public void testExecute() throws SQLException {
+        assertFalse(stmt.execute(SQL));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinUpdateStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinUpdateStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinUpdateStatementSelfTest.java
new file mode 100644
index 0000000..f749dbe
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinUpdateStatementSelfTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.util.typedef.F;
+
+/**
+ *
+ */
+public class JdbcThinUpdateStatementSelfTest extends JdbcThinAbstractUpdateStatementSelfTest {
+    /**
+     * @throws SQLException If failed.
+     */
+    public void testExecute() throws SQLException {
+        conn.createStatement().execute("update Person set firstName = 'Jack' where " +
+            "cast(substring(_key, 2, 1) as int) % 2 = 0");
+
+        assertEquals(Arrays.asList(F.asList("John"), F.asList("Jack"), F.asList("Mike")),
+            jcache(0).query(new SqlFieldsQuery("select firstName from Person order by _key")).getAll());
+    }
+
+    /**
+     * @throws SQLException If failed.
+     */
+    public void testExecuteUpdate() throws SQLException {
+        conn.createStatement().executeUpdate("update Person set firstName = 'Jack' where " +
+                "cast(substring(_key, 2, 1) as int) % 2 = 0");
+
+        assertEquals(Arrays.asList(F.asList("John"), F.asList("Jack"), F.asList("Mike")),
+                jcache(0).query(new SqlFieldsQuery("select firstName from Person order by _key")).getAll());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
index 0b1cad8..49a78b6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
@@ -48,6 +48,9 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
     /** SQL query. */
     private final String sql;
 
+    /** Query arguments. */
+    protected ArrayList<Object> args;
+
     /**
      * Creates new prepared statement.
      *
@@ -62,9 +65,12 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
 
     /** {@inheritDoc} */
     @Override public ResultSet executeQuery() throws SQLException {
-        ResultSet rs = super.executeQuery(sql);
+        executeWithArguments();
 
-        args = null;
+        ResultSet rs = getResultSet();
+
+        if (rs == null)
+            throw new SQLException("The query isn't SELECT query: " + sql);
 
         return rs;
     }
@@ -76,9 +82,14 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
 
     /** {@inheritDoc} */
     @Override public int executeUpdate() throws SQLException {
-        ensureNotClosed();
+        executeWithArguments();
 
-        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+        int res = getUpdateCount();
+
+        if (res == -1)
+            throw new SQLException("The query is not DML statememt: " + sql);
+
+        return res;
     }
 
     /** {@inheritDoc} */
@@ -196,7 +207,20 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
 
     /** {@inheritDoc} */
     @Override public boolean execute() throws SQLException {
-        return super.execute(sql);
+        executeWithArguments();
+
+        return rs.isQuery();
+    }
+
+    /**
+     * Execute query with arguments and nullify them afterwards.
+     *
+     * @throws SQLException If failed.
+     */
+    private void executeWithArguments() throws SQLException {
+        execute0(sql, args);
+
+        args = null;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
index f4ab444..36f938b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
@@ -107,20 +107,26 @@ public class JdbcThinResultSet implements ResultSet {
      * @param rows Rows.
      * @param isQuery Is Result ser for Select query
      */
-    @SuppressWarnings("OverlyStrongTypeCast") JdbcThinResultSet(JdbcThinStatement stmt, long qryId, int fetchSize, boolean finished,
-        List<List<Object>> rows, boolean isQuery) {
+    @SuppressWarnings("OverlyStrongTypeCast")
+    JdbcThinResultSet(JdbcThinStatement stmt, long qryId, int fetchSize, boolean finished,
+        List<List<Object>> rows, boolean isQuery, long updCnt) {
         assert stmt != null;
         assert fetchSize > 0;
 
         this.stmt = stmt;
         this.qryId = qryId;
         this.fetchSize = fetchSize;
-        this.rows = rows;
         this.finished = finished;
+        this.isQuery = isQuery;
 
-        rowsIter = rows.iterator();
+        if (isQuery) {
+            this.fetchSize = fetchSize;
+            this.rows = rows;
 
-        this.isQuery = isQuery;
+            rowsIter = rows.iterator();
+        }
+        else
+            this.updCnt = updCnt;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d2ec1cc/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
index 2bcd4d1..91b8b06 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
@@ -24,7 +24,7 @@ import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
 import java.sql.SQLWarning;
 import java.sql.Statement;
-import java.util.ArrayList;
+import java.util.List;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cache.query.SqlQuery;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult;
@@ -54,14 +54,12 @@ public class JdbcThinStatement implements Statement {
     private int timeout;
 
     /** Current result set. */
-    private JdbcThinResultSet rs;
-
-    /** Query arguments. */
-    protected ArrayList<Object> args;
+    protected JdbcThinResultSet rs;
 
     /** Fetch size. */
     private int pageSize = DFLT_PAGE_SIZE;
 
+    /** */
     private boolean alreadyRead;
 
     /**
@@ -77,20 +75,23 @@ public class JdbcThinStatement implements Statement {
 
     /** {@inheritDoc} */
     @Override public ResultSet executeQuery(String sql) throws SQLException {
-        JdbcThinResultSet rs = execute0(sql);
+        execute0(sql, null);
+
+        ResultSet rs = getResultSet();
 
-        if (!rs.isQuery())
-            throw new SQLException("The query isn't SELECT query: [sql=" + sql +']');
+        if (rs == null)
+            throw new SQLException("The query isn't SELECT query: " + sql);
 
         return rs;
     }
 
     /**
      * @param sql Sql query.
-     * @return Result set.
+     * @param args Query parameters.
+     *
      * @throws SQLException Onj error.
      */
-    protected JdbcThinResultSet execute0(String sql) throws SQLException {
+    protected void execute0(String sql, List<Object> args) throws SQLException {
         ensureNotClosed();
 
         if (rs != null) {
@@ -110,9 +111,8 @@ public class JdbcThinStatement implements Statement {
 
             assert res != null;
 
-            rs = new JdbcThinResultSet(this, res.getQueryId(), pageSize, res.last(), res.items(), res.isQuery());
-
-            return rs;
+            rs = new JdbcThinResultSet(this, res.getQueryId(), pageSize, res.last(), res.items(),
+                res.isQuery(), res.updateCount());
         }
         catch (IOException e) {
             conn.close();
@@ -126,9 +126,14 @@ public class JdbcThinStatement implements Statement {
 
     /** {@inheritDoc} */
     @Override public int executeUpdate(String sql) throws SQLException {
-        ensureNotClosed();
+        execute0(sql, null);
 
-        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+        int res = getUpdateCount();
+
+        if (res == -1)
+            throw new SQLException("The query is not DML statememt: " + sql);
+
+        return res;
     }
 
     /** {@inheritDoc} */
@@ -217,33 +222,48 @@ public class JdbcThinStatement implements Statement {
     @Override public boolean execute(String sql) throws SQLException {
         ensureNotClosed();
 
-        rs = execute0(sql);
+        execute0(sql, null);
 
         return rs.isQuery();
     }
 
     /** {@inheritDoc} */
     @Override public ResultSet getResultSet() throws SQLException {
-        ensureNotClosed();
+        JdbcThinResultSet rs = lastResultSet();
 
-        if (rs == null || !rs.isQuery() || alreadyRead)
-            return null;
+        ResultSet res = rs == null || !rs.isQuery() ? null : rs;
 
-        alreadyRead = true;
+        if (res != null)
+            alreadyRead = true;
 
-        return rs;
+        return res;
     }
 
     /** {@inheritDoc} */
     @Override public int getUpdateCount() throws SQLException {
-        ensureNotClosed();
+        JdbcThinResultSet rs = lastResultSet();
+
+        int res = rs == null || rs.isQuery() ? -1 : (int)rs.updatedCount();
 
-        if (rs == null || rs.isQuery() || alreadyRead)
-            return -1;
+        if (res != -1)
+            alreadyRead = true;
 
-        alreadyRead = true;
+        return res;
+    }
 
-        return (int)rs.updatedCount();
+    /**
+     * Get last result set if any.
+     *
+     * @return Result set or null.
+     * @throws SQLException If failed.
+     */
+    private JdbcThinResultSet lastResultSet() throws SQLException {
+        ensureNotClosed();
+
+        if (rs == null || alreadyRead)
+            return null;
+
+        return rs;
     }
 
     /** {@inheritDoc} */
@@ -341,28 +361,28 @@ public class JdbcThinStatement implements Statement {
     @Override public ResultSet getGeneratedKeys() throws SQLException {
         ensureNotClosed();
 
-        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+        throw new SQLFeatureNotSupportedException("Auto-generated columns are not supported .");
     }
 
     /** {@inheritDoc} */
     @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
         ensureNotClosed();
 
-        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+        throw new SQLFeatureNotSupportedException("Auto-generated columns are not supported .");
     }
 
     /** {@inheritDoc} */
     @Override public int executeUpdate(String sql, int[] colIndexes) throws SQLException {
         ensureNotClosed();
 
-        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+        throw new SQLFeatureNotSupportedException("Auto-generated columns are not supported .");
     }
 
     /** {@inheritDoc} */
     @Override public int executeUpdate(String sql, String[] colNames) throws SQLException {
         ensureNotClosed();
 
-        throw new SQLFeatureNotSupportedException("Updates are not supported.");
+        throw new SQLFeatureNotSupportedException("Auto-generated columns are not supported .");
     }
 
     /** {@inheritDoc} */
@@ -370,7 +390,7 @@ public class JdbcThinStatement implements Statement {
         ensureNotClosed();
 
         if (autoGeneratedKeys == RETURN_GENERATED_KEYS)
-            throw new SQLFeatureNotSupportedException("Updates are not supported.");
+            throw new SQLFeatureNotSupportedException("Auto-generated columns are not supported .");
 
         return execute(sql);
     }
@@ -380,7 +400,7 @@ public class JdbcThinStatement implements Statement {
         ensureNotClosed();
 
         if (colIndexes != null && colIndexes.length > 0)
-            throw new SQLFeatureNotSupportedException("Updates are not supported.");
+            throw new SQLFeatureNotSupportedException("Auto-generated columns are not supported .");
 
         return execute(sql);
     }
@@ -390,7 +410,7 @@ public class JdbcThinStatement implements Statement {
         ensureNotClosed();
 
         if (colNames != null && colNames.length > 0)
-            throw new SQLFeatureNotSupportedException("Updates are not supported.");
+            throw new SQLFeatureNotSupportedException("Auto-generated columns are not supported .");
 
         return execute(sql);
     }


[11/50] [abbrv] ignite git commit: IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
new file mode 100644
index 0000000..418b5fc
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
@@ -0,0 +1,762 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Result set test.
+ */
+@SuppressWarnings("FloatingPointEquality")
+public class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** SQL query. */
+    private static final String SQL =
+        "select id, boolVal, byteVal, shortVal, intVal, longVal, floatVal, " +
+            "doubleVal, bigVal, strVal, arrVal, dateVal, timeVal, tsVal " +
+            "from TestObject where id = 1";
+
+    /** Statement. */
+    private Statement stmt;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+        cache.setIndexedTypes(
+            Integer.class, TestObject.class
+        );
+
+        cfg.setCacheConfiguration(cache);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        cfg.setMarshaller(new BinaryMarshaller());
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(3);
+
+        IgniteCache<Integer, TestObject> cache = grid(0).cache(DEFAULT_CACHE_NAME);
+
+        assert cache != null;
+
+        TestObject o = createObjectWithData(1);
+
+        cache.put(1, o);
+        cache.put(2, new TestObject(2));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        Connection conn = DriverManager.getConnection(URL);
+
+        conn.setSchema(DEFAULT_CACHE_NAME);
+
+        stmt = conn.createStatement();
+
+        assert stmt != null;
+        assert !stmt.isClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (stmt != null) {
+            stmt.getConnection().close();
+
+            stmt.close();
+
+            assert stmt.isClosed();
+        }
+    }
+
+    /**
+     * @param id ID.
+     * @return Object.
+     * @throws MalformedURLException If URL in incorrect.
+     */
+    @SuppressWarnings("deprecation")
+    private TestObject createObjectWithData(int id) throws MalformedURLException {
+        TestObject o = new TestObject(id);
+
+        o.boolVal = true;
+        o.byteVal = 1;
+        o.shortVal = 1;
+        o.intVal = 1;
+        o.longVal = 1L;
+        o.floatVal = 1.0f;
+        o.doubleVal = 1.0d;
+        o.bigVal = new BigDecimal(1);
+        o.strVal = "str";
+        o.arrVal = new byte[] {1};
+        o.dateVal = new Date(1, 1, 1);
+        o.timeVal = new Time(1, 1, 1);
+        o.tsVal = new Timestamp(1);
+        o.urlVal = new URL("http://abc.com/");
+
+        return o;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBoolean() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getBoolean("boolVal");
+                assert rs.getBoolean(2);
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+
+        ResultSet rs0 = stmt.executeQuery("select 1");
+
+        assert rs0.next();
+        assert rs0.getBoolean(1);
+
+        rs0 = stmt.executeQuery("select 0");
+
+        assert rs0.next();
+        assert !rs0.getBoolean(1);
+
+        rs0 = stmt.executeQuery("select '1'");
+
+        assert rs0.next();
+        assert rs0.getBoolean(1);
+
+        rs0 = stmt.executeQuery("select '0'");
+
+        assert rs0.next();
+        assert !rs0.getBoolean(1);
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                ResultSet rs0 = stmt.executeQuery("select 10");
+
+                assert rs0.next();
+                assert rs0.getBoolean(1);
+
+                return null;
+            }
+        }, ClassCastException.class, "Cannot cast java.lang.Integer [val=10] to boolean");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                ResultSet rs0 = stmt.executeQuery("select '10'");
+
+                assert rs0.next();
+                assert rs0.getBoolean(1);
+
+                return null;
+            }
+        }, ClassCastException.class, "Cannot cast java.lang.Integer [val=10] to boolean");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                ResultSet rs0 = stmt.executeQuery("select ''");
+
+                assert rs0.next();
+                assert rs0.getBoolean(1);
+
+                return null;
+            }
+        }, ClassCastException.class, "Cannot cast [val=] to boolean");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                ResultSet rs0 = stmt.executeQuery("select 'qwe'");
+
+                assert rs0.next();
+                assert rs0.getBoolean(1);
+
+                return null;
+            }
+        }, ClassCastException.class, "Cannot cast [val=qwe] to boolean");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testByte() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getByte("byteVal") == 1;
+                assert rs.getByte(3) == 1;
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testShort() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getShort("shortVal") == 1;
+                assert rs.getShort(4) == 1;
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testInteger() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getInt("intVal") == 1;
+                assert rs.getInt(5) == 1;
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLong() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getLong("longVal") == 1;
+                assert rs.getLong(6) == 1;
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testFloat() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getFloat("floatVal") == 1.0;
+                assert rs.getFloat(7) == 1.0;
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDouble() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getDouble("doubleVal") == 1.0;
+                assert rs.getDouble(8) == 1.0;
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBigDecimal() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getBigDecimal("bigVal").intValue() == 1;
+                assert rs.getBigDecimal(9).intValue() == 1;
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testString() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert "str".equals(rs.getString("strVal"));
+                assert "str".equals(rs.getString(10));
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testArray() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert Arrays.equals(rs.getBytes("arrVal"), new byte[] {1});
+                assert Arrays.equals(rs.getBytes(11), new byte[] {1});
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("deprecation")
+    public void testDate() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getDate("dateVal").equals(new Date(1, 1, 1));
+                assert rs.getDate(12).equals(new Date(1, 1, 1));
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("deprecation")
+    public void testTime() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getTime("timeVal").equals(new Time(1, 1, 1));
+                assert rs.getTime(13).equals(new Time(1, 1, 1));
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testTimestamp() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0) {
+                assert rs.getTimestamp("tsVal").getTime() == 1;
+                assert rs.getTimestamp(14).getTime() == 1;
+            }
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testObjectNotSupported() throws Exception {
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                stmt.executeQuery("select f1 from TestObject where id = 1");
+
+                return null;
+            }
+        }, IgniteCheckedException.class, "Custom objects are not supported");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNavigation() throws Exception {
+        ResultSet rs = stmt.executeQuery("select id from TestObject where id > 0");
+
+        assert rs.isBeforeFirst();
+        assert !rs.isAfterLast();
+        assert !rs.isFirst();
+        assert !rs.isLast();
+        assert rs.getRow() == 0;
+
+        assert rs.next();
+
+        assert !rs.isBeforeFirst();
+        assert !rs.isAfterLast();
+        assert rs.isFirst();
+        assert !rs.isLast();
+        assert rs.getRow() == 1;
+
+        assert rs.next();
+
+        assert !rs.isBeforeFirst();
+        assert !rs.isAfterLast();
+        assert !rs.isFirst();
+        assert rs.isLast();
+        assert rs.getRow() == 2;
+
+        assert !rs.next();
+
+        assert !rs.isBeforeFirst();
+        assert rs.isAfterLast();
+        assert !rs.isFirst();
+        assert !rs.isLast();
+        assert rs.getRow() == 0;
+
+        rs = stmt.executeQuery("select id from TestObject where id < 0");
+
+        assert !rs.isBeforeFirst();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testFindColumn() throws Exception {
+        final ResultSet rs = stmt.executeQuery(SQL);
+
+        assert rs != null;
+        assert rs.next();
+
+        assert rs.findColumn("id") == 1;
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    rs.findColumn("wrong");
+
+                    return null;
+                }
+            },
+            SQLException.class,
+            "Column not found: wrong"
+        );
+    }
+
+    /**
+     * Test object.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class TestObject implements Serializable {
+        /** */
+        @QuerySqlField
+        private final int id;
+
+        /** */
+        @QuerySqlField(index = false)
+        private Boolean boolVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private Byte byteVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private Short shortVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private Integer intVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private Long longVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private Float floatVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private Double doubleVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private BigDecimal bigVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private String strVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private byte[] arrVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private Date dateVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private Time timeVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private Timestamp tsVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private URL urlVal;
+
+        /** */
+        @QuerySqlField(index = false)
+        private TestObjectField f1 = new TestObjectField(100, "AAAA");
+
+        /** */
+        @QuerySqlField(index = false)
+        private TestObjectField f2 = new TestObjectField(500, "BBBB");
+
+        /** */
+        @QuerySqlField(index = false)
+        private TestObjectField f3;
+
+        /**
+         * @param id ID.
+         */
+        private TestObject(int id) {
+            this.id = id;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return S.toString(TestObject.class, this);
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings({"BigDecimalEquals", "EqualsHashCodeCalledOnUrl", "RedundantIfStatement"})
+        @Override public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            TestObject that = (TestObject)o;
+
+            if (id != that.id) return false;
+            if (!Arrays.equals(arrVal, that.arrVal)) return false;
+            if (bigVal != null ? !bigVal.equals(that.bigVal) : that.bigVal != null) return false;
+            if (boolVal != null ? !boolVal.equals(that.boolVal) : that.boolVal != null) return false;
+            if (byteVal != null ? !byteVal.equals(that.byteVal) : that.byteVal != null) return false;
+            if (dateVal != null ? !dateVal.equals(that.dateVal) : that.dateVal != null) return false;
+            if (doubleVal != null ? !doubleVal.equals(that.doubleVal) : that.doubleVal != null) return false;
+            if (f1 != null ? !f1.equals(that.f1) : that.f1 != null) return false;
+            if (f2 != null ? !f2.equals(that.f2) : that.f2 != null) return false;
+            if (f3 != null ? !f3.equals(that.f3) : that.f3 != null) return false;
+            if (floatVal != null ? !floatVal.equals(that.floatVal) : that.floatVal != null) return false;
+            if (intVal != null ? !intVal.equals(that.intVal) : that.intVal != null) return false;
+            if (longVal != null ? !longVal.equals(that.longVal) : that.longVal != null) return false;
+            if (shortVal != null ? !shortVal.equals(that.shortVal) : that.shortVal != null) return false;
+            if (strVal != null ? !strVal.equals(that.strVal) : that.strVal != null) return false;
+            if (timeVal != null ? !timeVal.equals(that.timeVal) : that.timeVal != null) return false;
+            if (tsVal != null ? !tsVal.equals(that.tsVal) : that.tsVal != null) return false;
+            if (urlVal != null ? !urlVal.equals(that.urlVal) : that.urlVal != null) return false;
+
+            return true;
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("EqualsHashCodeCalledOnUrl")
+        @Override public int hashCode() {
+            int res = id;
+
+            res = 31 * res + (boolVal != null ? boolVal.hashCode() : 0);
+            res = 31 * res + (byteVal != null ? byteVal.hashCode() : 0);
+            res = 31 * res + (shortVal != null ? shortVal.hashCode() : 0);
+            res = 31 * res + (intVal != null ? intVal.hashCode() : 0);
+            res = 31 * res + (longVal != null ? longVal.hashCode() : 0);
+            res = 31 * res + (floatVal != null ? floatVal.hashCode() : 0);
+            res = 31 * res + (doubleVal != null ? doubleVal.hashCode() : 0);
+            res = 31 * res + (bigVal != null ? bigVal.hashCode() : 0);
+            res = 31 * res + (strVal != null ? strVal.hashCode() : 0);
+            res = 31 * res + (arrVal != null ? Arrays.hashCode(arrVal) : 0);
+            res = 31 * res + (dateVal != null ? dateVal.hashCode() : 0);
+            res = 31 * res + (timeVal != null ? timeVal.hashCode() : 0);
+            res = 31 * res + (tsVal != null ? tsVal.hashCode() : 0);
+            res = 31 * res + (urlVal != null ? urlVal.hashCode() : 0);
+            res = 31 * res + (f1 != null ? f1.hashCode() : 0);
+            res = 31 * res + (f2 != null ? f2.hashCode() : 0);
+            res = 31 * res + (f3 != null ? f3.hashCode() : 0);
+
+            return res;
+        }
+    }
+
+    /**
+     * Test object field.
+     */
+    @SuppressWarnings("PackageVisibleField")
+    private static class TestObjectField implements Serializable {
+        /** */
+        final int a;
+
+        /** */
+        final String b;
+
+        /**
+         * @param a A.
+         * @param b B.
+         */
+        private TestObjectField(int a, String b) {
+            this.a = a;
+            this.b = b;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            TestObjectField that = (TestObjectField)o;
+
+            return a == that.a && !(b != null ? !b.equals(that.b) : that.b != null);
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            int res = a;
+
+            res = 31 * res + (b != null ? b.hashCode() : 0);
+
+            return res;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return S.toString(TestObjectField.class, this);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
new file mode 100644
index 0000000..a9a7e7b
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
@@ -0,0 +1,343 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.Serializable;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Statement test.
+ */
+public class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** SQL query. */
+    private static final String SQL = "select * from Person where age > 30";
+
+    /** Connection. */
+    private Connection conn;
+
+    /** Statement. */
+    private Statement stmt;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+        cache.setIndexedTypes(
+            String.class, Person.class
+        );
+
+        cfg.setCacheConfiguration(cache);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        cfg.setOdbcConfiguration(new OdbcConfiguration());
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(3);
+
+        IgniteCache<String, Person> cache = grid(0).cache(DEFAULT_CACHE_NAME);
+
+        assert cache != null;
+
+        cache.put("p1", new Person(1, "John", "White", 25));
+        cache.put("p2", new Person(2, "Joe", "Black", 35));
+        cache.put("p3", new Person(3, "Mike", "Green", 40));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        conn = DriverManager.getConnection(URL);
+
+        conn.setSchema(DEFAULT_CACHE_NAME);
+
+        stmt = conn.createStatement();
+
+        assert stmt != null;
+        assert !stmt.isClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (stmt != null && !stmt.isClosed()) {
+            stmt.close();
+
+            assert stmt.isClosed();
+        }
+
+        conn.close();
+
+        assert stmt.isClosed();
+        assert conn.isClosed();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testExecuteQuery() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            int id = rs.getInt("id");
+
+            if (id == 2) {
+                assert "Joe".equals(rs.getString("firstName"));
+                assert "Black".equals(rs.getString("lastName"));
+                assert rs.getInt("age") == 35;
+            }
+            else if (id == 3) {
+                assert "Mike".equals(rs.getString("firstName"));
+                assert "Green".equals(rs.getString("lastName"));
+                assert rs.getInt("age") == 40;
+            }
+            else
+                assert false : "Wrong ID: " + id;
+
+            cnt++;
+        }
+
+        assert cnt == 2;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testExecute() throws Exception {
+        assert stmt.execute(SQL);
+
+        assert stmt.getUpdateCount() == -1 : "Update count must be -1 for SELECT query";
+
+        ResultSet rs = stmt.getResultSet();
+
+        assert rs != null;
+
+        assert stmt.getResultSet() == null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            int id = rs.getInt("id");
+
+            if (id == 2) {
+                assert "Joe".equals(rs.getString("firstName"));
+                assert "Black".equals(rs.getString("lastName"));
+                assert rs.getInt("age") == 35;
+            }
+            else if (id == 3) {
+                assert "Mike".equals(rs.getString("firstName"));
+                assert "Green".equals(rs.getString("lastName"));
+                assert rs.getInt("age") == 40;
+            }
+            else
+                assert false : "Wrong ID: " + id;
+
+            cnt++;
+        }
+
+        assert cnt == 2;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMaxRows() throws Exception {
+        stmt.setMaxRows(1);
+
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            int id = rs.getInt("id");
+
+            if (id == 2) {
+                assert "Joe".equals(rs.getString("firstName"));
+                assert "Black".equals(rs.getString("lastName"));
+                assert rs.getInt("age") == 35;
+            }
+            else if (id == 3) {
+                assert "Mike".equals(rs.getString("firstName"));
+                assert "Green".equals(rs.getString("lastName"));
+                assert rs.getInt("age") == 40;
+            }
+            else
+                assert false : "Wrong ID: " + id;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setMaxRows(0);
+
+        rs = stmt.executeQuery(SQL);
+
+        assert rs != null;
+
+        cnt = 0;
+
+        while (rs.next()) {
+            int id = rs.getInt("id");
+
+            if (id == 2) {
+                assert "Joe".equals(rs.getString("firstName"));
+                assert "Black".equals(rs.getString("lastName"));
+                assert rs.getInt("age") == 35;
+            }
+            else if (id == 3) {
+                assert "Mike".equals(rs.getString("firstName"));
+                assert "Green".equals(rs.getString("lastName"));
+                assert rs.getInt("age") == 40;
+            }
+            else
+                assert false : "Wrong ID: " + id;
+
+            cnt++;
+        }
+
+        assert cnt == 2;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCloseResultSet0() throws Exception {
+        ResultSet rs0 = stmt.executeQuery(SQL);
+        ResultSet rs1 = stmt.executeQuery(SQL);
+        ResultSet rs2 = stmt.executeQuery(SQL);
+
+        assert rs0.isClosed() : "ResultSet must be implicitly closed after re-execute statement";
+        assert rs1.isClosed() : "ResultSet must be implicitly closed after re-execute statement";
+
+        assert !rs2.isClosed() : "Last result set must be available";
+
+        stmt.close();
+
+        assert rs2.isClosed() : "ResultSet must be explicitly closed after close statement";
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCloseResultSet1() throws Exception {
+        stmt.execute(SQL);
+
+        ResultSet rs = stmt.getResultSet();
+
+        stmt.close();
+
+        assert rs.isClosed() : "ResultSet must be explicitly closed after close statement";
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCloseResultSetByConnectionClose() throws Exception {
+        ResultSet rs = stmt.executeQuery(SQL);
+
+        conn.close();
+
+        assert stmt.isClosed() : "Statement must be implicitly closed after close connection";
+        assert rs.isClosed() : "ResultSet must be implicitly closed after close connection";
+    }
+
+    /**
+     * Person.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Person implements Serializable {
+        /** ID. */
+        @QuerySqlField
+        private final int id;
+
+        /** First name. */
+        @QuerySqlField(index = false)
+        private final String firstName;
+
+        /** Last name. */
+        @QuerySqlField(index = false)
+        private final String lastName;
+
+        /** Age. */
+        @QuerySqlField
+        private final int age;
+
+        /**
+         * @param id ID.
+         * @param firstName First name.
+         * @param lastName Last name.
+         * @param age Age.
+         */
+        private Person(int id, String firstName, String lastName, int age) {
+            assert !F.isEmpty(firstName);
+            assert !F.isEmpty(lastName);
+            assert age > 0;
+
+            this.id = id;
+            this.firstName = firstName;
+            this.lastName = lastName;
+            this.age = age;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
index df4929c..345bbc3 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
@@ -385,6 +385,9 @@ public class IgniteJdbcDriver implements Driver {
 
     /** {@inheritDoc} */
     @Override public Connection connect(String url, Properties props) throws SQLException {
+        if (!acceptsURL(url))
+            return null;
+
         if (!parseUrl(url, props))
             throw new SQLException("URL is invalid: " + url);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
index 19e1edd..5c04701 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
@@ -31,7 +31,7 @@ import org.apache.ignite.cache.affinity.AffinityKey;
 import org.apache.ignite.configuration.OdbcConfiguration;
 import org.apache.ignite.internal.IgniteVersionUtils;
 import org.apache.ignite.internal.jdbc.JdbcDriverPropertyInfo;
-import org.apache.ignite.internal.jdbc.thin.JdbcConnection;
+import org.apache.ignite.internal.jdbc.thin.JdbcThinConnection;
 
 /**
  * JDBC driver thin implementation for In-Memory Data Grid.
@@ -179,10 +179,13 @@ public class IgniteJdbcThinDriver implements Driver {
 
     /** {@inheritDoc} */
     @Override public Connection connect(String url, Properties props) throws SQLException {
+        if (!acceptsURL(url))
+            return null;
+
         if (!parseUrl(url, props))
             throw new SQLException("URL is invalid: " + url);
 
-        return new JdbcConnection(url, props);
+        return new JdbcThinConnection(url, props);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcConnection.java
deleted file mode 100644
index 25d62b4..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcConnection.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.jdbc.thin;
-
-import java.sql.Array;
-import java.sql.Blob;
-import java.sql.CallableStatement;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.NClob;
-import java.sql.PreparedStatement;
-import java.sql.SQLClientInfoException;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.sql.SQLWarning;
-import java.sql.SQLXML;
-import java.sql.Savepoint;
-import java.sql.Statement;
-import java.sql.Struct;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.Executor;
-import java.util.logging.Logger;
-
-import static java.sql.ResultSet.CONCUR_READ_ONLY;
-import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
-import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
-import static org.apache.ignite.IgniteJdbcThinDriver.PROP_DISTRIBUTED_JOINS;
-import static org.apache.ignite.IgniteJdbcThinDriver.PROP_ENFORCE_JOIN_ORDER;
-import static org.apache.ignite.IgniteJdbcThinDriver.PROP_HOST;
-import static org.apache.ignite.IgniteJdbcThinDriver.PROP_PORT;
-
-/**
- * JDBC connection implementation.
- *
- * See documentation of {@link org.apache.ignite.IgniteJdbcThinDriver} for details.
- */
-public class JdbcConnection implements Connection {
-    /** Logger. */
-    private static final Logger LOG = Logger.getLogger(JdbcConnection.class.getName());
-
-    /** Cache name. */
-    private String schemaName;
-
-    /** Closed flag. */
-    private boolean closed;
-
-    /** Current transaction isolation. */
-    private int txIsolation;
-
-    /** Auto commit flag. */
-    private boolean autoCommit;
-
-    /** Current transaction holdability. */
-    private int holdability;
-
-    /** Timeout. */
-    private int timeout;
-
-    /** Ignite endpoint. */
-    private JdbcTcpIo cliIo;
-
-    /**
-     * Creates new connection.
-     *
-     * @param url Connection URL.
-     * @param props Additional properties.
-     * @throws SQLException In case Ignite client failed to start.
-     */
-    public JdbcConnection(String url, Properties props) throws SQLException {
-        assert url != null;
-        assert props != null;
-
-        holdability = HOLD_CURSORS_OVER_COMMIT;
-        autoCommit = true;
-        txIsolation = Connection.TRANSACTION_NONE;
-
-        boolean distributedJoins = Boolean.parseBoolean(props.getProperty(PROP_DISTRIBUTED_JOINS, "false"));
-        boolean enforceJoinOrder = Boolean.parseBoolean(props.getProperty(PROP_ENFORCE_JOIN_ORDER, "false"));
-
-        String host = props.getProperty(PROP_HOST);
-        String portStr = props.getProperty(PROP_PORT);
-
-        try {
-            int port = Integer.parseInt(portStr);
-
-            if (port <= 0 || port > 0xFFFF)
-                throw new SQLException("Invalid port: " + portStr);
-        }
-        catch (NumberFormatException e) {
-            throw new SQLException("Invalid port: " + portStr, e);
-        }
-
-        if (host == null || host.trim().isEmpty())
-            throw new SQLException("Host name is empty.");
-
-        String endpoint = host.trim() + ":" + portStr.trim();
-
-        try {
-            cliIo = new JdbcTcpIo(endpoint, distributedJoins, enforceJoinOrder);
-
-            cliIo.start();
-        }
-        catch (Exception e) {
-            cliIo.close();
-
-            throw new SQLException("Failed to connect to Ignite cluster [host=" + host + ", port=" + portStr + ']', e);
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public Statement createStatement() throws SQLException {
-        return createStatement(TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT);
-    }
-
-    /** {@inheritDoc} */
-    @Override public Statement createStatement(int resSetType, int resSetConcurrency) throws SQLException {
-        return createStatement(resSetType, resSetConcurrency, HOLD_CURSORS_OVER_COMMIT);
-    }
-
-    /** {@inheritDoc} */
-    @Override public Statement createStatement(int resSetType, int resSetConcurrency,
-        int resSetHoldability) throws SQLException {
-        ensureNotClosed();
-
-        checkCursorOptions(resSetType, resSetConcurrency, resSetHoldability);
-
-        return null;
-    }
-
-    /** {@inheritDoc} */
-    @Override public PreparedStatement prepareStatement(String sql) throws SQLException {
-        return prepareStatement(sql, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT);
-    }
-
-    /** {@inheritDoc} */
-    @Override public PreparedStatement prepareStatement(String sql, int resSetType,
-        int resSetConcurrency) throws SQLException {
-        return prepareStatement(sql, resSetType, resSetConcurrency, HOLD_CURSORS_OVER_COMMIT);
-    }
-
-    /** {@inheritDoc} */
-    @Override public PreparedStatement prepareStatement(String sql, int resSetType, int resSetConcurrency,
-        int resSetHoldability) throws SQLException {
-        ensureNotClosed();
-
-        checkCursorOptions(resSetType, resSetConcurrency, resSetHoldability);
-
-        return null;
-    }
-
-    /**
-     * @param resSetType Cursor option.
-     * @param resSetConcurrency Cursor option.
-     * @param resSetHoldability Cursor option.
-     * @throws SQLException If options unsupported.
-     */
-    private void checkCursorOptions(int resSetType, int resSetConcurrency,
-        int resSetHoldability) throws SQLException {
-        if (resSetType != TYPE_FORWARD_ONLY)
-            throw new SQLFeatureNotSupportedException("Invalid result set type (only forward is supported.)");
-
-        if (resSetConcurrency != CONCUR_READ_ONLY)
-            throw new SQLFeatureNotSupportedException("Invalid concurrency (updates are not supported).");
-
-        if (resSetHoldability != HOLD_CURSORS_OVER_COMMIT)
-            LOG.warning("Transactions are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public CallableStatement prepareCall(String sql) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Callable functions are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public CallableStatement prepareCall(String sql, int resSetType, int resSetConcurrency)
-        throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Callable functions are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public String nativeSQL(String sql) throws SQLException {
-        ensureNotClosed();
-
-        return sql;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setAutoCommit(boolean autoCommit) throws SQLException {
-        ensureNotClosed();
-
-        this.autoCommit = autoCommit;
-
-        if (!autoCommit)
-            LOG.warning("Transactions are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean getAutoCommit() throws SQLException {
-        ensureNotClosed();
-
-        if (!autoCommit)
-            LOG.warning("Transactions are not supported.");
-
-        return autoCommit;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void commit() throws SQLException {
-        ensureNotClosed();
-
-        LOG.warning("Transactions are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public void rollback() throws SQLException {
-        ensureNotClosed();
-
-        LOG.warning("Transactions are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public void close() throws SQLException {
-        if (closed)
-            return;
-
-        closed = true;
-
-        cliIo.close();
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isClosed() throws SQLException {
-        return closed;
-    }
-
-    /** {@inheritDoc} */
-    @Override public DatabaseMetaData getMetaData() throws SQLException {
-        ensureNotClosed();
-
-        return null;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setReadOnly(boolean readOnly) throws SQLException {
-        ensureNotClosed();
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isReadOnly() throws SQLException {
-        ensureNotClosed();
-
-        return true;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setCatalog(String catalog) throws SQLException {
-        ensureNotClosed();
-    }
-
-    /** {@inheritDoc} */
-    @Override public String getCatalog() throws SQLException {
-        ensureNotClosed();
-
-        return null;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setTransactionIsolation(int level) throws SQLException {
-        ensureNotClosed();
-
-        LOG.warning("Transactions are not supported.");
-
-        txIsolation = level;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int getTransactionIsolation() throws SQLException {
-        ensureNotClosed();
-
-        LOG.warning("Transactions are not supported.");
-
-        return txIsolation;
-    }
-
-    /** {@inheritDoc} */
-    @Override public SQLWarning getWarnings() throws SQLException {
-        ensureNotClosed();
-
-        return null;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void clearWarnings() throws SQLException {
-        ensureNotClosed();
-    }
-
-    /** {@inheritDoc} */
-    @Override public Map<String, Class<?>> getTypeMap() throws SQLException {
-        throw new SQLFeatureNotSupportedException("Types mapping is not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Types mapping is not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setHoldability(int holdability) throws SQLException {
-        ensureNotClosed();
-
-        if (holdability != HOLD_CURSORS_OVER_COMMIT)
-            LOG.warning("Transactions are not supported.");
-
-        this.holdability = holdability;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int getHoldability() throws SQLException {
-        ensureNotClosed();
-
-        return holdability;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Savepoint setSavepoint() throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public Savepoint setSavepoint(String name) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public void rollback(Savepoint savepoint) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public CallableStatement prepareCall(String sql, int resSetType, int resSetConcurrency,
-        int resSetHoldability) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Callable functions are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Auto generated keys are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public PreparedStatement prepareStatement(String sql, int[] colIndexes) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Auto generated keys are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public PreparedStatement prepareStatement(String sql, String[] colNames) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("Auto generated keys are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public Clob createClob() throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public Blob createBlob() throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public NClob createNClob() throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public SQLXML createSQLXML() throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isValid(int timeout) throws SQLException {
-        if (timeout < 0)
-            throw new SQLException("Invalid timeout: " + timeout);
-
-        return !closed;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setClientInfo(String name, String val) throws SQLClientInfoException {
-        throw new UnsupportedOperationException("Client info is not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setClientInfo(Properties props) throws SQLClientInfoException {
-        throw new UnsupportedOperationException("Client info is not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public String getClientInfo(String name) throws SQLException {
-        ensureNotClosed();
-
-        return null;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Properties getClientInfo() throws SQLException {
-        ensureNotClosed();
-
-        return new Properties();
-    }
-
-    /** {@inheritDoc} */
-    @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @Override public Struct createStruct(String typeName, Object[] attrs) throws SQLException {
-        ensureNotClosed();
-
-        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
-    }
-
-    /** {@inheritDoc} */
-    @SuppressWarnings("unchecked")
-    @Override public <T> T unwrap(Class<T> iface) throws SQLException {
-        if (!isWrapperFor(iface))
-            throw new SQLException("Connection is not a wrapper for " + iface.getName());
-
-        return (T)this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isWrapperFor(Class<?> iface) throws SQLException {
-        return iface != null && iface == Connection.class;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setSchema(String schema) throws SQLException {
-        schemaName = schema;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String getSchema() throws SQLException {
-        return schemaName;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void abort(Executor executor) throws SQLException {
-        close();
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setNetworkTimeout(Executor executor, int ms) throws SQLException {
-        if (ms < 0)
-            throw new IllegalArgumentException("Timeout is below zero: " + ms);
-
-        timeout = ms;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int getNetworkTimeout() throws SQLException {
-        return timeout;
-    }
-
-    /**
-     * Ensures that connection is not closed.
-     *
-     * @throws SQLException If connection is closed.
-     */
-    private void ensureNotClosed() throws SQLException {
-        if (closed)
-            throw new SQLException("Connection is closed.");
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcTcpIo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcTcpIo.java
deleted file mode 100644
index 4946b41..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcTcpIo.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.jdbc.thin;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.util.logging.Logger;
-import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.internal.binary.BinaryReaderExImpl;
-import org.apache.ignite.internal.binary.BinaryWriterExImpl;
-import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream;
-import org.apache.ignite.internal.binary.streams.BinaryHeapOutputStream;
-import org.apache.ignite.internal.processors.odbc.SqlListenerProtocolVersion;
-import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
-import org.apache.ignite.internal.processors.odbc.SqlListenerNioListener;
-import org.apache.ignite.internal.util.ipc.IpcEndpoint;
-import org.apache.ignite.internal.util.ipc.IpcEndpointFactory;
-import org.apache.ignite.internal.util.typedef.internal.U;
-
-/**
- * JDBC IO layer implementation based on blocking IPC streams.
- */
-public class JdbcTcpIo {
-    /** Current version. */
-    private static final SqlListenerProtocolVersion CURRENT_VER = SqlListenerProtocolVersion.create(2, 1, 0);
-
-    /** Initial output stream capacity. */
-    private static final int HANDSHAKE_MSG_SIZE = 10;
-
-    /** Logger. */
-    private static final Logger log = Logger.getLogger(JdbcTcpIo.class.getName());
-
-    /** Server endpoint address. */
-    private final String endpointAddr;
-
-    /** Endpoint. */
-    private IpcEndpoint endpoint;
-
-    /** Output stream. */
-    private BufferedOutputStream out;
-
-    /** Input stream. */
-    private BufferedInputStream in;
-
-    /** Distributed joins. */
-    private boolean distributedJoins;
-
-    /** Enforce join order. */
-    private boolean enforceJoinOrder;
-
-    /** Closed flag. */
-    private boolean closed;
-
-    /**
-     * @param endpointAddr Endpoint.
-     * @param distributedJoins Distributed joins flag.
-     * @param enforceJoinOrder Enforce join order flag.
-     */
-    JdbcTcpIo(String endpointAddr, boolean distributedJoins, boolean enforceJoinOrder) {
-        assert endpointAddr != null;
-
-        this.endpointAddr = endpointAddr;
-        this.distributedJoins = distributedJoins;
-        this.enforceJoinOrder= enforceJoinOrder;
-    }
-
-    /**
-     * @throws IgniteCheckedException On error.
-     * @throws IOException On IO error in handshake.
-     */
-    public void start() throws IgniteCheckedException, IOException {
-        endpoint = IpcEndpointFactory.connectEndpoint(endpointAddr, null);
-
-        out = new BufferedOutputStream(endpoint.outputStream());
-        in = new BufferedInputStream(endpoint.inputStream());
-
-        handshake();
-    }
-
-    /**
-     * @throws IOException On error.
-     * @throws IgniteCheckedException On error.
-     */
-    public void handshake() throws IOException, IgniteCheckedException {
-        BinaryWriterExImpl writer = new BinaryWriterExImpl(null, new BinaryHeapOutputStream(HANDSHAKE_MSG_SIZE),
-            null, null);
-
-        writer.writeByte((byte)SqlListenerRequest.HANDSHAKE);
-
-        writer.writeShort(CURRENT_VER.major());
-        writer.writeShort(CURRENT_VER.minor());
-        writer.writeShort(CURRENT_VER.maintenance());
-
-        writer.writeByte(SqlListenerNioListener.JDBC_CLIENT);
-
-        writer.writeBoolean(distributedJoins);
-        writer.writeBoolean(enforceJoinOrder);
-
-        send(writer.array());
-
-        BinaryReaderExImpl reader = new BinaryReaderExImpl(null, new BinaryHeapInputStream(read()),
-            null, null, false);
-
-        boolean accepted = reader.readBoolean();
-
-        if (accepted)
-            return;
-
-        short maj = reader.readShort();
-        short min = reader.readShort();
-        short maintenance = reader.readShort();
-
-        String err = reader.readString();
-
-        SqlListenerProtocolVersion ver = SqlListenerProtocolVersion.create(maj, min, maintenance);
-
-        throw new IgniteCheckedException("Handshake failed [driverProtocolVer=" + CURRENT_VER +
-            ", remoteNodeProtocolVer=" + ver + ", err=" + err + ']');
-    }
-
-    /**
-     * @param req ODBC request.
-     * @throws IOException On error.
-     */
-    private void send(byte[] req) throws IOException {
-        int size = req.length;
-
-        out.write(size & 0xFF);
-        out.write((size >> 8) & 0xFF);
-        out.write((size >> 16) & 0xFF);
-        out.write((size >> 24) & 0xFF);
-
-        out.write(req);
-
-        out.flush();
-    }
-
-    /**
-     * @return Bytes of a response from server.
-     * @throws IOException On error.
-     * @throws IgniteCheckedException On error.
-     */
-    private byte[] read() throws IOException, IgniteCheckedException {
-        byte[] sizeBytes = read(4);
-
-        int msgSize  = (((0xFF & sizeBytes[3]) << 24) | ((0xFF & sizeBytes[2]) << 16)
-            | ((0xFF & sizeBytes[1]) << 8) + (0xFF & sizeBytes[0]));
-
-        return read(msgSize);
-    }
-
-    /**
-     * @param size Count of bytes to read from stream.
-     * @return Read bytes.
-     * @throws IOException On error.
-     * @throws IgniteCheckedException On error.
-     */
-    private byte [] read(int size) throws IOException, IgniteCheckedException {
-        int off = 0;
-
-        byte[] data = new byte[size];
-
-        while (off != size) {
-            int res = in.read(data, off, size - off);
-
-            if (res == -1)
-                throw new IgniteCheckedException("Failed to read incoming message (not enough data).");
-
-            off += res;
-        }
-
-        return data;
-    }
-
-    /**
-     * Close the client IO.
-     */
-    public void close() {
-        if (closed)
-            return;
-
-        // Clean up resources.
-        U.closeQuiet(out);
-        U.closeQuiet(in);
-
-        if (endpoint != null)
-            endpoint.close();
-
-        closed = true;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
new file mode 100644
index 0000000..4ba7557
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
@@ -0,0 +1,545 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+import java.util.logging.Logger;
+
+import static java.sql.ResultSet.CONCUR_READ_ONLY;
+import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
+import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
+import static org.apache.ignite.IgniteJdbcThinDriver.PROP_DISTRIBUTED_JOINS;
+import static org.apache.ignite.IgniteJdbcThinDriver.PROP_ENFORCE_JOIN_ORDER;
+import static org.apache.ignite.IgniteJdbcThinDriver.PROP_HOST;
+import static org.apache.ignite.IgniteJdbcThinDriver.PROP_PORT;
+
+/**
+ * JDBC connection implementation.
+ *
+ * See documentation of {@link org.apache.ignite.IgniteJdbcThinDriver} for details.
+ */
+public class JdbcThinConnection implements Connection {
+    /** Logger. */
+    private static final Logger LOG = Logger.getLogger(JdbcThinConnection.class.getName());
+
+    /** Schema name. */
+    private String schemaName;
+
+    /** Closed flag. */
+    private boolean closed;
+
+    /** Current transaction isolation. */
+    private int txIsolation;
+
+    /** Auto commit flag. */
+    private boolean autoCommit;
+
+    /** Current transaction holdability. */
+    private int holdability;
+
+    /** Timeout. */
+    private int timeout;
+
+    /** Ignite endpoint. */
+    private JdbcThinTcpIo cliIo;
+
+    /**
+     * Creates new connection.
+     *
+     * @param url Connection URL.
+     * @param props Additional properties.
+     * @throws SQLException In case Ignite client failed to start.
+     */
+    public JdbcThinConnection(String url, Properties props) throws SQLException {
+        assert url != null;
+        assert props != null;
+
+        holdability = HOLD_CURSORS_OVER_COMMIT;
+        autoCommit = true;
+        txIsolation = Connection.TRANSACTION_NONE;
+
+        boolean distributedJoins = Boolean.parseBoolean(props.getProperty(PROP_DISTRIBUTED_JOINS, "false"));
+        boolean enforceJoinOrder = Boolean.parseBoolean(props.getProperty(PROP_ENFORCE_JOIN_ORDER, "false"));
+
+        String host = props.getProperty(PROP_HOST);
+        String portStr = props.getProperty(PROP_PORT);
+
+        try {
+            int port = Integer.parseInt(portStr);
+
+            if (port <= 0 || port > 0xFFFF)
+                throw new SQLException("Invalid port: " + portStr);
+        }
+        catch (NumberFormatException e) {
+            throw new SQLException("Invalid port: " + portStr, e);
+        }
+
+        if (host == null || host.trim().isEmpty())
+            throw new SQLException("Host name is empty.");
+
+        String endpoint = host.trim() + ":" + portStr.trim();
+
+        try {
+            cliIo = new JdbcThinTcpIo(endpoint, distributedJoins, enforceJoinOrder);
+
+            cliIo.start();
+        }
+        catch (Exception e) {
+            cliIo.close();
+
+            throw new SQLException("Failed to connect to Ignite cluster [host=" + host + ", port=" + portStr + ']', e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public Statement createStatement() throws SQLException {
+        return createStatement(TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Statement createStatement(int resSetType, int resSetConcurrency) throws SQLException {
+        return createStatement(resSetType, resSetConcurrency, HOLD_CURSORS_OVER_COMMIT);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Statement createStatement(int resSetType, int resSetConcurrency,
+        int resSetHoldability) throws SQLException {
+        ensureNotClosed();
+
+        checkCursorOptions(resSetType, resSetConcurrency, resSetHoldability);
+
+        JdbcThinStatement stmt  = new JdbcThinStatement(this);
+
+        if (timeout > 0)
+            stmt.timeout(timeout);
+
+        return stmt;
+    }
+
+    /** {@inheritDoc} */
+    @Override public PreparedStatement prepareStatement(String sql) throws SQLException {
+        return prepareStatement(sql, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT);
+    }
+
+    /** {@inheritDoc} */
+    @Override public PreparedStatement prepareStatement(String sql, int resSetType,
+        int resSetConcurrency) throws SQLException {
+        return prepareStatement(sql, resSetType, resSetConcurrency, HOLD_CURSORS_OVER_COMMIT);
+    }
+
+    /** {@inheritDoc} */
+    @Override public PreparedStatement prepareStatement(String sql, int resSetType, int resSetConcurrency,
+        int resSetHoldability) throws SQLException {
+        ensureNotClosed();
+
+        checkCursorOptions(resSetType, resSetConcurrency, resSetHoldability);
+
+        JdbcThinPreparedStatement stmt = new JdbcThinPreparedStatement(this, sql);
+
+        if (timeout > 0)
+            stmt.timeout(timeout);
+
+        return stmt;
+    }
+
+    /**
+     * @param resSetType Cursor option.
+     * @param resSetConcurrency Cursor option.
+     * @param resSetHoldability Cursor option.
+     * @throws SQLException If options unsupported.
+     */
+    private void checkCursorOptions(int resSetType, int resSetConcurrency,
+        int resSetHoldability) throws SQLException {
+        if (resSetType != TYPE_FORWARD_ONLY)
+            throw new SQLFeatureNotSupportedException("Invalid result set type (only forward is supported.)");
+
+        if (resSetConcurrency != CONCUR_READ_ONLY)
+            throw new SQLFeatureNotSupportedException("Invalid concurrency (updates are not supported).");
+
+        if (resSetHoldability != HOLD_CURSORS_OVER_COMMIT)
+            LOG.warning("Transactions are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public CallableStatement prepareCall(String sql) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Callable functions are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public CallableStatement prepareCall(String sql, int resSetType, int resSetConcurrency)
+        throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Callable functions are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public String nativeSQL(String sql) throws SQLException {
+        ensureNotClosed();
+
+        return sql;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setAutoCommit(boolean autoCommit) throws SQLException {
+        ensureNotClosed();
+
+        this.autoCommit = autoCommit;
+
+        if (!autoCommit)
+            LOG.warning("Transactions are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean getAutoCommit() throws SQLException {
+        ensureNotClosed();
+
+        if (!autoCommit)
+            LOG.warning("Transactions are not supported.");
+
+        return autoCommit;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void commit() throws SQLException {
+        ensureNotClosed();
+
+        LOG.warning("Transactions are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void rollback() throws SQLException {
+        ensureNotClosed();
+
+        LOG.warning("Transactions are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void close() throws SQLException {
+        if (isClosed())
+            return;
+
+        closed = true;
+
+        cliIo.close();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isClosed() throws SQLException {
+        return closed;
+    }
+
+    /** {@inheritDoc} */
+    @Override public DatabaseMetaData getMetaData() throws SQLException {
+        ensureNotClosed();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setReadOnly(boolean readOnly) throws SQLException {
+        ensureNotClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isReadOnly() throws SQLException {
+        ensureNotClosed();
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setCatalog(String catalog) throws SQLException {
+        ensureNotClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getCatalog() throws SQLException {
+        ensureNotClosed();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setTransactionIsolation(int level) throws SQLException {
+        ensureNotClosed();
+
+        LOG.warning("Transactions are not supported.");
+
+        txIsolation = level;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getTransactionIsolation() throws SQLException {
+        ensureNotClosed();
+
+        LOG.warning("Transactions are not supported.");
+
+        return txIsolation;
+    }
+
+    /** {@inheritDoc} */
+    @Override public SQLWarning getWarnings() throws SQLException {
+        ensureNotClosed();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clearWarnings() throws SQLException {
+        ensureNotClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map<String, Class<?>> getTypeMap() throws SQLException {
+        throw new SQLFeatureNotSupportedException("Types mapping is not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Types mapping is not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setHoldability(int holdability) throws SQLException {
+        ensureNotClosed();
+
+        if (holdability != HOLD_CURSORS_OVER_COMMIT)
+            LOG.warning("Transactions are not supported.");
+
+        this.holdability = holdability;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getHoldability() throws SQLException {
+        ensureNotClosed();
+
+        return holdability;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Savepoint setSavepoint() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Savepoint setSavepoint(String name) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void rollback(Savepoint savepoint) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Savepoints are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public CallableStatement prepareCall(String sql, int resSetType, int resSetConcurrency,
+        int resSetHoldability) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Callable functions are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Auto generated keys are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public PreparedStatement prepareStatement(String sql, int[] colIndexes) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Auto generated keys are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public PreparedStatement prepareStatement(String sql, String[] colNames) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("Auto generated keys are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Clob createClob() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Blob createBlob() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public NClob createNClob() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public SQLXML createSQLXML() throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isValid(int timeout) throws SQLException {
+        if (timeout < 0)
+            throw new SQLException("Invalid timeout: " + timeout);
+
+        return !closed;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setClientInfo(String name, String val) throws SQLClientInfoException {
+        throw new UnsupportedOperationException("Client info is not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setClientInfo(Properties props) throws SQLClientInfoException {
+        throw new UnsupportedOperationException("Client info is not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getClientInfo(String name) throws SQLException {
+        ensureNotClosed();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Properties getClientInfo() throws SQLException {
+        ensureNotClosed();
+
+        return new Properties();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Struct createStruct(String typeName, Object[] attrs) throws SQLException {
+        ensureNotClosed();
+
+        throw new SQLFeatureNotSupportedException("SQL-specific types are not supported.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> T unwrap(Class<T> iface) throws SQLException {
+        if (!isWrapperFor(iface))
+            throw new SQLException("Connection is not a wrapper for " + iface.getName());
+
+        return (T)this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        return iface != null && iface.isAssignableFrom(JdbcThinConnection.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setSchema(String schema) throws SQLException {
+        schemaName = schema;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSchema() throws SQLException {
+        return schemaName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void abort(Executor executor) throws SQLException {
+        close();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setNetworkTimeout(Executor executor, int ms) throws SQLException {
+        if (ms < 0)
+            throw new IllegalArgumentException("Timeout is below zero: " + ms);
+
+        timeout = ms;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getNetworkTimeout() throws SQLException {
+        return timeout;
+    }
+
+    /**
+     * Ensures that connection is not closed.
+     *
+     * @throws SQLException If connection is closed.
+     */
+    private void ensureNotClosed() throws SQLException {
+        if (closed)
+            throw new SQLException("Connection is closed.");
+    }
+
+    /**
+     * @return Ignite endpoint and I/O protocol.
+     */
+    JdbcThinTcpIo cliIo() {
+        return cliIo;
+    }
+}


[04/50] [abbrv] ignite git commit: IGNITE-4509: Send unicast SQL request when partition can be deduced from the query. This closes #1916.

Posted by sb...@apache.org.
IGNITE-4509: Send unicast SQL request when partition can be deduced from the query. This closes #1916.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/fbf0e353
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/fbf0e353
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/fbf0e353

Branch: refs/heads/ignite-5075
Commit: fbf0e35371949309f07105331f3bafb54da6c29c
Parents: 79d45e3
Author: Sergey Kalashnikov <sk...@gridgain.com>
Authored: Fri Jun 2 14:20:37 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 14:20:37 2017 +0300

----------------------------------------------------------------------
 .../cache/query/GridCacheSqlQuery.java          |  23 +
 .../cache/query/CacheQueryPartitionInfo.java    | 110 ++++
 .../cache/query/GridCacheTwoStepQuery.java      |  18 +
 .../processors/query/h2/IgniteH2Indexing.java   |  50 +-
 .../query/h2/sql/GridSqlQuerySplitter.java      | 228 +++++++-
 .../processors/query/IgniteSqlRoutingTest.java  | 552 +++++++++++++++++++
 .../IgniteCacheQuerySelfTestSuite.java          |   2 +
 7 files changed, 976 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/fbf0e353/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlQuery.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlQuery.java
index 780e462..d3746f3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlQuery.java
@@ -69,6 +69,11 @@ public class GridCacheSqlQuery implements Message {
     /** Single node to execute the query on. */
     private UUID node;
 
+    /** Derived partition info. */
+    @GridToStringInclude
+    @GridDirectTransient
+    private transient Object[] derivedPartitions;
+
     /**
      * For {@link Message}.
      */
@@ -253,6 +258,7 @@ public class GridCacheSqlQuery implements Message {
         cp.paramIdxs = paramIdxs;
         cp.sort = sort;
         cp.partitioned = partitioned;
+        cp.derivedPartitions = derivedPartitions;
 
         return cp;
     }
@@ -324,4 +330,21 @@ public class GridCacheSqlQuery implements Message {
 
         return res;
     }
+
+    /**
+     * @return Derived partitions.
+     */
+    public Object[] derivedPartitions() {
+        return derivedPartitions;
+    }
+
+    /**
+     * @param derivedPartitions Derived partitions.
+     * @return {@code this}.
+     */
+    public GridCacheSqlQuery derivedPartitions(Object[] derivedPartitions) {
+        this.derivedPartitions = derivedPartitions;
+
+        return this;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/fbf0e353/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/CacheQueryPartitionInfo.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/CacheQueryPartitionInfo.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/CacheQueryPartitionInfo.java
new file mode 100644
index 0000000..1329d5c
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/CacheQueryPartitionInfo.java
@@ -0,0 +1,110 @@
+/*
+ * 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.processors.cache.query;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * Holds the partition calculation info extracted from a query.
+ * The query may have several such items associated with it.
+ *
+ * The query may contain expressions containing key or affinity key.
+ * Such expressions can be used as hints to derive small isolated set
+ * of partitions the query needs to run on.
+ *
+ * In case expression contains constant (e.g. _key = 100), the partition
+ * can be calculated right away and saved into cache along with the query.
+ *
+ * In case expression has a parameter (e.g. _key = ?), the effective
+ * partition varies with each run of the query. Hence, instead of partition,
+ * one must store the info required to calculate partition.
+ *
+ * The given class holds the required info, so that effective partition
+ * can be calculated during query parameter binding.
+ */
+public class CacheQueryPartitionInfo {
+    /** */
+    private int partId;
+
+    /** */
+    private String cacheName;
+
+    /** */
+    private int paramIdx;
+
+    /**
+     * @param partId Partition id, or -1 if parameter binding required.
+     * @param cacheName Cache name required for partition calculation.
+     * @param paramIdx Query parameter index required for partition calculation.
+     */
+    public CacheQueryPartitionInfo(int partId, String cacheName, int paramIdx) {
+        this.partId = partId;
+        this.cacheName = cacheName;
+        this.paramIdx = paramIdx;
+    }
+
+    /**
+     * @return Partition id, or -1 if parameter binding is required to calculate partition.
+     */
+    public int partition() {
+        return partId;
+    }
+
+    /**
+     * @return Cache name required for partition calculation.
+     */
+    public String cacheName() {
+        return cacheName;
+    }
+
+    /**
+     * @return Query parameter index required for partition calculation.
+     */
+    public int paramIdx() {
+        return paramIdx;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        return partId ^ paramIdx ^ (cacheName == null ? 0 : cacheName.hashCode());
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (!(obj instanceof CacheQueryPartitionInfo))
+            return false;
+
+        CacheQueryPartitionInfo other = (CacheQueryPartitionInfo)obj;
+
+        if (partId >= 0)
+            return partId == other.partId;
+
+        if (other.cacheName == null)
+            return false;
+
+        return other.cacheName.equals(cacheName) && other.paramIdx == paramIdx;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(CacheQueryPartitionInfo.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/fbf0e353/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
index 9e9a875..24958af 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
@@ -62,6 +62,9 @@ public class GridCacheTwoStepQuery {
     /** */
     private boolean local;
 
+    /** */
+    private CacheQueryPartitionInfo[] derivedPartitions;
+
     /**
      * @param originalSql Original query SQL.
      * @param tbls Tables in query.
@@ -210,6 +213,20 @@ public class GridCacheTwoStepQuery {
     }
 
     /**
+     * @return Query derived partitions info.
+     */
+    public CacheQueryPartitionInfo[] derivedPartitions() {
+        return this.derivedPartitions;
+    }
+
+    /**
+     * @param derivedPartitions Query derived partitions info.
+     */
+    public void derivedPartitions(CacheQueryPartitionInfo[] derivedPartitions) {
+        this.derivedPartitions = derivedPartitions;
+    }
+
+    /**
      * @return Copy.
      */
     public GridCacheTwoStepQuery copy() {
@@ -222,6 +239,7 @@ public class GridCacheTwoStepQuery {
         cp.skipMergeTbl = skipMergeTbl;
         cp.pageSize = pageSize;
         cp.distributedJoins = distributedJoins;
+        cp.derivedPartitions = derivedPartitions;
 
         for (int i = 0; i < mapQrys.size(); i++)
             cp.mapQrys.add(mapQrys.get(i).copy());

http://git-wip-us.apache.org/repos/asf/ignite/blob/fbf0e353/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 50c8e41..12addbd 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -73,6 +73,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedExceptio
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
 import org.apache.ignite.internal.processors.cache.database.CacheDataRow;
 import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO;
+import org.apache.ignite.internal.processors.cache.query.CacheQueryPartitionInfo;
 import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMarshallable;
 import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
 import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
@@ -1387,9 +1388,20 @@ public class IgniteH2Indexing implements GridQueryIndexing {
         if (cancel == null)
             cancel = new GridQueryCancel();
 
+        int partitions[] = qry.getPartitions();
+
+        if (partitions == null && twoStepQry.derivedPartitions() != null) {
+            try {
+                partitions = calculateQueryPartitions(twoStepQry.derivedPartitions(), qry.getArgs());
+            } catch (IgniteCheckedException e) {
+                throw new CacheException("Failed to calculate derived partitions: [qry=" + sqlQry + ", params=" +
+                    Arrays.deepToString(qry.getArgs()) + "]", e);
+            }
+        }
+
         QueryCursorImpl<List<?>> cursor = new QueryCursorImpl<>(
             runQueryTwoStep(schemaName, twoStepQry, keepBinary, enforceJoinOrder, qry.getTimeout(), cancel,
-                qry.getArgs(), qry.getPartitions()), cancel);
+                qry.getArgs(), partitions), cancel);
 
         cursor.fieldsMeta(meta);
 
@@ -2245,6 +2257,42 @@ public class IgniteH2Indexing implements GridQueryIndexing {
         rdcQryExec.onDisconnected(reconnectFut);
     }
 
+    /**
+     * Bind query parameters and calculate partitions derived from the query.
+     *
+     * @return Partitions.
+     */
+    private int[] calculateQueryPartitions(CacheQueryPartitionInfo[] partInfoList, Object[] params)
+        throws IgniteCheckedException {
+
+        ArrayList<Integer> list = new ArrayList<>(partInfoList.length);
+
+        for (CacheQueryPartitionInfo partInfo: partInfoList) {
+            int partId = partInfo.partition() < 0 ?
+                kernalContext().affinity().partition(partInfo.cacheName(), params[partInfo.paramIdx()]) :
+                partInfo.partition();
+
+            int i = 0;
+
+            while (i < list.size() && list.get(i) < partId)
+                i++;
+
+            if (i < list.size()) {
+                if (list.get(i) > partId)
+                    list.add(i, partId);
+            }
+            else
+                list.add(partId);
+        }
+
+        int[] result = new int[list.size()];
+
+        for (int i = 0; i < list.size(); i++)
+            result[i] = list.get(i);
+
+        return result;
+    }
+
     /** {@inheritDoc} */
     @Override public Collection<GridRunningQueryInfo> runningQueries(long duration) {
         Collection<GridRunningQueryInfo> res = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/ignite/blob/fbf0e353/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
index e2b82ab..1b9619e 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
@@ -34,11 +34,15 @@ import java.util.TreeSet;
 import javax.cache.CacheException;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.cache.query.CacheQueryPartitionInfo;
 import org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery;
 import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
 import org.apache.ignite.internal.processors.cache.query.QueryTable;
 import org.apache.ignite.internal.processors.query.h2.H2Utils;
 import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.S;
@@ -46,6 +50,7 @@ import org.h2.command.Prepared;
 import org.h2.command.dml.Query;
 import org.h2.command.dml.SelectUnion;
 import org.h2.jdbc.JdbcPreparedStatement;
+import org.h2.table.IndexColumn;
 import org.h2.value.Value;
 import org.jetbrains.annotations.Nullable;
 
@@ -116,13 +121,17 @@ public class GridSqlQuerySplitter {
     /** */
     private IdentityHashMap<GridSqlAst, GridSqlAlias> uniqueFromAliases = new IdentityHashMap<>();
 
+    /** */
+    private GridKernalContext ctx;
+
     /**
      * @param params Query parameters.
      * @param collocatedGrpBy If it is a collocated GROUP BY query.
      */
-    public GridSqlQuerySplitter(Object[] params, boolean collocatedGrpBy) {
+    public GridSqlQuerySplitter(Object[] params, boolean collocatedGrpBy, GridKernalContext ctx) {
         this.params = params;
         this.collocatedGrpBy = collocatedGrpBy;
+        this.ctx = ctx;
     }
 
     /**
@@ -182,7 +191,7 @@ public class GridSqlQuerySplitter {
 
         qry.explain(false);
 
-        GridSqlQuerySplitter splitter = new GridSqlQuerySplitter(params, collocatedGrpBy);
+        GridSqlQuerySplitter splitter = new GridSqlQuerySplitter(params, collocatedGrpBy, h2.kernalContext());
 
         // Normalization will generate unique aliases for all the table filters in FROM.
         // Also it will collect all tables and schemas from the query.
@@ -234,13 +243,16 @@ public class GridSqlQuerySplitter {
         twoStepQry.explain(explain);
         twoStepQry.distributedJoins(distributedJoins);
 
+        // all map queries must have non-empty derivedPartitions to use this feature.
+        twoStepQry.derivedPartitions(mergePartitionsFromMultipleQueries(twoStepQry.mapQueries()));
+
         return twoStepQry;
     }
 
     /**
      * @param qry Optimized and normalized query to split.
      */
-    private void splitQuery(GridSqlQuery qry) {
+    private void splitQuery(GridSqlQuery qry) throws IgniteCheckedException {
         // Create a fake parent AST element for the query to allow replacing the query in the parent by split.
         GridSqlSubquery fakeQryPrnt = new GridSqlSubquery(qry);
 
@@ -1016,7 +1028,7 @@ public class GridSqlQuerySplitter {
     /**
      * @param qrym Query model.
      */
-    private void splitQueryModel(QueryModel qrym) {
+    private void splitQueryModel(QueryModel qrym) throws IgniteCheckedException {
         switch (qrym.type) {
             case SELECT:
                 if (qrym.needSplit) {
@@ -1191,7 +1203,7 @@ public class GridSqlQuerySplitter {
     private void splitSelect(
         final GridSqlAst prnt,
         final int childIdx
-    ) {
+    ) throws IgniteCheckedException {
         if (++splitId > 99)
             throw new CacheException("Too complex query to process.");
 
@@ -1317,6 +1329,9 @@ public class GridSqlQuerySplitter {
         map.sortColumns(mapQry.sort());
         map.partitioned(hasPartitionedTables(mapQry));
 
+        if (map.isPartitioned())
+            map.derivedPartitions(derivePartitionsFromQuery(mapQry, ctx));
+
         mapSqlQrys.add(map);
     }
 
@@ -1985,8 +2000,209 @@ public class GridSqlQuerySplitter {
      * @return true if given type is fractional
      */
     private static boolean isFractionalType(int type) {
-       return type == Value.DECIMAL || type == Value.FLOAT || type == Value.DOUBLE;
+        return type == Value.DECIMAL || type == Value.FLOAT || type == Value.DOUBLE;
+    }
+
+    /**
+     * Checks if given query contains expressions over key or affinity key
+     * that make it possible to run it only on a small isolated
+     * set of partitions.
+     *
+     * @param qry Query.
+     * @param ctx Kernal context.
+     * @return Array of partitions, or {@code null} if none identified
+     */
+    private static CacheQueryPartitionInfo[] derivePartitionsFromQuery(GridSqlQuery qry, GridKernalContext ctx)
+        throws IgniteCheckedException {
+
+        if (!(qry instanceof GridSqlSelect))
+            return null;
+
+        GridSqlSelect select = (GridSqlSelect)qry;
+
+        // no joins support yet
+        if (select.from() == null || select.from().size() != 1)
+            return null;
+
+        return extractPartition(select.where(), ctx);
+    }
+
+    /**
+     * @param el AST element to start with.
+     * @param ctx Kernal context.
+     * @return Array of partition info objects, or {@code null} if none identified
+     */
+    private static CacheQueryPartitionInfo[] extractPartition(GridSqlAst el, GridKernalContext ctx)
+        throws IgniteCheckedException {
+
+        if (!(el instanceof GridSqlOperation))
+            return null;
+
+        GridSqlOperation op = (GridSqlOperation)el;
+
+        switch (op.operationType()) {
+            case EQUAL: {
+                CacheQueryPartitionInfo partInfo = extractPartitionFromEquality(op, ctx);
+
+                if (partInfo != null)
+                    return new CacheQueryPartitionInfo[] { partInfo };
+
+                return null;
+            }
+
+            case AND: {
+                assert op.size() == 2;
+
+                CacheQueryPartitionInfo[] partsLeft = extractPartition(op.child(0), ctx);
+                CacheQueryPartitionInfo[] partsRight = extractPartition(op.child(1), ctx);
+
+                if (partsLeft != null && partsRight != null)
+                    return null; //kind of conflict (_key = 1) and (_key = 2)
+
+                if (partsLeft != null)
+                    return partsLeft;
+
+                if (partsRight != null)
+                    return partsRight;
+
+                return null;
+            }
+
+            case OR: {
+                assert op.size() == 2;
+
+                CacheQueryPartitionInfo[] partsLeft = extractPartition(op.child(0), ctx);
+                CacheQueryPartitionInfo[] partsRight = extractPartition(op.child(1), ctx);
+
+                if (partsLeft != null && partsRight != null)
+                    return mergePartitionInfo(partsLeft, partsRight);
+
+                return null;
+            }
+
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * Analyses the equality operation and extracts the partition if possible
+     *
+     * @param op AST equality operation.
+     * @param ctx Kernal Context.
+     * @return partition info, or {@code null} if none identified
+     */
+    private static CacheQueryPartitionInfo extractPartitionFromEquality(GridSqlOperation op, GridKernalContext ctx)
+        throws IgniteCheckedException {
+
+        assert op.operationType() == GridSqlOperationType.EQUAL;
+
+        GridSqlElement left = op.child(0);
+        GridSqlElement right = op.child(1);
+
+        if (!(left instanceof GridSqlColumn))
+            return null;
+
+        if (!(right instanceof GridSqlConst) && !(right instanceof GridSqlParameter))
+            return null;
+
+        GridSqlColumn column = (GridSqlColumn)left;
+
+        assert column.column().getTable() instanceof GridH2Table;
+
+        GridH2Table tbl = (GridH2Table) column.column().getTable();
+
+        GridH2RowDescriptor desc = tbl.rowDescriptor();
+
+        IndexColumn affKeyCol = tbl.getAffinityKeyColumn();
+
+        int colId = column.column().getColumnId();
+
+        if ((affKeyCol == null || colId != affKeyCol.column.getColumnId()) && !desc.isKeyColumn(colId))
+            return null;
+
+        if (right instanceof GridSqlConst) {
+            GridSqlConst constant = (GridSqlConst)right;
+
+            return new CacheQueryPartitionInfo(ctx.affinity().partition(tbl.cacheName(),
+                constant.value().getObject()), null, -1);
+        }
+
+        assert right instanceof GridSqlParameter;
+
+        GridSqlParameter param = (GridSqlParameter) right;
+
+        return new CacheQueryPartitionInfo(-1, tbl.cacheName(), param.index());
     }
+
+    /**
+     * Merges two partition info arrays, removing duplicates
+     *
+     * @param a Partition info array.
+     * @param b Partition info array.
+     * @return Result.
+     */
+    private static CacheQueryPartitionInfo[] mergePartitionInfo(CacheQueryPartitionInfo[] a, CacheQueryPartitionInfo[] b) {
+        assert a != null;
+        assert b != null;
+
+        if (a.length == 1 && b.length == 1) {
+            if (a[0].equals(b[0]))
+                return new CacheQueryPartitionInfo[] { a[0] };
+
+            return new CacheQueryPartitionInfo[] { a[0], b[0] };
+        }
+
+        ArrayList<CacheQueryPartitionInfo> list = new ArrayList<>(a.length + b.length);
+
+        for (CacheQueryPartitionInfo part: a)
+            list.add(part);
+
+        for (CacheQueryPartitionInfo part: b) {
+            int i = 0;
+
+            while (i < list.size() && !list.get(i).equals(part))
+                i++;
+
+            if (i == list.size())
+                list.add(part);
+        }
+
+        CacheQueryPartitionInfo[] result = new CacheQueryPartitionInfo[list.size()];
+
+        for (int i = 0; i < list.size(); i++)
+            result[i] = list.get(i);
+
+        return result;
+    }
+
+    /**
+     * Ensures all given queries have non-empty derived partitions and merges them.
+     *
+     * @param queries Collection of queries.
+     * @return Derived partitions for all queries, or {@code null}.
+     */
+    private static CacheQueryPartitionInfo[] mergePartitionsFromMultipleQueries(List<GridCacheSqlQuery> queries) {
+        CacheQueryPartitionInfo[] result = null;
+
+        for (GridCacheSqlQuery qry : queries) {
+            CacheQueryPartitionInfo[] partInfo = (CacheQueryPartitionInfo[])qry.derivedPartitions();
+
+            if (partInfo == null) {
+                result = null;
+
+                break;
+            }
+
+            if (result == null)
+                result = partInfo;
+            else
+                result = mergePartitionInfo(result, partInfo);
+        }
+
+        return result;
+    }
+
     /**
      * Simplified tree-like model for a query.
      * - SELECT : All the children are list of joined query models in the FROM clause.

http://git-wip-us.apache.org/repos/asf/ignite/blob/fbf0e353/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlRoutingTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlRoutingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlRoutingTest.java
new file mode 100644
index 0000000..fddd3f4
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlRoutingTest.java
@@ -0,0 +1,552 @@
+/*
+ * 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.processors.query;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheKeyConfiguration;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.affinity.AffinityKeyMapped;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.events.CacheQueryExecutedEvent;
+import org.apache.ignite.events.Event;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.apache.ignite.events.EventType.EVT_CACHE_QUERY_EXECUTED;
+
+public class IgniteSqlRoutingTest extends GridCommonAbstractTest {
+    /** IP finder. */
+    private static final TcpDiscoveryVmIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static String NODE_CLIENT = "client";
+
+    /** */
+    private static String CACHE_PERSON = "Person";
+
+    /** */
+    private static String CACHE_CALL = "Call";
+
+    /** */
+    private static int NODE_COUNT = 4;
+
+    /** broadcast query to ensure events came from all nodes */
+    private static String FINAL_QRY = "select count(1) from {0} where name=?";
+
+    /** Param to distinguish the final query event */
+    private static String FINAL_QRY_PARAM = "Abracadabra";
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration c = super.getConfiguration(gridName);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        c.setDiscoverySpi(disco);
+
+        c.setMarshaller(new BinaryMarshaller());
+
+        List<CacheConfiguration> ccfgs = new ArrayList<>();
+
+        CacheConfiguration ccfg = buildCacheConfiguration(gridName);
+
+        if (ccfg != null)
+            ccfgs.add(ccfg);
+
+        ccfgs.add(buildCacheConfiguration(CACHE_PERSON));
+        ccfgs.add(buildCacheConfiguration(CACHE_CALL));
+
+        c.setCacheConfiguration(ccfgs.toArray(new CacheConfiguration[ccfgs.size()]));
+
+        if (gridName.equals(NODE_CLIENT))
+            c.setClientMode(true);
+
+        c.setCacheKeyConfiguration(new CacheKeyConfiguration(CallKey.class));
+
+        return c;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGrids(NODE_COUNT);
+
+        startGrid(NODE_CLIENT);
+
+        fillCaches();
+    }
+
+    @Override protected void afterTestsStopped() throws Exception {
+        super.afterTestsStopped();
+
+        stopAllGrids();
+    }
+
+    private CacheConfiguration buildCacheConfiguration(String name) {
+        if (name.equals(CACHE_PERSON)) {
+            CacheConfiguration ccfg = new CacheConfiguration(CACHE_PERSON);
+
+            ccfg.setCacheMode(CacheMode.PARTITIONED);
+
+            QueryEntity entity = new QueryEntity();
+
+            entity.setKeyType(Integer.class.getName());
+
+            entity.setValueType(Person.class.getName());
+
+            LinkedHashMap<String, String> fields = new LinkedHashMap<>();
+
+            fields.put("name", String.class.getName());
+            fields.put("age", Integer.class.getName());
+
+            entity.setFields(fields);
+
+            ccfg.setQueryEntities(Arrays.asList(entity));
+
+            return ccfg;
+        }
+
+        if (name.equals(CACHE_CALL)) {
+            CacheConfiguration ccfg = new CacheConfiguration(CACHE_CALL);
+
+            ccfg.setCacheMode(CacheMode.PARTITIONED);
+
+            QueryEntity entity = new QueryEntity(CallKey.class.getName(), Call.class.getName());
+
+            Set<String> keyFields = new HashSet<>();
+
+            keyFields.add("personId");
+            keyFields.add("id");
+
+            entity.setKeyFields(keyFields);
+
+            LinkedHashMap<String, String> fields = new LinkedHashMap<>();
+
+            fields.put("personId", Integer.class.getName());
+            fields.put("id", Integer.class.getName());
+            fields.put("name", String.class.getName());
+            fields.put("duration", Integer.class.getName());
+
+            entity.setFields(fields);
+
+            ccfg.setQueryEntities(Arrays.asList(entity));
+
+            return ccfg;
+        }
+        return null;
+    }
+
+    /** */
+    public void testUnicastQuerySelectAffinityKeyEqualsConstant() throws Exception {
+        IgniteCache<CallKey, Call> cache = grid(NODE_CLIENT).cache(CACHE_CALL);
+
+        List<List<?>> result = runQueryEnsureUnicast(cache,
+                new SqlFieldsQuery("select id, name, duration from Call where personId=100 order by id"), 1);
+
+        assertEquals(2, result.size());
+
+        checkResultsRow(result, 0, 1, "caller1", 100);
+        checkResultsRow(result, 1, 2, "caller2", 200);
+    }
+
+    /** */
+    public void testUnicastQuerySelectAffinityKeyEqualsParameter() throws Exception {
+        IgniteCache<CallKey, Call> cache = grid(NODE_CLIENT).cache(CACHE_CALL);
+
+        List<List<?>> result = runQueryEnsureUnicast(cache,
+                new SqlFieldsQuery("select id, name, duration from Call where personId=? order by id").setArgs(100), 1);
+
+        assertEquals(2, result.size());
+
+        checkResultsRow(result, 0, 1, "caller1", 100);
+        checkResultsRow(result, 1, 2, "caller2", 200);
+    }
+
+    /** */
+    public void testUnicastQuerySelectKeyEqualsParameterReused() throws Exception {
+        IgniteCache<Integer, Person> cache = grid(NODE_CLIENT).cache(CACHE_PERSON);
+
+        for (int key : new int[] {0, 250, 500, 750, 1000} ) {
+            List<List<?>> result = runQueryEnsureUnicast(cache,
+                    new SqlFieldsQuery("select name, age from Person where _key=?").setArgs(key), 1);
+
+            assertEquals(1, result.size());
+
+            Person person = cache.get(key);
+
+            checkResultsRow(result, 0, person.name, person.age);
+        }
+    }
+
+    /** */
+    public void testUnicastQuerySelectKeyEqualsParameter() throws Exception {
+        IgniteCache<CallKey, Call> cache = grid(NODE_CLIENT).cache(CACHE_CALL);
+
+        CallKey callKey = new CallKey(5, 1);
+
+        List<List<?>> result = runQueryEnsureUnicast(cache,
+                new SqlFieldsQuery("select name, duration from Call where _key=?")
+                .setArgs(callKey), 1);
+
+        assertEquals(1, result.size());
+
+        Call call = cache.get(callKey);
+
+        checkResultsRow(result, 0, call.name, call.duration);
+    }
+
+    /** Check group, having, ordering allowed to be unicast requests */
+    public void testUnicastQueryGroups() throws Exception {
+        IgniteCache<CallKey, Call> cache = grid(NODE_CLIENT).cache(CACHE_CALL);
+
+        String qry = "select name, count(1) " +
+                "from Call " +
+                "where personId = ? " +
+                "group by name " +
+                "having count(1) = 1 " +
+                "order by name";
+
+        final int personId = 10;
+
+        List<List<?>> result = runQueryEnsureUnicast(cache, new SqlFieldsQuery(qry).setArgs(personId), 1);
+
+        assertEquals(2, result.size());
+
+        checkResultsRow(result, 0, "caller1", 1L);
+        checkResultsRow(result, 1, "caller2", 1L);
+    }
+
+    /** */
+    public void testUnicastQuerySelectKeyEqualAndFieldParameter() throws Exception {
+        IgniteCache<CallKey, Call> cache = grid(NODE_CLIENT).cache(CACHE_CALL);
+
+        CallKey callKey = new CallKey(5, 1);
+
+        List<List<?>> result = runQueryEnsureUnicast(cache,
+                new SqlFieldsQuery("select name, duration from Call where _key=? and duration=?")
+                        .setArgs(callKey, 100), 1);
+
+        assertEquals(1, result.size());
+
+        Call call = cache.get(callKey);
+
+        checkResultsRow(result, 0, call.name, call.duration);
+    }
+
+    /** */
+    public void testUnicastQuerySelect2KeyEqualsAndFieldParameter() throws Exception {
+        IgniteCache<CallKey, Call> cache = grid(NODE_CLIENT).cache(CACHE_CALL);
+
+        CallKey callKey1 = new CallKey(5, 1);
+        CallKey callKey2 = new CallKey(1000, 1);
+
+        List<List<?>> result = runQueryEnsureUnicast(cache,
+                new SqlFieldsQuery("select name, duration from Call where (_key=? and duration=?) or (_key=?)")
+                        .setArgs(callKey1, 100, callKey2), 2);
+
+        assertEquals(2, result.size());
+
+        Call call = cache.get(callKey1);
+
+        checkResultsRow(result, 0, call.name, call.duration);
+
+        call = cache.get(callKey2);
+
+        checkResultsRow(result, 1, call.name, call.duration);
+    }
+
+    /** */
+    public void testBroadcastQuerySelectKeyEqualsOrFieldParameter() throws Exception {
+        IgniteCache<CallKey, Call> cache = grid(NODE_CLIENT).cache(CACHE_CALL);
+
+        CallKey callKey = new CallKey(5, 1);
+
+        List<List<?>> result = runQueryEnsureBroadcast(cache,
+                new SqlFieldsQuery("select name, duration from Call where _key=? or duration=?")
+                        .setArgs(callKey, 100));
+
+        assertEquals(cache.size() / 2, result.size());
+    }
+
+    /** */
+    private void fillCaches() {
+        IgniteCache<CallKey, Call> callCache = grid(NODE_CLIENT).cache(CACHE_CALL);
+        IgniteCache<Integer, Person> personCache = grid(NODE_CLIENT).cache(CACHE_PERSON);
+
+        int count = affinity(personCache).partitions();
+
+        String[] names = {"John", "Bob", "James", "David", "Chuck"};
+
+        for (int i = 0; i < count; i++) {
+            Person person = new Person(names[i % names.length], 20 + (i % names.length));
+
+            personCache.put(i, person);
+
+            // each person gets 2 calls
+            callCache.put(new CallKey(i, 1), new Call("caller1", 100));
+            callCache.put(new CallKey(i, 2), new Call("caller2", 200));
+        }
+    }
+
+    /** */
+    private void checkResultsRow(List<List<?>> results, int rowId, Object ... expected) throws Exception {
+        assertTrue(rowId < results.size());
+
+        List<?> row = results.get(rowId);
+
+        assertEquals(expected.length, row.size());
+
+        for(int col = 0; col < expected.length; ++col)
+            assertEquals(expected[col], row.get(col));
+    }
+
+    /** Run query and check that only one node did generate 'query executed' event for it */
+    private List<List<?>> runQueryEnsureUnicast(IgniteCache<?,?> cache, SqlFieldsQuery qry, int nodeCnt) throws Exception {
+        try (EventCounter evtCounter = new EventCounter(nodeCnt)) {
+            List<List<?>> result = cache.query(qry).getAll();
+
+            // do broadcast 'marker' query to ensure that we received all events from previous qry
+            cache.query(new SqlFieldsQuery(
+                    MessageFormat.format(FINAL_QRY, cache.getName()))
+                    .setArgs(FINAL_QRY_PARAM)).getAll();
+
+            // wait for all events from 'marker' query
+            evtCounter.await();
+
+            // return result set of first query
+            return result;
+        }
+    }
+
+    private List<List<?>> runQueryEnsureBroadcast(IgniteCache<?, ?> cache, SqlFieldsQuery qry) throws Exception {
+        final CountDownLatch execLatch = new CountDownLatch(NODE_COUNT);
+
+        final IgnitePredicate<Event> pred = new IgnitePredicate<Event>() {
+            @Override public boolean apply(Event evt) {
+                assert evt instanceof CacheQueryExecutedEvent;
+
+                CacheQueryExecutedEvent qe = (CacheQueryExecutedEvent)evt;
+
+                assertNotNull(qe.clause());
+
+                execLatch.countDown();
+
+                return true;
+            }
+        };
+
+        for (int i = 0; i < NODE_COUNT; i++)
+            grid(i).events().localListen(pred, EVT_CACHE_QUERY_EXECUTED);
+
+        List<List<?>> result = cache.query(qry).getAll();
+
+        assertTrue(execLatch.await(5000, MILLISECONDS));
+
+        for (int i = 0; i < NODE_COUNT; i++)
+            grid(i).events().stopLocalListen(pred);
+
+        return result;
+    }
+
+    /** */
+    private class EventCounter implements AutoCloseable {
+        /** */
+        final AtomicInteger cnt;
+
+        /** */
+        final CountDownLatch execLatch;
+
+        /** */
+        final IgnitePredicate<Event> pred = new IgnitePredicate<Event>() {
+            @Override public boolean apply(Event evt) {
+                assert evt instanceof CacheQueryExecutedEvent;
+
+                CacheQueryExecutedEvent qe = (CacheQueryExecutedEvent)evt;
+
+                String cacheName = qe.cacheName();
+
+                assert cacheName != null;
+
+                if (!cacheName.equals(CACHE_PERSON) &&
+                    !cacheName.equals(CACHE_CALL))
+                    return true;
+
+                assertNotNull(qe.clause());
+
+                Object[] args = qe.arguments();
+
+                if ((args != null) && (args.length > 0) && (args[0] instanceof String)) {
+                    String strParam = (String)args[0];
+
+                    if (FINAL_QRY_PARAM.equals(strParam)) {
+                        execLatch.countDown();
+
+                        return true;
+                    }
+                }
+                cnt.decrementAndGet();
+
+                return true;
+            }
+        };
+
+        /** */
+        private EventCounter(int cnt) {
+            this.cnt = new AtomicInteger(cnt);
+
+            this.execLatch = new CountDownLatch(NODE_COUNT);
+
+            for (int i = 0; i < NODE_COUNT; i++)
+                grid(i).events().localListen(pred, EVT_CACHE_QUERY_EXECUTED);
+        }
+
+        /** */
+        public void await() throws Exception {
+            assertTrue(execLatch.await(5000, MILLISECONDS));
+
+            assertEquals(0, cnt.get());
+        }
+
+        /** {@inheritDoc} */
+        @Override public void close() throws Exception {
+            for (int i = 0; i < NODE_COUNT; i++)
+                grid(i).events().stopLocalListen(pred);
+        }
+    }
+
+    /** */
+    private static class Person {
+        /** */
+        private String name;
+
+        /** */
+        private int age;
+
+        /** */
+        public Person(String name, int age) {
+            this.name = name;
+            this.age = age;
+        }
+
+        /** */
+        @Override public int hashCode() {
+            return name.hashCode() ^ age;
+        }
+
+        /** */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+
+            if (!(o instanceof Person))
+                return false;
+
+            Person other = (Person)o;
+
+            return name.equals(other.name) && age == other.age;
+        }
+    }
+
+    /** */
+    private static class CallKey {
+        /** */
+        @AffinityKeyMapped
+        private int personId;
+
+        /** */
+        private int id;
+
+        /** */
+        public CallKey(int personId, int id) {
+            this.personId = personId;
+            this.id = id;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return personId ^ id;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+
+            if (!(o instanceof CallKey))
+                return false;
+
+            CallKey other = (CallKey)o;
+
+            return this.personId == other.personId && this.id == other.id;
+        }
+    }
+
+    /** */
+    private static class Call {
+        /** */
+        private String name;
+
+        /** */
+        private int duration;
+
+        /** */
+        public Call(String name, int duration) {
+            this.name = name;
+
+            this.duration = duration;
+        }
+
+        /** */
+        @Override public int hashCode() {
+            return name.hashCode() ^ duration;
+        }
+
+        /** */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+
+            if (!(o instanceof Call))
+                return false;
+
+            Call other = (Call)o;
+
+            return name.equals(other.name) && duration == other.duration;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/fbf0e353/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
index 14fb6ce..13dfef7 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
@@ -110,6 +110,7 @@ import org.apache.ignite.internal.processors.cache.query.IndexingSpiQueryTxSelfT
 import org.apache.ignite.internal.processors.query.IgniteQueryDedicatedPoolTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlEntryCacheModeAgnosticTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlKeyValueFieldsTest;
+import org.apache.ignite.internal.processors.query.IgniteSqlRoutingTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSchemaIndexingTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexMultiNodeSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexSelfTest;
@@ -287,6 +288,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
         suite.addTestSuite(IgniteCacheDistributedPartitionQueryNodeRestartsSelfTest.class);
         suite.addTestSuite(IgniteCacheDistributedPartitionQueryConfigurationSelfTest.class);
         suite.addTestSuite(IgniteSqlKeyValueFieldsTest.class);
+        suite.addTestSuite(IgniteSqlRoutingTest.class);
 
         return suite;
     }


[50/50] [abbrv] ignite git commit: ignite-5075

Posted by sb...@apache.org.
ignite-5075


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a7cd1b63
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a7cd1b63
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a7cd1b63

Branch: refs/heads/ignite-5075
Commit: a7cd1b637aa86e949de0dc66ef3a6e20cbc1e053
Parents: d1a8d5c
Author: sboikov <sb...@gridgain.com>
Authored: Tue Jun 6 11:57:53 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Jun 6 11:57:53 2017 +0300

----------------------------------------------------------------------
 .../apache/ignite/internal/processors/cache/ClusterCachesInfo.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/a7cd1b63/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
index b5b8a43..0fcc740 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
@@ -342,7 +342,7 @@ class ClusterCachesInfo {
                     }
                     else {
                         SchemaOperationException err = QueryUtils.checkQueryEntityConflicts(
-                            req.startCacheConfiguration(), ctx.cache().cacheDescriptors());
+                            req.startCacheConfiguration(), ctx.cache().cacheDescriptors().values());
 
                         if (err != null) {
                             ctx.cache().completeCacheStartFuture(req, false, err);


[41/50] [abbrv] ignite git commit: IGNITE-5275: Implemented SqlConnectorConfiguration. Deprecated OdbcConfiguration. This closes #2080.

Posted by sb...@apache.org.
IGNITE-5275: Implemented SqlConnectorConfiguration. Deprecated OdbcConfiguration. This closes #2080.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/776cc6e7
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/776cc6e7
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/776cc6e7

Branch: refs/heads/ignite-5075
Commit: 776cc6e70a2a0a2d2e69f9bd89e3d44784402dec
Parents: 2485b98
Author: devozerov <vo...@gridgain.com>
Authored: Mon Jun 5 17:39:32 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Mon Jun 5 17:39:32 2017 +0300

----------------------------------------------------------------------
 .../JdbcThinAbstractDmlStatementSelfTest.java   |   3 -
 .../jdbc/thin/JdbcThinAbstractSelfTest.java     |  11 -
 .../jdbc/thin/JdbcThinEmptyCacheSelfTest.java   |   3 -
 .../thin/JdbcThinPreparedStatementSelfTest.java |   3 -
 .../jdbc/thin/JdbcThinStatementSelfTest.java    |   3 -
 .../org/apache/ignite/IgniteJdbcThinDriver.java |   1 -
 .../configuration/IgniteConfiguration.java      |  30 ++
 .../ignite/configuration/OdbcConfiguration.java |   4 +
 .../SqlConnectorConfiguration.java              | 275 +++++++++++++++++++
 .../internal/jdbc/thin/JdbcThinUtils.java       |   3 +-
 .../internal/processors/odbc/OdbcTypes.java     | 131 ---------
 .../internal/processors/odbc/OdbcUtils.java     | 141 ----------
 .../processors/odbc/SqlListenerDataTypes.java   |  30 +-
 .../processors/odbc/SqlListenerNioListener.java |   2 +-
 .../processors/odbc/SqlListenerProcessor.java   | 187 +++++++++----
 .../processors/odbc/odbc/OdbcColumnMeta.java    |   1 -
 .../odbc/odbc/OdbcRequestHandler.java           |   1 -
 .../processors/odbc/odbc/OdbcTableMeta.java     |   1 -
 .../processors/odbc/odbc/OdbcTypes.java         | 131 +++++++++
 .../processors/odbc/odbc/OdbcUtils.java         | 142 ++++++++++
 .../odbc/odbc/escape/OdbcEscapeUtils.java       |   2 +-
 .../OdbcConfigurationValidationSelfTest.java    | 186 +++++++++++++
 .../SqlListenerProcessorValidationSelfTest.java | 184 -------------
 .../ignite/testsuites/IgniteBasicTestSuite.java |   4 +-
 .../processors/query/h2/IgniteH2Indexing.java   |   2 +-
 ...onnectorConfigurationValidationSelfTest.java | 245 +++++++++++++++++
 .../IgniteCacheQuerySelfTestSuite.java          |   3 +
 .../odbc-example/config/example-odbc.xml        |   6 -
 .../odbc-test/config/queries-test-default.xml   |   9 +-
 .../odbc-test/config/queries-test-noodbc-32.xml |   4 +
 .../odbc-test/config/queries-test-noodbc.xml    |   6 +-
 31 files changed, 1188 insertions(+), 566 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
index eddf61b..b5760dd 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractDmlStatementSelfTest.java
@@ -26,7 +26,6 @@ import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.ConnectorConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.OdbcConfiguration;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
@@ -105,8 +104,6 @@ public abstract class JdbcThinAbstractDmlStatementSelfTest extends JdbcThinAbstr
 
         cfg.setConnectorConfiguration(new ConnectorConfiguration());
 
-        cfg.setOdbcConfiguration(new OdbcConfiguration());
-
         return cfg;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
index bbefbd4..99b79ea 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.jdbc.thin;
 
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.OdbcConfiguration;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 
 /**
@@ -29,13 +27,4 @@ public class JdbcThinAbstractSelfTest extends GridCommonAbstractTest {
     @Override protected void beforeTestsStarted() throws Exception {
         Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
     }
-
-    /** {@inheritDoc} */
-    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
-        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
-
-        cfg.setOdbcConfiguration(new OdbcConfiguration());
-
-        return cfg;
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java
index 4775a79..1ede536 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java
@@ -23,7 +23,6 @@ import java.sql.ResultSet;
 import java.sql.Statement;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.OdbcConfiguration;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
@@ -69,8 +68,6 @@ public class JdbcThinEmptyCacheSelfTest extends JdbcThinAbstractSelfTest {
 
         cfg.setDiscoverySpi(disco);
 
-        cfg.setOdbcConfiguration(new OdbcConfiguration());
-
         return cfg;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
index aead436..6f18c75 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
@@ -33,7 +33,6 @@ import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.OdbcConfiguration;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
@@ -98,8 +97,6 @@ public class JdbcThinPreparedStatementSelfTest extends JdbcThinAbstractSelfTest
 
         cfg.setDiscoverySpi(disco);
 
-        cfg.setOdbcConfiguration(new OdbcConfiguration());
-
         return cfg;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
index a9a7e7b..92f7255 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
@@ -26,7 +26,6 @@ import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.OdbcConfiguration;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
@@ -75,8 +74,6 @@ public class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
 
         cfg.setDiscoverySpi(disco);
 
-        cfg.setOdbcConfiguration(new OdbcConfiguration());
-
         return cfg;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
index 665ac69..3e3511b 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
@@ -133,7 +133,6 @@ import org.apache.ignite.internal.util.typedef.F;
  */
 @SuppressWarnings("JavadocReference")
 public class IgniteJdbcThinDriver implements Driver {
-
     /** Major version. */
     private static final int MAJOR_VER = IgniteVersionUtils.VER.major();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
index 89ab43e..8e531e2 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
@@ -419,6 +419,7 @@ public class IgniteConfiguration {
     private ConnectorConfiguration connectorCfg = new ConnectorConfiguration();
 
     /** ODBC configuration. */
+    @Deprecated
     private OdbcConfiguration odbcCfg;
 
     /** Warmup closure. Will be invoked before actual grid start. */
@@ -463,6 +464,9 @@ public class IgniteConfiguration {
     /** */
     private long longQryWarnTimeout = DFLT_LONG_QRY_WARN_TIMEOUT;
 
+    /** SQL connector configuration. */
+    private SqlConnectorConfiguration sqlConnCfg = new SqlConnectorConfiguration();
+
     /**
      * Creates valid grid configuration with all default values.
      */
@@ -554,6 +558,7 @@ public class IgniteConfiguration {
         segResolvers = cfg.getSegmentationResolvers();
         sndRetryCnt = cfg.getNetworkSendRetryCount();
         sndRetryDelay = cfg.getNetworkSendRetryDelay();
+        sqlConnCfg = cfg.getSqlConnectorConfiguration();
         sslCtxFactory = cfg.getSslContextFactory();
         storeSesLsnrs = cfg.getCacheStoreSessionListenerFactories();
         stripedPoolSize = cfg.getStripedPoolSize();
@@ -2438,7 +2443,9 @@ public class IgniteConfiguration {
      * Gets configuration for ODBC.
      *
      * @return ODBC configuration.
+     * @deprecated Use {@link #getSqlConnectorConfiguration()} instead.
      */
+    @Deprecated
     public OdbcConfiguration getOdbcConfiguration() {
         return odbcCfg;
     }
@@ -2448,7 +2455,9 @@ public class IgniteConfiguration {
      *
      * @param odbcCfg ODBC configuration.
      * @return {@code this} for chaining.
+     * @deprecated Use {@link #setSqlConnectorConfiguration(SqlConnectorConfiguration)} instead.
      */
+    @Deprecated
     public IgniteConfiguration setOdbcConfiguration(OdbcConfiguration odbcCfg) {
         this.odbcCfg = odbcCfg;
 
@@ -2742,6 +2751,27 @@ public class IgniteConfiguration {
         return this;
     }
 
+    /**
+     * Sets SQL connector configuration.
+     *
+     * @param sqlConnCfg SQL connector configuration.
+     * @return {@code this} for chaining.
+     */
+    public IgniteConfiguration setSqlConnectorConfiguration(SqlConnectorConfiguration sqlConnCfg) {
+        this.sqlConnCfg = sqlConnCfg;
+
+        return this;
+    }
+
+    /**
+     * Gets SQL connector configuration.
+     *
+     * @return SQL connector configuration.
+     */
+    public SqlConnectorConfiguration getSqlConnectorConfiguration() {
+        return sqlConnCfg;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(IgniteConfiguration.class, this);

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/configuration/OdbcConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/OdbcConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/OdbcConfiguration.java
index 8fe1665..6d7ab38 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/OdbcConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/OdbcConfiguration.java
@@ -21,7 +21,11 @@ import org.apache.ignite.internal.util.typedef.internal.S;
 
 /**
  * ODBC configuration.
+ * <p>
+ * Deprecated as of Apache Ignite 2.1. Please use {@link SqlConnectorConfiguration} and
+ * {@link IgniteConfiguration#setSqlConnectorConfiguration(SqlConnectorConfiguration)} instead.
  */
+@Deprecated
 public class OdbcConfiguration {
     /** Default TCP host. */
     public static final String DFLT_TCP_HOST = "0.0.0.0";

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/configuration/SqlConnectorConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/SqlConnectorConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/SqlConnectorConfiguration.java
new file mode 100644
index 0000000..15563c8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/SqlConnectorConfiguration.java
@@ -0,0 +1,275 @@
+/*
+ * 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.configuration;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * SQL connector configuration.
+ */
+public class SqlConnectorConfiguration {
+    /** Default port. */
+    public static final int DFLT_PORT = 10800;
+
+    /** Default port range. */
+    public static final int DFLT_PORT_RANGE = 100;
+
+    /** Default socket send and receive buffer size. */
+    public static final int DFLT_SOCK_BUF_SIZE = 0;
+
+    /** Default value for {@code TCP_NODELAY} socket option (value is <tt>true</tt>). */
+    public static final boolean DFLT_TCP_NO_DELAY = true;
+
+    /** Default max number of open cursors per connection. */
+    public static final int DFLT_MAX_OPEN_CURSORS_PER_CONN = 128;
+
+    /** Default size of thread pool. */
+    public static final int DFLT_THREAD_POOL_SIZE = IgniteConfiguration.DFLT_PUBLIC_THREAD_CNT;
+
+    /** Host. */
+    private String host;
+
+    /** Port. */
+    private int port = DFLT_PORT;
+
+    /** Poart range. */
+    private int portRange = DFLT_PORT_RANGE;
+
+    /** Socket send buffer size. */
+    private int sockSndBufSize = DFLT_SOCK_BUF_SIZE;
+
+    /** Socket receive buffer size. */
+    private int sockRcvBufSize = DFLT_SOCK_BUF_SIZE;
+
+    /** TCP no delay. */
+    private boolean tcpNoDelay = DFLT_TCP_NO_DELAY;
+
+    /** Max number of opened cursors per connection. */
+    private int maxOpenCursorsPerConn = DFLT_MAX_OPEN_CURSORS_PER_CONN;
+
+    /** Thread pool size. */
+    private int threadPoolSize = DFLT_THREAD_POOL_SIZE;
+
+    /**
+     * Creates SQL connector configuration with all default values.
+     */
+    public SqlConnectorConfiguration() {
+        // No-op.
+    }
+
+    /**
+     * Creates SQL connector configuration by copying all properties from given configuration.
+     *
+     * @param cfg Configuration to copy.
+     */
+    public SqlConnectorConfiguration(SqlConnectorConfiguration cfg) {
+        assert cfg != null;
+
+        host = cfg.getHost();
+        maxOpenCursorsPerConn = cfg.getMaxOpenCursorsPerConnection();
+        port = cfg.getPort();
+        portRange = cfg.getPortRange();
+        sockRcvBufSize = cfg.getSocketReceiveBufferSize();
+        sockSndBufSize = cfg.getSocketSendBufferSize();
+        tcpNoDelay = cfg.isTcpNoDelay();
+        threadPoolSize = cfg.getThreadPoolSize();
+    }
+
+    /**
+     * Get host.
+     *
+     * @return Host.
+     */
+    @Nullable public String getHost() {
+        return host;
+    }
+
+    /**
+     * Set host.
+     *
+     * @param host Host.
+     * @return This instance for chaining.
+     */
+    public SqlConnectorConfiguration setHost(@Nullable String host) {
+        this.host = host;
+
+        return this;
+    }
+
+    /**
+     * Get port.
+     *
+     * @return Port.
+     */
+    public int getPort() {
+        return port;
+    }
+
+    /**
+     * Set port.
+     *
+     * @param port Port.
+     * @return This instance for chaining.
+     */
+    public SqlConnectorConfiguration setPort(int port) {
+        this.port = port;
+
+        return this;
+    }
+
+    /**
+     * Get port range.
+     *
+     * @return Port range.
+     */
+    public int getPortRange() {
+        return portRange;
+    }
+
+    /**
+     * Set port range.
+     *
+     * @param portRange Port range.
+     * @return This instance for chaining.
+     */
+    public SqlConnectorConfiguration setPortRange(int portRange) {
+        this.portRange = portRange;
+
+        return this;
+    }
+
+    /**
+     * Gets socket send buffer size. When set to zero, operation system default will be used.
+     * <p>
+     * Defaults to {@link #DFLT_SOCK_BUF_SIZE}
+     *
+     * @return Socket send buffer size in bytes.
+     */
+    public int getSocketSendBufferSize() {
+        return sockSndBufSize;
+    }
+
+    /**
+     * Sets socket send buffer size. See {@link #getSocketSendBufferSize()} for more information.
+     *
+     * @param sockSndBufSize Socket send buffer size in bytes.
+     * @return This instance for chaining.
+     */
+    public SqlConnectorConfiguration setSocketSendBufferSize(int sockSndBufSize) {
+        this.sockSndBufSize = sockSndBufSize;
+
+        return this;
+    }
+
+    /**
+     * Gets socket receive buffer size. When set to zero, operation system default will be used.
+     * <p>
+     * Defaults to {@link #DFLT_SOCK_BUF_SIZE}.
+     *
+     * @return Socket receive buffer size in bytes.
+     */
+    public int getSocketReceiveBufferSize() {
+        return sockRcvBufSize;
+    }
+
+    /**
+     * Sets socket receive buffer size. See {@link #getSocketReceiveBufferSize()} for more information.
+     *
+     * @param sockRcvBufSize Socket receive buffer size in bytes.
+     * @return This instance for chaining.
+     */
+    public SqlConnectorConfiguration setSocketReceiveBufferSize(int sockRcvBufSize) {
+        this.sockRcvBufSize = sockRcvBufSize;
+
+        return this;
+    }
+
+    /**
+     * Get TCP NO_DELAY flag.
+     *
+     * @return TCP NO_DELAY flag.
+     */
+    public boolean isTcpNoDelay() {
+        return tcpNoDelay;
+    }
+
+    /**
+     * Set TCP NO_DELAY flag.
+     *
+     * @param tcpNoDelay TCP NO_DELAY flag.
+     * @return This instance for chaining.
+     */
+    public SqlConnectorConfiguration setTcpNoDelay(boolean tcpNoDelay) {
+        this.tcpNoDelay = tcpNoDelay;
+
+        return this;
+    }
+
+    /**
+     * Gets maximum number of opened cursors per connection.
+     * <p>
+     * Defaults to {@link #DFLT_MAX_OPEN_CURSORS_PER_CONN}.
+     *
+     * @return Maximum number of opened cursors.
+     */
+    public int getMaxOpenCursorsPerConnection() {
+        return maxOpenCursorsPerConn;
+    }
+
+    /**
+     * Sets maximum number of opened cursors per connection.
+     *
+     * @param maxOpenCursorsPerConn Maximum number of opened cursors.
+     * @return This instance for chaining.
+     */
+    public SqlConnectorConfiguration setMaxOpenCursorsPerConnection(int maxOpenCursorsPerConn) {
+        this.maxOpenCursorsPerConn = maxOpenCursorsPerConn;
+
+        return this;
+    }
+
+    /**
+     * Size of thread pool that is in charge of processing SQL requests.
+     * <p>
+     * Defaults {@link #DFLT_THREAD_POOL_SIZE}.
+     *
+     * @return Thread pool that is in charge of processing SQL requests.
+     */
+    public int getThreadPoolSize() {
+        return threadPoolSize;
+    }
+
+    /**
+     * Sets thread pool that is in charge of processing SQL requests. See {@link #getThreadPoolSize()} for more
+     * information.
+     *
+     * @param threadPoolSize Thread pool that is in charge of processing SQL requests.
+     * @return This instance for chaining.
+     */
+    public SqlConnectorConfiguration setThreadPoolSize(int threadPoolSize) {
+        this.threadPoolSize = threadPoolSize;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(SqlConnectorConfiguration.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
index a346ea8..8d7d6b1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.jdbc.thin;
 
 import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.configuration.SqlConnectorConfiguration;
 
 import java.sql.Time;
 import java.sql.Timestamp;
@@ -85,7 +86,7 @@ public class JdbcThinUtils {
     public static final String PROP_TCP_NO_DELAY = PROP_PREFIX + PARAM_TCP_NO_DELAY;
 
     /** Default port. */
-    public static final int DFLT_PORT = OdbcConfiguration.DFLT_TCP_PORT_FROM;
+    public static final int DFLT_PORT = SqlConnectorConfiguration.DFLT_PORT;
 
     /**
      * Trim prefix from property.

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTypes.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTypes.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTypes.java
deleted file mode 100644
index 70ac92b..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTypes.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-/**
- * Data type names that can occur within ODBC escape sequence
- */
-public class OdbcTypes {
-    /** Type name for BIGINT */
-    static final String SQL_BIGINT = "SQL_BIGINT";
-
-    /** Type name for BINARY */
-    static final String SQL_BINARY = "SQL_BINARY";
-
-    /** Type name for LONGVARBINARY */
-    static final String SQL_LONGVARBINARY = "SQL_LONGVARBINARY";
-
-    /** Type name for VARBINARY */
-    static final String SQL_VARBINARY = "SQL_VARBINARY";
-
-    /** Type name for BIT */
-    static final String SQL_BIT = "SQL_BIT";
-
-    /** Type name for CHAR */
-    static final String SQL_CHAR = "SQL_CHAR";
-
-    /** Type name for DECIMAL */
-    static final String SQL_DECIMAL = "SQL_DECIMAL";
-
-    /** Type name for NUMERIC */
-    static final String SQL_NUMERIC = "SQL_NUMERIC";
-
-    /** Type name for LONGVARCHAR */
-    static final String SQL_LONGVARCHAR = "SQL_LONGVARCHAR";
-
-    /** Type name for VARCHAR */
-    static final String SQL_VARCHAR = "SQL_VARCHAR";
-
-    /** Type name for WCHAR */
-    static final String SQL_WCHAR = "SQL_WCHAR";
-
-    /** Type name for WLONGVARCHAR */
-    static final String SQL_WLONGVARCHAR = "SQL_WLONGVARCHAR";
-
-    /** Type name for WVARCHAR */
-    static final String SQL_WVARCHAR = "SQL_WVARCHAR";
-
-    /** Type name for DOUBLE */
-    static final String SQL_DOUBLE = "SQL_DOUBLE";
-
-    /** Type name for FLOAT */
-    static final String SQL_FLOAT = "SQL_FLOAT";
-
-    /** Type name for REAL */
-    static final String SQL_REAL = "SQL_REAL";
-
-    /** Type name for GUID */
-    static final String SQL_GUID = "SQL_GUID";
-
-    /** Type name for SMALLINT */
-    static final String SQL_SMALLINT = "SQL_SMALLINT";
-
-    /** Type name for INTEGER */
-    static final String SQL_INTEGER = "SQL_INTEGER";
-
-    /** Type name for DATE */
-    static final String SQL_DATE = "SQL_DATE";
-
-    /** Type name for TIME */
-    static final String SQL_TIME = "SQL_TIME";
-
-    /** Type name for TIMESTAMP */
-    static final String SQL_TIMESTAMP = "SQL_TIMESTAMP";
-
-    /** Type name for TINYINT */
-    static final String SQL_TINYINT = "SQL_TINYINT";
-
-    /** Type name for INTERVAL_SECOND */
-    static final String SQL_INTERVAL_SECOND = "SQL_INTERVAL_SECOND";
-
-    /** Type name for INTERVAL_MINUTE */
-    static final String SQL_INTERVAL_MINUTE = "SQL_INTERVAL_MINUTE";
-
-    /** Type name for INTERVAL_HOUR */
-    static final String SQL_INTERVAL_HOUR = "SQL_INTERVAL_HOUR";
-
-    /** Type name for INTERVAL_DAY */
-    static final String SQL_INTERVAL_DAY = "SQL_INTERVAL_DAY";
-
-    /** Type name for INTERVAL_MONTH */
-    static final String SQL_INTERVAL_MONTH = "SQL_INTERVAL_MONTH";
-
-    /** Type name for INTERVAL_YEAR */
-    static final String SQL_INTERVAL_YEAR = "SQL_INTERVAL_YEAR";
-
-    /** Type name for INTERVAL_YEAR_TO_MONTH */
-    static final String SQL_INTERVAL_YEAR_TO_MONTH = "SQL_INTERVAL_YEAR_TO_MONTH";
-
-    /** Type name for INTERVAL_HOUR_TO_MINUTE */
-    static final String SQL_INTERVAL_HOUR_TO_MINUTE = "SQL_INTERVAL_HOUR_TO_MINUTE";
-
-    /** Type name for INTERVAL_HOUR_TO_SECOND */
-    static final String SQL_INTERVAL_HOUR_TO_SECOND = "SQL_INTERVAL_HOUR_TO_SECOND";
-
-    /** Type name for INTERVAL_MINUTE_TO_SECOND */
-    static final String SQL_INTERVAL_MINUTE_TO_SECOND = "SQL_INTERVAL_MINUTE_TO_SECOND";
-
-    /** Type name for INTERVAL_DAY_TO_HOUR */
-    static final String SQL_INTERVAL_DAY_TO_HOUR = "SQL_INTERVAL_DAY_TO_HOUR";
-
-    /** Type name for INTERVAL_DAY_TO_MINUTE */
-    static final String SQL_INTERVAL_DAY_TO_MINUTE = "SQL_INTERVAL_DAY_TO_MINUTE";
-
-    /** Type name for INTERVAL_DAY_TO_SECOND */
-    static final String SQL_INTERVAL_DAY_TO_SECOND  = "SQL_INTERVAL_DAY_TO_SECOND";
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcUtils.java
deleted file mode 100644
index 4b046e8..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcUtils.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import org.apache.ignite.IgniteException;
-
-/**
- * Various ODBC utility methods.
- */
-public class OdbcUtils {
-    /**
-     * Add quotation marks at the beginning and end of the string.
-     *
-     * @param str Input string.
-     * @return String surrounded with quotation marks.
-     */
-    public static String addQuotationMarksIfNeeded(String str) {
-        if (str != null && !str.isEmpty() && !(str.startsWith("\"") && str.endsWith("\"")))
-            return "\"" + str + "\"";
-
-        return str;
-    }
-
-    /**
-     * Remove quotation marks at the beginning and end of the string if present.
-     *
-     * @param str Input string.
-     * @return String without leading and trailing quotation marks.
-     */
-    public static String removeQuotationMarksIfNeeded(String str) {
-        if (str != null && str.startsWith("\"") && str.endsWith("\""))
-            return str.substring(1, str.length() - 1);
-
-        return str;
-    }
-
-    /**
-     * Private constructor.
-     */
-    private OdbcUtils() {
-        // No-op.
-    }
-
-    /**
-     * Lookup Ignite data type corresponding to specific ODBC data type
-     *
-     * @param odbcDataType ODBC data type identifier
-     * @return Ignite data type name
-     */
-    public static String getIgniteTypeFromOdbcType(String odbcDataType) {
-        assert odbcDataType != null;
-        switch (odbcDataType.toUpperCase()) {
-            case OdbcTypes.SQL_BIGINT:
-                return SqlListenerDataTypes.BIGINT;
-
-            case OdbcTypes.SQL_BINARY:
-            case OdbcTypes.SQL_LONGVARBINARY:
-            case OdbcTypes.SQL_VARBINARY:
-                return SqlListenerDataTypes.BINARY;
-
-            case OdbcTypes.SQL_BIT:
-                return SqlListenerDataTypes.BIT;
-
-            case OdbcTypes.SQL_CHAR:
-                return SqlListenerDataTypes.CHAR;
-
-            case OdbcTypes.SQL_DECIMAL:
-            case OdbcTypes.SQL_NUMERIC:
-                return SqlListenerDataTypes.DECIMAL;
-
-            case OdbcTypes.SQL_LONGVARCHAR:
-            case OdbcTypes.SQL_VARCHAR:
-            case OdbcTypes.SQL_WCHAR:
-            case OdbcTypes.SQL_WLONGVARCHAR:
-            case OdbcTypes.SQL_WVARCHAR:
-                return SqlListenerDataTypes.VARCHAR;
-
-            case OdbcTypes.SQL_DOUBLE:
-            case OdbcTypes.SQL_FLOAT:
-                return SqlListenerDataTypes.DOUBLE;
-
-            case OdbcTypes.SQL_REAL:
-                return SqlListenerDataTypes.REAL;
-
-            case OdbcTypes.SQL_GUID:
-                return SqlListenerDataTypes.UUID;
-
-            case OdbcTypes.SQL_SMALLINT:
-                return SqlListenerDataTypes.SMALLINT;
-
-            case OdbcTypes.SQL_INTEGER:
-                return SqlListenerDataTypes.INTEGER;
-
-            case OdbcTypes.SQL_DATE:
-                return SqlListenerDataTypes.DATE;
-
-            case OdbcTypes.SQL_TIME:
-                return SqlListenerDataTypes.TIME;
-
-            case OdbcTypes.SQL_TIMESTAMP:
-                return SqlListenerDataTypes.TIMESTAMP;
-
-            case OdbcTypes.SQL_TINYINT:
-                return SqlListenerDataTypes.TINYINT;
-
-            //No support for interval types
-            case OdbcTypes.SQL_INTERVAL_SECOND:
-            case OdbcTypes.SQL_INTERVAL_MINUTE:
-            case OdbcTypes.SQL_INTERVAL_HOUR:
-            case OdbcTypes.SQL_INTERVAL_DAY:
-            case OdbcTypes.SQL_INTERVAL_MONTH:
-            case OdbcTypes.SQL_INTERVAL_YEAR:
-            case OdbcTypes.SQL_INTERVAL_YEAR_TO_MONTH:
-            case OdbcTypes.SQL_INTERVAL_HOUR_TO_MINUTE:
-            case OdbcTypes.SQL_INTERVAL_HOUR_TO_SECOND:
-            case OdbcTypes.SQL_INTERVAL_MINUTE_TO_SECOND:
-            case OdbcTypes.SQL_INTERVAL_DAY_TO_HOUR:
-            case OdbcTypes.SQL_INTERVAL_DAY_TO_MINUTE:
-            case OdbcTypes.SQL_INTERVAL_DAY_TO_SECOND:
-                throw new IgniteException("Unsupported ODBC data type '" + odbcDataType + "'");
-
-            default:
-                throw new IgniteException("Invalid ODBC data type '" + odbcDataType + "'");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerDataTypes.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerDataTypes.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerDataTypes.java
index 0f0bfdd..c25b89d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerDataTypes.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerDataTypes.java
@@ -23,47 +23,47 @@ package org.apache.ignite.internal.processors.odbc;
  */
 public class SqlListenerDataTypes {
     /** Type name for 64-bit integer */
-    static final String BIGINT = "BIGINT";
+    public static final String BIGINT = "BIGINT";
 
     /** Type name for byte array */
-    static final String BINARY = "BINARY";
+    public static final String BINARY = "BINARY";
 
     /** Type name for boolean flag */
-    static final String BIT = "BIT";
+    public static final String BIT = "BIT";
 
     /** Type name for unicode string */
-    static final String CHAR = "CHAR";
+    public static final String CHAR = "CHAR";
 
     /** Type name for decimal number */
-    static final String DECIMAL = "DECIMAL";
+    public static final String DECIMAL = "DECIMAL";
 
     /** Type name for unicode string */
-    static final String VARCHAR = "VARCHAR";
+    public static final String VARCHAR = "VARCHAR";
 
     /** Type name for floating point number */
-    static final String DOUBLE = "DOUBLE";
+    public static final String DOUBLE = "DOUBLE";
 
     /** Type name for single precision floating point number */
-    static final String REAL = "REAL";
+    public static final String REAL = "REAL";
 
     /** Type name for universally unique identifier */
-    static final String UUID = "UUID";
+    public static final String UUID = "UUID";
 
     /** Type name for 16-bit integer */
-    static final String SMALLINT = "SMALLINT";
+    public static final String SMALLINT = "SMALLINT";
 
     /** Type name for 32-bit integer */
-    static final String INTEGER = "INTEGER";
+    public static final String INTEGER = "INTEGER";
 
     /** Type name for 8-bit integer */
-    static final String TINYINT = "TINYINT";
+    public static final String TINYINT = "TINYINT";
 
     /** Type name for date */
-    static final String DATE = "DATE";
+    public static final String DATE = "DATE";
 
     /** Type name for time */
-    static final String TIME = "TIME";
+    public static final String TIME = "TIME";
 
     /** Type name for timestamp */
-    static final String TIMESTAMP = "TIMESTAMP";
+    public static final String TIMESTAMP = "TIMESTAMP";
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
index e46ee50..f8f595f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
@@ -39,7 +39,7 @@ import org.apache.ignite.internal.util.nio.GridNioSessionMetaKey;
 import org.jetbrains.annotations.Nullable;
 
 /**
- * ODBC message listener.
+ * SQL message listener.
  */
 public class SqlListenerNioListener extends GridNioServerListenerAdapter<byte[]> {
     /** The value corresponds to ODBC driver of the parser field of the handshake request. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessor.java
index 7ac0929..9a30d54 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessor.java
@@ -24,6 +24,7 @@ import java.util.concurrent.LinkedBlockingQueue;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.configuration.SqlConnectorConfiguration;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.GridProcessorAdapter;
 import org.apache.ignite.internal.util.GridSpinBusyLock;
@@ -37,28 +38,26 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.spi.IgnitePortProtocol;
 import org.apache.ignite.thread.IgniteThreadPoolExecutor;
+import org.jetbrains.annotations.Nullable;
 
 /**
- * ODBC processor.
+ * SQL processor.
  */
 public class SqlListenerProcessor extends GridProcessorAdapter {
     /** Default number of selectors. */
     private static final int DFLT_SELECTOR_CNT = Math.min(4, Runtime.getRuntime().availableProcessors());
 
-    /** Default TCP_NODELAY flag. */
-    private static final boolean DFLT_TCP_NODELAY = true;
-
     /** Default TCP direct buffer flag. */
     private static final boolean DFLT_TCP_DIRECT_BUF = false;
 
     /** Busy lock. */
     private final GridSpinBusyLock busyLock = new GridSpinBusyLock();
 
-    /** ODBC TCP Server. */
+    /** TCP Server. */
     private GridNioServer<byte[]> srv;
 
-    /** ODBC executor service. */
-    private ExecutorService odbcExecSvc;
+    /** Executor service. */
+    private ExecutorService execSvc;
 
     /**
      * @param ctx Kernal context.
@@ -71,71 +70,69 @@ public class SqlListenerProcessor extends GridProcessorAdapter {
     @Override public void start(boolean activeOnStart) throws IgniteCheckedException {
         IgniteConfiguration cfg = ctx.config();
 
-        OdbcConfiguration odbcCfg = cfg.getOdbcConfiguration();
+        SqlConnectorConfiguration sqlCfg = prepareConfiguration(cfg);
 
-        if (odbcCfg != null) {
+        if (sqlCfg != null) {
             try {
-                HostAndPortRange hostPort;
-
-                if (F.isEmpty(odbcCfg.getEndpointAddress())) {
-                    hostPort = new HostAndPortRange(OdbcConfiguration.DFLT_TCP_HOST,
-                        OdbcConfiguration.DFLT_TCP_PORT_FROM,
-                        OdbcConfiguration.DFLT_TCP_PORT_TO
-                    );
-                }
-                else {
-                    hostPort = HostAndPortRange.parse(odbcCfg.getEndpointAddress(),
-                        OdbcConfiguration.DFLT_TCP_PORT_FROM,
-                        OdbcConfiguration.DFLT_TCP_PORT_TO,
-                        "Failed to parse ODBC endpoint address"
-                    );
-                }
+                validateConfiguration(sqlCfg);
 
-                assertParameter(odbcCfg.getThreadPoolSize() > 0, "threadPoolSize > 0");
+                // Resolve host.
+                String host = sqlCfg.getHost();
 
-                odbcExecSvc = new IgniteThreadPoolExecutor(
-                    "odbc",
-                    cfg.getIgniteInstanceName(),
-                    odbcCfg.getThreadPoolSize(),
-                    odbcCfg.getThreadPoolSize(),
-                    0,
-                    new LinkedBlockingQueue<Runnable>());
+                if (host == null)
+                    host = cfg.getLocalHost();
 
-                InetAddress host;
+                InetAddress hostAddr;
 
                 try {
-                    host = InetAddress.getByName(hostPort.host());
+                    hostAddr = U.resolveLocalHost(host);
                 }
                 catch (Exception e) {
-                    throw new IgniteCheckedException("Failed to resolve ODBC host: " + hostPort.host(), e);
+                    throw new IgniteCheckedException("Failed to resolve SQL connector host: " + host, e);
                 }
 
+                execSvc = new IgniteThreadPoolExecutor(
+                    "sql-connector",
+                    cfg.getIgniteInstanceName(),
+                    sqlCfg.getThreadPoolSize(),
+                    sqlCfg.getThreadPoolSize(),
+                    0,
+                    new LinkedBlockingQueue<Runnable>());
+
                 Exception lastErr = null;
 
-                for (int port = hostPort.portFrom(); port <= hostPort.portTo(); port++) {
+                int portTo = sqlCfg.getPort() + sqlCfg.getPortRange();
+
+                if (portTo <= 0) // Handle int overflow.
+                    portTo = Integer.MAX_VALUE;
+
+                for (int port = sqlCfg.getPort(); port <= portTo && port <= 65535; port++) {
                     try {
                         GridNioFilter[] filters = new GridNioFilter[] {
-                            new GridNioAsyncNotifyFilter(ctx.igniteInstanceName(), odbcExecSvc, log) {
-                                @Override public void onSessionOpened(GridNioSession ses) throws IgniteCheckedException {
+                            new GridNioAsyncNotifyFilter(ctx.igniteInstanceName(), execSvc, log) {
+                                @Override public void onSessionOpened(GridNioSession ses)
+                                    throws IgniteCheckedException {
                                     proceedSessionOpened(ses);
                                 }
                             },
                             new GridNioCodecFilter(new SqlListenerBufferedParser(), log, false)
                         };
 
+                        int maxOpenCursors = sqlCfg.getMaxOpenCursorsPerConnection();
+
                         GridNioServer<byte[]> srv0 = GridNioServer.<byte[]>builder()
-                            .address(host)
+                            .address(hostAddr)
                             .port(port)
-                            .listener(new SqlListenerNioListener(ctx, busyLock, odbcCfg.getMaxOpenCursors()))
+                            .listener(new SqlListenerNioListener(ctx, busyLock, maxOpenCursors))
                             .logger(log)
                             .selectorCount(DFLT_SELECTOR_CNT)
                             .igniteInstanceName(ctx.igniteInstanceName())
-                            .serverName("odbc")
-                            .tcpNoDelay(DFLT_TCP_NODELAY)
+                            .serverName("sql-listener")
+                            .tcpNoDelay(sqlCfg.isTcpNoDelay())
                             .directBuffer(DFLT_TCP_DIRECT_BUF)
                             .byteOrder(ByteOrder.nativeOrder())
-                            .socketSendBufferSize(odbcCfg.getSocketSendBufferSize())
-                            .socketReceiveBufferSize(odbcCfg.getSocketReceiveBufferSize())
+                            .socketSendBufferSize(sqlCfg.getSocketSendBufferSize())
+                            .socketReceiveBufferSize(sqlCfg.getSocketReceiveBufferSize())
                             .filters(filters)
                             .directMode(false)
                             .idleTimeout(Long.MAX_VALUE)
@@ -147,7 +144,7 @@ public class SqlListenerProcessor extends GridProcessorAdapter {
 
                         ctx.ports().registerPort(port, IgnitePortProtocol.TCP, getClass());
 
-                        log.info("ODBC processor has started on TCP port " + port);
+                        log.info("SQL connector processor has started on TCP port " + port);
 
                         lastErr = null;
 
@@ -162,10 +159,11 @@ public class SqlListenerProcessor extends GridProcessorAdapter {
 
                 if (lastErr != null)
                     throw new IgniteCheckedException("Failed to bind to any [host:port] from the range [" +
-                        "address=" + hostPort + ", lastErr=" + lastErr + ']');
+                        "host=" + host + ", portFrom=" + sqlCfg.getPort() + ", portTo=" + portTo +
+                        ", lastErr=" + lastErr + ']');
             }
             catch (Exception e) {
-                throw new IgniteCheckedException("Failed to start ODBC processor.", e);
+                throw new IgniteCheckedException("Failed to start SQL connector processor.", e);
             }
         }
     }
@@ -179,14 +177,101 @@ public class SqlListenerProcessor extends GridProcessorAdapter {
 
             ctx.ports().deregisterPorts(getClass());
 
-            if (odbcExecSvc != null) {
-                U.shutdownNow(getClass(), odbcExecSvc, log);
+            if (execSvc != null) {
+                U.shutdownNow(getClass(), execSvc, log);
 
-                odbcExecSvc = null;
+                execSvc = null;
             }
 
             if (log.isDebugEnabled())
-                log.debug("ODBC processor stopped.");
+                log.debug("SQL connector processor stopped.");
         }
     }
+
+    /**
+     * Prepare connector configuration.
+     *
+     * @param cfg Ignote configuration.
+     * @return Connector configuration.
+     * @throws IgniteCheckedException If failed.
+     */
+    @SuppressWarnings("deprecation")
+    @Nullable private SqlConnectorConfiguration prepareConfiguration(IgniteConfiguration cfg)
+        throws IgniteCheckedException {
+        SqlConnectorConfiguration res = cfg.getSqlConnectorConfiguration();
+
+        OdbcConfiguration odbcCfg = cfg.getOdbcConfiguration();
+
+        if (odbcCfg != null) {
+            if (res == null) {
+                // SQL connector is either default or null, so we replace it with ODBC stuff.
+                HostAndPortRange hostAndPort = parseOdbcEndpoint(odbcCfg);
+
+                res = new SqlConnectorConfiguration();
+
+                res.setHost(hostAndPort.host());
+                res.setPort(hostAndPort.portFrom());
+                res.setPortRange(hostAndPort.portTo() - hostAndPort.portFrom());
+                res.setThreadPoolSize(odbcCfg.getThreadPoolSize());
+                res.setSocketSendBufferSize(odbcCfg.getSocketSendBufferSize());
+                res.setSocketReceiveBufferSize(odbcCfg.getSocketReceiveBufferSize());
+                res.setMaxOpenCursorsPerConnection(odbcCfg.getMaxOpenCursors());
+
+                U.warn(log, "Automatically converted deprecated ODBC configuration to SQL connector configuration: " +
+                    res);
+            }
+            else {
+                // Non-default SQL connector is set, ignore ODBC.
+                U.warn(log, "Deprecated ODBC configuration will be ignored because SQL connector configuration is " +
+                    "set (either migrate to new SqlConnectorConfiguration or set " +
+                    "IgniteConfiguration.sqlConnectorConfiguration to null explicitly).");
+            }
+        }
+
+        return res;
+    }
+
+    /**
+     * Validate SQL connector configuration.
+     *
+     * @param cfg Configuration.
+     * @throws IgniteCheckedException If failed.
+     */
+    private void validateConfiguration(SqlConnectorConfiguration cfg) throws IgniteCheckedException {
+        assertParameter(cfg.getPort() > 1024, "port > 1024");
+        assertParameter(cfg.getPort() <= 65535, "port <= 65535");
+        assertParameter(cfg.getPortRange() >= 0, "portRange > 0");
+        assertParameter(cfg.getSocketSendBufferSize() >= 0, "socketSendBufferSize > 0");
+        assertParameter(cfg.getSocketReceiveBufferSize() >= 0, "socketReceiveBufferSize > 0");
+        assertParameter(cfg.getMaxOpenCursorsPerConnection() >= 0, "maxOpenCursorsPerConnection() >= 0");
+        assertParameter(cfg.getThreadPoolSize() > 0, "threadPoolSize > 0");
+    }
+
+    /**
+     * Parse ODBC endpoint.
+     *
+     * @param odbcCfg ODBC configuration.
+     * @return ODBC host and port range.
+     * @throws IgniteCheckedException If failed.
+     */
+    @SuppressWarnings("deprecation")
+    private HostAndPortRange parseOdbcEndpoint(OdbcConfiguration odbcCfg) throws IgniteCheckedException {
+        HostAndPortRange res;
+
+        if (F.isEmpty(odbcCfg.getEndpointAddress())) {
+            res = new HostAndPortRange(OdbcConfiguration.DFLT_TCP_HOST,
+                OdbcConfiguration.DFLT_TCP_PORT_FROM,
+                OdbcConfiguration.DFLT_TCP_PORT_TO
+            );
+        }
+        else {
+            res = HostAndPortRange.parse(odbcCfg.getEndpointAddress(),
+                OdbcConfiguration.DFLT_TCP_PORT_FROM,
+                OdbcConfiguration.DFLT_TCP_PORT_TO,
+                "Failed to parse SQL connector endpoint address"
+            );
+        }
+
+        return res;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcColumnMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcColumnMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcColumnMeta.java
index d9d39de..1d4f1a8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcColumnMeta.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcColumnMeta.java
@@ -19,7 +19,6 @@ package org.apache.ignite.internal.processors.odbc.odbc;
 
 import org.apache.ignite.binary.BinaryRawWriter;
 import org.apache.ignite.internal.binary.BinaryUtils;
-import org.apache.ignite.internal.processors.odbc.OdbcUtils;
 import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
 
 /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
index a520d96..dfcd462 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
@@ -33,7 +33,6 @@ import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.binary.GridBinaryMarshaller;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
-import org.apache.ignite.internal.processors.odbc.OdbcUtils;
 import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
 import org.apache.ignite.internal.processors.odbc.SqlListenerRequestHandler;
 import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTableMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTableMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTableMeta.java
index d680435..a6bb178 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTableMeta.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTableMeta.java
@@ -20,7 +20,6 @@ package org.apache.ignite.internal.processors.odbc.odbc;
 import org.apache.ignite.internal.binary.BinaryRawWriterEx;
 
 import java.util.Objects;
-import org.apache.ignite.internal.processors.odbc.OdbcUtils;
 
 /**
  * ODBC table-related metadata.

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTypes.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTypes.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTypes.java
new file mode 100644
index 0000000..650066f
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTypes.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc.odbc;
+
+/**
+ * Data type names that can occur within ODBC escape sequence
+ */
+public class OdbcTypes {
+    /** Type name for BIGINT */
+    static final String SQL_BIGINT = "SQL_BIGINT";
+
+    /** Type name for BINARY */
+    static final String SQL_BINARY = "SQL_BINARY";
+
+    /** Type name for LONGVARBINARY */
+    static final String SQL_LONGVARBINARY = "SQL_LONGVARBINARY";
+
+    /** Type name for VARBINARY */
+    static final String SQL_VARBINARY = "SQL_VARBINARY";
+
+    /** Type name for BIT */
+    static final String SQL_BIT = "SQL_BIT";
+
+    /** Type name for CHAR */
+    static final String SQL_CHAR = "SQL_CHAR";
+
+    /** Type name for DECIMAL */
+    static final String SQL_DECIMAL = "SQL_DECIMAL";
+
+    /** Type name for NUMERIC */
+    static final String SQL_NUMERIC = "SQL_NUMERIC";
+
+    /** Type name for LONGVARCHAR */
+    static final String SQL_LONGVARCHAR = "SQL_LONGVARCHAR";
+
+    /** Type name for VARCHAR */
+    static final String SQL_VARCHAR = "SQL_VARCHAR";
+
+    /** Type name for WCHAR */
+    static final String SQL_WCHAR = "SQL_WCHAR";
+
+    /** Type name for WLONGVARCHAR */
+    static final String SQL_WLONGVARCHAR = "SQL_WLONGVARCHAR";
+
+    /** Type name for WVARCHAR */
+    static final String SQL_WVARCHAR = "SQL_WVARCHAR";
+
+    /** Type name for DOUBLE */
+    static final String SQL_DOUBLE = "SQL_DOUBLE";
+
+    /** Type name for FLOAT */
+    static final String SQL_FLOAT = "SQL_FLOAT";
+
+    /** Type name for REAL */
+    static final String SQL_REAL = "SQL_REAL";
+
+    /** Type name for GUID */
+    static final String SQL_GUID = "SQL_GUID";
+
+    /** Type name for SMALLINT */
+    static final String SQL_SMALLINT = "SQL_SMALLINT";
+
+    /** Type name for INTEGER */
+    static final String SQL_INTEGER = "SQL_INTEGER";
+
+    /** Type name for DATE */
+    static final String SQL_DATE = "SQL_DATE";
+
+    /** Type name for TIME */
+    static final String SQL_TIME = "SQL_TIME";
+
+    /** Type name for TIMESTAMP */
+    static final String SQL_TIMESTAMP = "SQL_TIMESTAMP";
+
+    /** Type name for TINYINT */
+    static final String SQL_TINYINT = "SQL_TINYINT";
+
+    /** Type name for INTERVAL_SECOND */
+    static final String SQL_INTERVAL_SECOND = "SQL_INTERVAL_SECOND";
+
+    /** Type name for INTERVAL_MINUTE */
+    static final String SQL_INTERVAL_MINUTE = "SQL_INTERVAL_MINUTE";
+
+    /** Type name for INTERVAL_HOUR */
+    static final String SQL_INTERVAL_HOUR = "SQL_INTERVAL_HOUR";
+
+    /** Type name for INTERVAL_DAY */
+    static final String SQL_INTERVAL_DAY = "SQL_INTERVAL_DAY";
+
+    /** Type name for INTERVAL_MONTH */
+    static final String SQL_INTERVAL_MONTH = "SQL_INTERVAL_MONTH";
+
+    /** Type name for INTERVAL_YEAR */
+    static final String SQL_INTERVAL_YEAR = "SQL_INTERVAL_YEAR";
+
+    /** Type name for INTERVAL_YEAR_TO_MONTH */
+    static final String SQL_INTERVAL_YEAR_TO_MONTH = "SQL_INTERVAL_YEAR_TO_MONTH";
+
+    /** Type name for INTERVAL_HOUR_TO_MINUTE */
+    static final String SQL_INTERVAL_HOUR_TO_MINUTE = "SQL_INTERVAL_HOUR_TO_MINUTE";
+
+    /** Type name for INTERVAL_HOUR_TO_SECOND */
+    static final String SQL_INTERVAL_HOUR_TO_SECOND = "SQL_INTERVAL_HOUR_TO_SECOND";
+
+    /** Type name for INTERVAL_MINUTE_TO_SECOND */
+    static final String SQL_INTERVAL_MINUTE_TO_SECOND = "SQL_INTERVAL_MINUTE_TO_SECOND";
+
+    /** Type name for INTERVAL_DAY_TO_HOUR */
+    static final String SQL_INTERVAL_DAY_TO_HOUR = "SQL_INTERVAL_DAY_TO_HOUR";
+
+    /** Type name for INTERVAL_DAY_TO_MINUTE */
+    static final String SQL_INTERVAL_DAY_TO_MINUTE = "SQL_INTERVAL_DAY_TO_MINUTE";
+
+    /** Type name for INTERVAL_DAY_TO_SECOND */
+    static final String SQL_INTERVAL_DAY_TO_SECOND  = "SQL_INTERVAL_DAY_TO_SECOND";
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcUtils.java
new file mode 100644
index 0000000..9bdd0c7
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcUtils.java
@@ -0,0 +1,142 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.processors.odbc.SqlListenerDataTypes;
+
+/**
+ * Various ODBC utility methods.
+ */
+public class OdbcUtils {
+    /**
+     * Add quotation marks at the beginning and end of the string.
+     *
+     * @param str Input string.
+     * @return String surrounded with quotation marks.
+     */
+    public static String addQuotationMarksIfNeeded(String str) {
+        if (str != null && !str.isEmpty() && !(str.startsWith("\"") && str.endsWith("\"")))
+            return "\"" + str + "\"";
+
+        return str;
+    }
+
+    /**
+     * Remove quotation marks at the beginning and end of the string if present.
+     *
+     * @param str Input string.
+     * @return String without leading and trailing quotation marks.
+     */
+    public static String removeQuotationMarksIfNeeded(String str) {
+        if (str != null && str.startsWith("\"") && str.endsWith("\""))
+            return str.substring(1, str.length() - 1);
+
+        return str;
+    }
+
+    /**
+     * Private constructor.
+     */
+    private OdbcUtils() {
+        // No-op.
+    }
+
+    /**
+     * Lookup Ignite data type corresponding to specific ODBC data type
+     *
+     * @param odbcDataType ODBC data type identifier
+     * @return Ignite data type name
+     */
+    public static String getIgniteTypeFromOdbcType(String odbcDataType) {
+        assert odbcDataType != null;
+        switch (odbcDataType.toUpperCase()) {
+            case OdbcTypes.SQL_BIGINT:
+                return SqlListenerDataTypes.BIGINT;
+
+            case OdbcTypes.SQL_BINARY:
+            case OdbcTypes.SQL_LONGVARBINARY:
+            case OdbcTypes.SQL_VARBINARY:
+                return SqlListenerDataTypes.BINARY;
+
+            case OdbcTypes.SQL_BIT:
+                return SqlListenerDataTypes.BIT;
+
+            case OdbcTypes.SQL_CHAR:
+                return SqlListenerDataTypes.CHAR;
+
+            case OdbcTypes.SQL_DECIMAL:
+            case OdbcTypes.SQL_NUMERIC:
+                return SqlListenerDataTypes.DECIMAL;
+
+            case OdbcTypes.SQL_LONGVARCHAR:
+            case OdbcTypes.SQL_VARCHAR:
+            case OdbcTypes.SQL_WCHAR:
+            case OdbcTypes.SQL_WLONGVARCHAR:
+            case OdbcTypes.SQL_WVARCHAR:
+                return SqlListenerDataTypes.VARCHAR;
+
+            case OdbcTypes.SQL_DOUBLE:
+            case OdbcTypes.SQL_FLOAT:
+                return SqlListenerDataTypes.DOUBLE;
+
+            case OdbcTypes.SQL_REAL:
+                return SqlListenerDataTypes.REAL;
+
+            case OdbcTypes.SQL_GUID:
+                return SqlListenerDataTypes.UUID;
+
+            case OdbcTypes.SQL_SMALLINT:
+                return SqlListenerDataTypes.SMALLINT;
+
+            case OdbcTypes.SQL_INTEGER:
+                return SqlListenerDataTypes.INTEGER;
+
+            case OdbcTypes.SQL_DATE:
+                return SqlListenerDataTypes.DATE;
+
+            case OdbcTypes.SQL_TIME:
+                return SqlListenerDataTypes.TIME;
+
+            case OdbcTypes.SQL_TIMESTAMP:
+                return SqlListenerDataTypes.TIMESTAMP;
+
+            case OdbcTypes.SQL_TINYINT:
+                return SqlListenerDataTypes.TINYINT;
+
+            //No support for interval types
+            case OdbcTypes.SQL_INTERVAL_SECOND:
+            case OdbcTypes.SQL_INTERVAL_MINUTE:
+            case OdbcTypes.SQL_INTERVAL_HOUR:
+            case OdbcTypes.SQL_INTERVAL_DAY:
+            case OdbcTypes.SQL_INTERVAL_MONTH:
+            case OdbcTypes.SQL_INTERVAL_YEAR:
+            case OdbcTypes.SQL_INTERVAL_YEAR_TO_MONTH:
+            case OdbcTypes.SQL_INTERVAL_HOUR_TO_MINUTE:
+            case OdbcTypes.SQL_INTERVAL_HOUR_TO_SECOND:
+            case OdbcTypes.SQL_INTERVAL_MINUTE_TO_SECOND:
+            case OdbcTypes.SQL_INTERVAL_DAY_TO_HOUR:
+            case OdbcTypes.SQL_INTERVAL_DAY_TO_MINUTE:
+            case OdbcTypes.SQL_INTERVAL_DAY_TO_SECOND:
+                throw new IgniteException("Unsupported ODBC data type '" + odbcDataType + "'");
+
+            default:
+                throw new IgniteException("Invalid ODBC data type '" + odbcDataType + "'");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/escape/OdbcEscapeUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/escape/OdbcEscapeUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/escape/OdbcEscapeUtils.java
index cd97667..70a284d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/escape/OdbcEscapeUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/escape/OdbcEscapeUtils.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.internal.processors.odbc.odbc.escape;
 
 import org.apache.ignite.IgniteException;
-import org.apache.ignite.internal.processors.odbc.OdbcUtils;
+import org.apache.ignite.internal.processors.odbc.odbc.OdbcUtils;
 
 import java.util.LinkedList;
 import java.util.regex.Matcher;

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcConfigurationValidationSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcConfigurationValidationSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcConfigurationValidationSelfTest.java
new file mode 100644
index 0000000..ae3f592
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcConfigurationValidationSelfTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.processors.odbc;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * ODBC configuration validation tests.
+ */
+@SuppressWarnings("deprecation")
+public class OdbcConfigurationValidationSelfTest extends GridCommonAbstractTest {
+    /** Node index generator. */
+    private static final AtomicInteger NODE_IDX_GEN = new AtomicInteger();
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * Ensure we can start with default configuration.
+     *
+     * @throws Exception If failed.
+     */
+    public void testAddressDefault() throws Exception {
+        check(new OdbcConfiguration(), true);
+    }
+
+    /**
+     * Test address where only host is provided.
+     *
+     * @throws Exception If failed.
+     */
+    public void testAddressHostOnly() throws Exception {
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1"), true);
+    }
+
+    /**
+     * Test address with both host and port.
+     *
+     * @throws Exception If failed.
+     */
+    public void testAddressHostAndPort() throws Exception {
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999"), true);
+
+        // Shouldn't fit into range.
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999"), false);
+    }
+
+    /**
+     * Test address with host and port range.
+     *
+     * @throws Exception If failed.
+     */
+    public void testAddressHostAndPortRange() throws Exception {
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999..10000"), true);
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999..10000"), true);
+
+        // Shouldn't fit into range.
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999..10000"), false);
+    }
+
+    /**
+     * Test start with invalid host.
+     *
+     * @throws Exception If failed.
+     */
+    public void testAddressInvalidHost() throws Exception {
+        check(new OdbcConfiguration().setEndpointAddress("126.0.0.1"), false);
+    }
+
+    /**
+     * Test start with invalid address format.
+     *
+     * @throws Exception If failed.
+     */
+    public void testAddressInvalidFormat() throws Exception {
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:"), false);
+
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:0"), false);
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:-1"), false);
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:111111"), false);
+
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999.."), false);
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999..9998"), false);
+
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:a"), false);
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:a.."), false);
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:a..b"), false);
+
+        check(new OdbcConfiguration().setEndpointAddress(":9999"), false);
+        check(new OdbcConfiguration().setEndpointAddress(":9999..10000"), false);
+    }
+
+    /**
+     * Test connection parameters: sendBufferSize, receiveBufferSize, connectionTimeout.
+     *
+     * @throws Exception If failed.
+     */
+    public void testConnectionParams() throws Exception {
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9998..10000")
+            .setSocketSendBufferSize(4 * 1024), true);
+
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9998..10000")
+            .setSocketReceiveBufferSize(4 * 1024), true);
+
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9998..10000")
+            .setSocketSendBufferSize(-64 * 1024), false);
+
+        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9998..10000")
+            .setSocketReceiveBufferSize(-64 * 1024), false);
+    }
+
+    /**
+     * Test thread pool size.
+     *
+     * @throws Exception If failed.
+     */
+    public void testThreadPoolSize() throws Exception {
+        check(new OdbcConfiguration().setThreadPoolSize(0), false);
+        check(new OdbcConfiguration().setThreadPoolSize(-1), false);
+
+        check(new OdbcConfiguration().setThreadPoolSize(4), true);
+    }
+
+    /**
+     * Perform check.
+     *
+     * @param odbcCfg ODBC configuration.
+     * @param success Success flag. * @throws Exception If failed.
+     */
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    private void check(OdbcConfiguration odbcCfg, boolean success) throws Exception {
+        final IgniteConfiguration cfg = super.getConfiguration();
+
+        cfg.setIgniteInstanceName(OdbcConfigurationValidationSelfTest.class.getName() + "-" +
+            NODE_IDX_GEN.incrementAndGet());
+
+        cfg.setLocalHost("127.0.0.1");
+        cfg.setSqlConnectorConfiguration(null);
+        cfg.setOdbcConfiguration(odbcCfg);
+        cfg.setMarshaller(new BinaryMarshaller());
+
+        TcpDiscoverySpi spi = new TcpDiscoverySpi();
+        spi.setIpFinder(new TcpDiscoveryVmIpFinder(true));
+
+        cfg.setDiscoverySpi(spi);
+
+        if (success)
+            startGrid(cfg.getIgniteInstanceName(), cfg);
+        else {
+            GridTestUtils.assertThrows(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    startGrid(cfg.getIgniteInstanceName(), cfg);
+
+                    return null;
+                }
+            }, IgniteException.class, null);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessorValidationSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessorValidationSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessorValidationSelfTest.java
deleted file mode 100644
index e433b6c..0000000
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessorValidationSelfTest.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicInteger;
-import org.apache.ignite.IgniteException;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.OdbcConfiguration;
-import org.apache.ignite.internal.binary.BinaryMarshaller;
-import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
-import org.apache.ignite.testframework.GridTestUtils;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-
-/**
- * ODBC configuration validation tests.
- */
-public class SqlListenerProcessorValidationSelfTest extends GridCommonAbstractTest {
-    /** Node index generator. */
-    private static final AtomicInteger NODE_IDX_GEN = new AtomicInteger();
-
-    /** {@inheritDoc} */
-    @Override protected void afterTest() throws Exception {
-        stopAllGrids();
-    }
-
-    /**
-     * Ensure we can start with default configuration.
-     *
-     * @throws Exception If failed.
-     */
-    public void testAddressDefault() throws Exception {
-        check(new OdbcConfiguration(), true);
-    }
-
-    /**
-     * Test address where only host is provided.
-     *
-     * @throws Exception If failed.
-     */
-    public void testAddressHostOnly() throws Exception {
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1"), true);
-    }
-
-    /**
-     * Test address with both host and port.
-     *
-     * @throws Exception If failed.
-     */
-    public void testAddressHostAndPort() throws Exception {
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999"), true);
-
-        // Shouldn't fit into range.
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999"), false);
-    }
-
-    /**
-     * Test address with host and port range.
-     *
-     * @throws Exception If failed.
-     */
-    public void testAddressHostAndPortRange() throws Exception {
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999..10000"), true);
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999..10000"), true);
-
-        // Shouldn't fit into range.
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999..10000"), false);
-    }
-
-    /**
-     * Test start with invalid host.
-     *
-     * @throws Exception If failed.
-     */
-    public void testAddressInvalidHost() throws Exception {
-        check(new OdbcConfiguration().setEndpointAddress("126.0.0.1"), false);
-    }
-
-    /**
-     * Test start with invalid address format.
-     *
-     * @throws Exception If failed.
-     */
-    public void testAddressInvalidFormat() throws Exception {
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:"), false);
-
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:0"), false);
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:-1"), false);
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:111111"), false);
-
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999.."), false);
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9999..9998"), false);
-
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:a"), false);
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:a.."), false);
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:a..b"), false);
-
-        check(new OdbcConfiguration().setEndpointAddress(":9999"), false);
-        check(new OdbcConfiguration().setEndpointAddress(":9999..10000"), false);
-    }
-
-    /**
-     * Test connection parameters: sendBufferSize, receiveBufferSize, connectionTimeout.
-     *
-     * @throws Exception If failed.
-     */
-    public void testConnectionParams() throws Exception {
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9998..10000")
-            .setSocketSendBufferSize(4 * 1024), true);
-
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9998..10000")
-            .setSocketReceiveBufferSize(4 * 1024), true);
-
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9998..10000")
-            .setSocketSendBufferSize(-64 * 1024), false);
-
-        check(new OdbcConfiguration().setEndpointAddress("127.0.0.1:9998..10000")
-            .setSocketReceiveBufferSize(-64 * 1024), false);
-    }
-
-    /**
-     * Test thread pool size.
-     *
-     * @throws Exception If failed.
-     */
-    public void testThreadPoolSize() throws Exception {
-        check(new OdbcConfiguration().setThreadPoolSize(0), false);
-        check(new OdbcConfiguration().setThreadPoolSize(-1), false);
-
-        check(new OdbcConfiguration().setThreadPoolSize(4), true);
-    }
-
-    /**
-     * Perform check.
-     *
-     * @param odbcCfg ODBC configuration.
-     * @param success Success flag. * @throws Exception If failed.
-     */
-    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
-    private void check(OdbcConfiguration odbcCfg, boolean success) throws Exception {
-        final IgniteConfiguration cfg = super.getConfiguration();
-
-        cfg.setIgniteInstanceName(SqlListenerProcessorValidationSelfTest.class.getName() + "-" +
-            NODE_IDX_GEN.incrementAndGet());
-
-        cfg.setLocalHost("127.0.0.1");
-        cfg.setOdbcConfiguration(odbcCfg);
-        cfg.setMarshaller(new BinaryMarshaller());
-
-        TcpDiscoverySpi spi = new TcpDiscoverySpi();
-        spi.setIpFinder(new TcpDiscoveryVmIpFinder(true));
-
-        cfg.setDiscoverySpi(spi);
-
-        if (success)
-            startGrid(cfg.getGridName(), cfg);
-        else {
-            GridTestUtils.assertThrows(log, new Callable<Void>() {
-                @Override public Void call() throws Exception {
-                    startGrid(cfg.getGridName(), cfg);
-
-                    return null;
-                }
-            }, IgniteException.class, null);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/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 46b1eb5..3305058 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
@@ -53,7 +53,7 @@ import org.apache.ignite.internal.processors.database.FreeListImplSelfTest;
 import org.apache.ignite.internal.processors.database.MemoryMetricsSelfTest;
 import org.apache.ignite.internal.processors.database.MetadataStorageSelfTest;
 import org.apache.ignite.internal.processors.odbc.OdbcEscapeSequenceSelfTest;
-import org.apache.ignite.internal.processors.odbc.SqlListenerProcessorValidationSelfTest;
+import org.apache.ignite.internal.processors.odbc.OdbcConfigurationValidationSelfTest;
 import org.apache.ignite.internal.processors.service.ClosureServiceClientsNodesTest;
 import org.apache.ignite.internal.product.GridProductVersionSelfTest;
 import org.apache.ignite.internal.util.nio.IgniteExceptionInNioWorkerSelfTest;
@@ -145,7 +145,7 @@ public class IgniteBasicTestSuite extends TestSuite {
 
         suite.addTestSuite(IgniteExceptionInNioWorkerSelfTest.class);
         suite.addTestSuite(IgniteLocalNodeMapBeforeStartTest.class);
-        suite.addTestSuite(SqlListenerProcessorValidationSelfTest.class);
+        suite.addTestSuite(OdbcConfigurationValidationSelfTest.class);
         suite.addTestSuite(OdbcEscapeSequenceSelfTest.class);
 
         GridTestUtils.addTestIfNeeded(suite, DynamicProxySerializationMultiJvmSelfTest.class, ignoredTests);

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 53201a7..e7f93c5 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -1830,7 +1830,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
 
         dbUrl = "jdbc:h2:mem:" + dbName + DB_OPTIONS;
 
-        org.h2.Driver.load();
+        //org.h2.Driver.load();
 
         try {
             if (getString(IGNITE_H2_DEBUG_CONSOLE) != null) {


[46/50] [abbrv] ignite git commit: IGNITE-5376: JDBC thin: added "collocated" and "replicatedOnly" flags.

Posted by sb...@apache.org.
IGNITE-5376: JDBC thin: added "collocated" and "replicatedOnly" flags.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a9733921
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a9733921
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a9733921

Branch: refs/heads/ignite-5075
Commit: a9733921f2203075738448806ce9713037361cb3
Parents: f060582
Author: devozerov <pp...@gmail.com>
Authored: Mon Jun 5 22:46:49 2017 +0300
Committer: devozerov <pp...@gmail.com>
Committed: Mon Jun 5 22:46:49 2017 +0300

----------------------------------------------------------------------
 .../jdbc/thin/JdbcThinConnectionSelfTest.java   | 84 +++++++++++++++++---
 .../org/apache/ignite/IgniteJdbcThinDriver.java |  4 +-
 .../internal/jdbc/thin/JdbcThinConnection.java  |  8 +-
 .../internal/jdbc/thin/JdbcThinTcpIo.java       | 45 ++++++++++-
 .../internal/jdbc/thin/JdbcThinUtils.java       | 12 +++
 .../processors/odbc/SqlListenerNioListener.java | 38 ++++-----
 .../odbc/jdbc/JdbcRequestHandler.java           | 14 +++-
 7 files changed, 166 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/a9733921/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
index 8407a15..7ea22d5 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
@@ -125,25 +125,75 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             "Property cannot be negative [name=" + JdbcThinUtils.PARAM_SOCK_RCV_BUF);
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
-            assertEquals(0, socket(conn).socketSendBuffer());
-            assertEquals(0, socket(conn).socketReceiveBuffer());
+            assertEquals(0, io(conn).socketSendBuffer());
+            assertEquals(0, io(conn).socketReceiveBuffer());
         }
 
         // Note that SO_* options are hints, so we check that value is equals to either what we set or to default.
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?socketSendBuffer=1024")) {
-            assertEquals(1024, socket(conn).socketSendBuffer());
-            assertEquals(0, socket(conn).socketReceiveBuffer());
+            assertEquals(1024, io(conn).socketSendBuffer());
+            assertEquals(0, io(conn).socketReceiveBuffer());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?socketReceiveBuffer=1024")) {
-            assertEquals(0, socket(conn).socketSendBuffer());
-            assertEquals(1024, socket(conn).socketReceiveBuffer());
+            assertEquals(0, io(conn).socketSendBuffer());
+            assertEquals(1024, io(conn).socketReceiveBuffer());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?" +
             "socketSendBuffer=1024&socketReceiveBuffer=2048")) {
-            assertEquals(1024, socket(conn).socketSendBuffer());
-            assertEquals(2048, socket(conn).socketReceiveBuffer());
+            assertEquals(1024, io(conn).socketSendBuffer());
+            assertEquals(2048, io(conn).socketReceiveBuffer());
+        }
+    }
+
+    /**
+     * Test SQL hints.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSqlHints() throws Exception {
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
+            assertFalse(io(conn).distributedJoins());
+            assertFalse(io(conn).enforceJoinOrder());
+            assertFalse(io(conn).collocated());
+            assertFalse(io(conn).replicatedOnly());
+        }
+
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?distributedJoins=true")) {
+            assertTrue(io(conn).distributedJoins());
+            assertFalse(io(conn).enforceJoinOrder());
+            assertFalse(io(conn).collocated());
+            assertFalse(io(conn).replicatedOnly());
+        }
+
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?enforceJoinOrder=true")) {
+            assertFalse(io(conn).distributedJoins());
+            assertTrue(io(conn).enforceJoinOrder());
+            assertFalse(io(conn).collocated());
+            assertFalse(io(conn).replicatedOnly());
+        }
+
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?collocated=true")) {
+            assertFalse(io(conn).distributedJoins());
+            assertFalse(io(conn).enforceJoinOrder());
+            assertTrue(io(conn).collocated());
+            assertFalse(io(conn).replicatedOnly());
+        }
+
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?replicatedOnly=true")) {
+            assertFalse(io(conn).distributedJoins());
+            assertFalse(io(conn).enforceJoinOrder());
+            assertFalse(io(conn).collocated());
+            assertTrue(io(conn).replicatedOnly());
+        }
+
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?distributedJoins=true&" +
+                "enforceJoinOrder=true&collocated=true&replicatedOnly=true")) {
+            assertTrue(io(conn).distributedJoins());
+            assertTrue(io(conn).enforceJoinOrder());
+            assertTrue(io(conn).collocated());
+            assertTrue(io(conn).replicatedOnly());
         }
     }
 
@@ -152,7 +202,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
      *
      * @throws Exception If failed.
      */
-    public void testPropertyTcpNoDelay() throws Exception {
+    public void testTcpNoDelay() throws Exception {
         assertInvalid("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=0",
             "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_TCP_NO_DELAY);
 
@@ -166,15 +216,23 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_TCP_NO_DELAY);
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
-            assertTrue(socket(conn).tcpNoDelay());
+            assertTrue(io(conn).tcpNoDelay());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=true")) {
-            assertTrue(socket(conn).tcpNoDelay());
+            assertTrue(io(conn).tcpNoDelay());
+        }
+
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=True")) {
+            assertTrue(io(conn).tcpNoDelay());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=false")) {
-            assertFalse(socket(conn).tcpNoDelay());
+            assertFalse(io(conn).tcpNoDelay());
+        }
+
+        try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=False")) {
+            assertFalse(io(conn).tcpNoDelay());
         }
     }
 
@@ -185,7 +243,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
      * @return Socket.
      * @throws Exception If failed.
      */
-    private static JdbcThinTcpIo socket(Connection conn) throws Exception {
+    private static JdbcThinTcpIo io(Connection conn) throws Exception {
         JdbcThinConnection conn0 = conn.unwrap(JdbcThinConnection.class);
 
         return conn0.io();

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9733921/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
index 7766d98..1392d62 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
@@ -184,7 +184,9 @@ public class IgniteJdbcThinDriver implements Driver {
             new JdbcDriverPropertyInfo("Hostname", info.getProperty(JdbcThinUtils.PROP_HOST), ""),
             new JdbcDriverPropertyInfo("Port number", info.getProperty(JdbcThinUtils.PROP_PORT), ""),
             new JdbcDriverPropertyInfo("Distributed Joins", info.getProperty(JdbcThinUtils.PROP_DISTRIBUTED_JOINS), ""),
-            new JdbcDriverPropertyInfo("Enforce Join Order", info.getProperty(JdbcThinUtils.PROP_ENFORCE_JOIN_ORDER), "")
+            new JdbcDriverPropertyInfo("Enforce Join Order", info.getProperty(JdbcThinUtils.PROP_ENFORCE_JOIN_ORDER), ""),
+            new JdbcDriverPropertyInfo("Collocated", info.getProperty(JdbcThinUtils.PROP_COLLOCATED), ""),
+            new JdbcDriverPropertyInfo("Replicated only", info.getProperty(JdbcThinUtils.PROP_REPLICATED_ONLY), "")
         );
 
         return props.toArray(new DriverPropertyInfo[0]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9733921/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
index b284f62..b372085 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
@@ -48,6 +48,8 @@ import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_HOST;
 import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_PORT;
 import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_DISTRIBUTED_JOINS;
 import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_ENFORCE_JOIN_ORDER;
+import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_COLLOCATED;
+import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_REPLICATED_ONLY;
 import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SOCK_SND_BUF;
 import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SOCK_RCV_BUF;
 import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_TCP_NO_DELAY;
@@ -102,6 +104,8 @@ public class JdbcThinConnection implements Connection {
 
         boolean distributedJoins = extractBoolean(props, PROP_DISTRIBUTED_JOINS, false);
         boolean enforceJoinOrder = extractBoolean(props, PROP_ENFORCE_JOIN_ORDER, false);
+        boolean collocated = extractBoolean(props, PROP_COLLOCATED, false);
+        boolean replicatedOnly = extractBoolean(props, PROP_REPLICATED_ONLY, false);
 
         int sockSndBuf = extractIntNonNegative(props, PROP_SOCK_SND_BUF, 0);
         int sockRcvBuf = extractIntNonNegative(props, PROP_SOCK_RCV_BUF, 0);
@@ -109,7 +113,7 @@ public class JdbcThinConnection implements Connection {
         boolean tcpNoDelay  = extractBoolean(props, PROP_TCP_NO_DELAY, true);
 
         try {
-            cliIo = new JdbcThinTcpIo(host, port, distributedJoins, enforceJoinOrder,
+            cliIo = new JdbcThinTcpIo(host, port, distributedJoins, enforceJoinOrder, collocated, replicatedOnly,
                 sockSndBuf, sockRcvBuf, tcpNoDelay);
 
             cliIo.start();
@@ -654,4 +658,4 @@ public class JdbcThinConnection implements Connection {
                 ", value=" + strVal + ']');
         }
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9733921/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
index 3f6edb8..bf8234d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
@@ -42,7 +42,6 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult;
-import org.apache.ignite.internal.util.ipc.IpcEndpoint;
 import org.apache.ignite.internal.util.ipc.loopback.IpcClientTcpEndpoint;
 import org.apache.ignite.internal.util.typedef.internal.U;
 
@@ -80,6 +79,12 @@ public class JdbcThinTcpIo {
     /** Enforce join order. */
     private final boolean enforceJoinOrder;
 
+    /** Collocated flag. */
+    private final boolean collocated;
+
+    /** Replicated only flag. */
+    private final boolean replicatedOnly;
+
     /** Socket send buffer. */
     private final int sockSndBuf;
 
@@ -108,16 +113,20 @@ public class JdbcThinTcpIo {
      * @param port Port.
      * @param distributedJoins Distributed joins flag.
      * @param enforceJoinOrder Enforce join order flag.
+     * @param collocated Collocated flag.
+     * @param replicatedOnly Replicated only flag.
      * @param sockSndBuf Socket send buffer.
      * @param sockRcvBuf Socket receive buffer.
      * @param tcpNoDelay TCP no delay flag.
      */
-    JdbcThinTcpIo(String host, int port, boolean distributedJoins, boolean enforceJoinOrder, int sockSndBuf,
-        int sockRcvBuf, boolean tcpNoDelay) {
+    JdbcThinTcpIo(String host, int port, boolean distributedJoins, boolean enforceJoinOrder, boolean collocated,
+        boolean replicatedOnly, int sockSndBuf, int sockRcvBuf, boolean tcpNoDelay) {
         this.host = host;
         this.port = port;
         this.distributedJoins = distributedJoins;
         this.enforceJoinOrder = enforceJoinOrder;
+        this.collocated = collocated;
+        this.replicatedOnly = replicatedOnly;
         this.sockSndBuf = sockSndBuf;
         this.sockRcvBuf = sockRcvBuf;
         this.tcpNoDelay = tcpNoDelay;
@@ -171,6 +180,8 @@ public class JdbcThinTcpIo {
 
         writer.writeBoolean(distributedJoins);
         writer.writeBoolean(enforceJoinOrder);
+        writer.writeBoolean(collocated);
+        writer.writeBoolean(replicatedOnly);
 
         send(writer.array());
 
@@ -343,6 +354,34 @@ public class JdbcThinTcpIo {
     }
 
     /**
+     * @return Distributed joins flag.
+     */
+    public boolean distributedJoins() {
+        return distributedJoins;
+    }
+
+    /**
+     * @return Enforce join order flag.
+     */
+    public boolean enforceJoinOrder() {
+        return enforceJoinOrder;
+    }
+
+    /**
+     * @return Collocated flag.
+     */
+    public boolean collocated() {
+        return collocated;
+    }
+
+    /**
+     * @return Replicated only flag.
+     */
+    public boolean replicatedOnly() {
+        return replicatedOnly;
+    }
+
+    /**
      * @return Socket send buffer size.
      */
     public int socketSendBuffer() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9733921/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
index 8d7d6b1..aa9b011 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
@@ -61,6 +61,12 @@ public class JdbcThinUtils {
     /** Parameter: enforce join order flag. */
     public static final String PARAM_ENFORCE_JOIN_ORDER = "enforceJoinOrder";
 
+    /** Parameter: collocated flag. */
+    public static final String PARAM_COLLOCATED = "collocated";
+
+    /** Parameter: replicated only flag. */
+    public static final String PARAM_REPLICATED_ONLY = "replicatedOnly";
+
     /** Parameter: socket send buffer. */
     public static final String PARAM_SOCK_SND_BUF = "socketSendBuffer";
 
@@ -76,6 +82,12 @@ public class JdbcThinUtils {
     /** Transactions allowed property name. */
     public static final String PROP_ENFORCE_JOIN_ORDER = PROP_PREFIX + PARAM_ENFORCE_JOIN_ORDER;
 
+    /** Collocated property name. */
+    public static final String PROP_COLLOCATED = PROP_PREFIX + PARAM_COLLOCATED;
+
+    /** Replicated only property name. */
+    public static final String PROP_REPLICATED_ONLY = PROP_PREFIX + PARAM_REPLICATED_ONLY;
+
     /** Socket send buffer property name. */
     public static final String PROP_SOCK_SND_BUF = PROP_PREFIX + PARAM_SOCK_SND_BUF;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9733921/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
index f8f595f..e00b001 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
@@ -236,31 +236,31 @@ public class SqlListenerNioListener extends GridNioServerListenerAdapter<byte[]>
     private SqlListenerConnectionContext prepareContext(SqlListenerProtocolVersion ver, BinaryReaderExImpl reader) {
         byte clientType = reader.readByte();
 
-        boolean distributedJoins = reader.readBoolean();
-        boolean enforceJoinOrder = reader.readBoolean();
+        if (clientType == ODBC_CLIENT) {
+            boolean distributedJoins = reader.readBoolean();
+            boolean enforceJoinOrder = reader.readBoolean();
 
-        SqlListenerRequestHandler handler;
-        SqlListenerMessageParser parser;
+            SqlListenerRequestHandler handler = new OdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins,
+                enforceJoinOrder);
 
-        switch (clientType) {
-            case ODBC_CLIENT:
-                parser = new OdbcMessageParser(ctx);
+            SqlListenerMessageParser parser = new JdbcMessageParser(ctx);
 
-                handler = new OdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins, enforceJoinOrder);
-
-                break;
-
-            case JDBC_CLIENT:
-                parser = new JdbcMessageParser(ctx);
+            return new SqlListenerConnectionContext(handler, parser);
+        }
+        else if (clientType == JDBC_CLIENT) {
+            boolean distributedJoins = reader.readBoolean();
+            boolean enforceJoinOrder = reader.readBoolean();
+            boolean collocated = reader.readBoolean();
+            boolean replicatedOnly = reader.readBoolean();
 
-                handler = new JdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins, enforceJoinOrder);
+            SqlListenerRequestHandler handler = new JdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins,
+                enforceJoinOrder, collocated, replicatedOnly);
 
-                break;
+            SqlListenerMessageParser parser = new OdbcMessageParser(ctx);
 
-            default:
-                throw new IgniteException("Unknown client type: " + clientType);
+            return new SqlListenerConnectionContext(handler, parser);
         }
-
-        return new SqlListenerConnectionContext(handler, parser);
+        else
+            throw new IgniteException("Unknown client type: " + clientType);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9733921/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
index e64e9a6..0796cfc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
@@ -68,6 +68,12 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler {
     /** Enforce join order flag. */
     private final boolean enforceJoinOrder;
 
+    /** Collocated flag. */
+    private final boolean collocated;
+
+    /** Replicated only flag. */
+    private final boolean replicatedOnly;
+
     /**
      * Constructor.
      *
@@ -76,14 +82,18 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler {
      * @param maxCursors Maximum allowed cursors.
      * @param distributedJoins Distributed joins flag.
      * @param enforceJoinOrder Enforce join order flag.
+     * @param collocated Collocated flag.
+     * @param replicatedOnly Replicated only flag.
      */
     public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int maxCursors,
-        boolean distributedJoins, boolean enforceJoinOrder) {
+        boolean distributedJoins, boolean enforceJoinOrder, boolean collocated, boolean replicatedOnly) {
         this.ctx = ctx;
         this.busyLock = busyLock;
         this.maxCursors = maxCursors;
         this.distributedJoins = distributedJoins;
         this.enforceJoinOrder = enforceJoinOrder;
+        this.collocated = collocated;
+        this.replicatedOnly = replicatedOnly;
 
         log = ctx.log(getClass());
     }
@@ -153,6 +163,8 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler {
 
             qry.setDistributedJoins(distributedJoins);
             qry.setEnforceJoinOrder(enforceJoinOrder);
+            qry.setCollocated(collocated);
+            qry.setReplicatedOnly(replicatedOnly);
 
             if (req.pageSize() <= 0)
                 return new JdbcResponse(SqlListenerResponse.STATUS_FAILED,


[38/50] [abbrv] ignite git commit: IGNITE-5263: Renamed ODBC connection param "cache" to schema

Posted by sb...@apache.org.
IGNITE-5263: Renamed ODBC connection param "cache" to schema


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/2ba6ab42
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/2ba6ab42
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/2ba6ab42

Branch: refs/heads/ignite-5075
Commit: 2ba6ab42bea0b1fff8fa4a7f5e676f04b6c14783
Parents: da37720
Author: Igor Sapego <is...@gridgain.com>
Authored: Mon Jun 5 16:28:58 2017 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Mon Jun 5 16:28:58 2017 +0300

----------------------------------------------------------------------
 .../processors/odbc/odbc/OdbcMessageParser.java | 12 ++--
 .../odbc/odbc/OdbcQueryExecuteRequest.java      | 16 ++---
 .../odbc/OdbcQueryGetColumnsMetaRequest.java    | 44 ++++++-------
 .../odbc/OdbcQueryGetParamsMetaRequest.java     | 15 +++--
 .../odbc/odbc/OdbcRequestHandler.java           | 68 ++++++++++----------
 .../project/vs/odbc-test.vcxproj.filters        |  4 +-
 .../cpp/odbc-test/src/api_robustness_test.cpp   | 54 ++++++++--------
 .../cpp/odbc-test/src/configuration_test.cpp    | 32 ++++-----
 .../cpp/odbc-test/src/queries_test.cpp          | 34 +++++-----
 .../odbc-test/src/sql_test_suite_fixture.cpp    |  2 +-
 .../include/ignite/odbc/config/configuration.h  | 24 +++----
 .../cpp/odbc/include/ignite/odbc/connection.h   |  6 +-
 .../cpp/odbc/include/ignite/odbc/message.h      | 30 ++++-----
 .../odbc/system/ui/dsn_configuration_window.h   | 12 ++--
 .../src/system/ui/dsn_configuration_window.cpp  | 18 +++---
 .../cpp/odbc/src/config/configuration.cpp       |  4 +-
 modules/platforms/cpp/odbc/src/connection.cpp   |  4 +-
 modules/platforms/cpp/odbc/src/dsn_config.cpp   |  4 +-
 .../odbc/src/query/column_metadata_query.cpp    |  2 +-
 .../platforms/cpp/odbc/src/query/data_query.cpp | 14 ++--
 modules/platforms/cpp/odbc/src/statement.cpp    | 12 ++--
 21 files changed, 208 insertions(+), 203 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
index 02e8676..91ed139 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
@@ -83,7 +83,7 @@ public class OdbcMessageParser implements SqlListenerMessageParser {
 
         switch (cmd) {
             case OdbcRequest.QRY_EXEC: {
-                String cache = reader.readString();
+                String schema = reader.readString();
                 String sql = reader.readString();
                 int argsNum = reader.readInt();
 
@@ -92,7 +92,7 @@ public class OdbcMessageParser implements SqlListenerMessageParser {
                 for (int i = 0; i < argsNum; ++i)
                     params[i] = SqlListenerUtils.readObject(reader, true);
 
-                res = new OdbcQueryExecuteRequest(cache, sql, params);
+                res = new OdbcQueryExecuteRequest(schema, sql, params);
 
                 break;
             }
@@ -115,11 +115,11 @@ public class OdbcMessageParser implements SqlListenerMessageParser {
             }
 
             case OdbcRequest.META_COLS: {
-                String cache = reader.readString();
+                String schema = reader.readString();
                 String table = reader.readString();
                 String column = reader.readString();
 
-                res = new OdbcQueryGetColumnsMetaRequest(cache, table, column);
+                res = new OdbcQueryGetColumnsMetaRequest(schema, table, column);
 
                 break;
             }
@@ -136,10 +136,10 @@ public class OdbcMessageParser implements SqlListenerMessageParser {
             }
 
             case OdbcRequest.META_PARAMS: {
-                String cacheName = reader.readString();
+                String schema = reader.readString();
                 String sqlQuery = reader.readString();
 
-                res = new OdbcQueryGetParamsMetaRequest(cacheName, sqlQuery);
+                res = new OdbcQueryGetParamsMetaRequest(schema, sqlQuery);
 
                 break;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
index dd674d2..8bb61dc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
@@ -26,8 +26,8 @@ import org.jetbrains.annotations.Nullable;
  * SQL listener query execute request.
  */
 public class OdbcQueryExecuteRequest extends OdbcRequest {
-    /** Cache name. */
-    private final String cacheName;
+    /** Schema. */
+    private final String schema;
 
     /** Sql query. */
     @GridToStringInclude(sensitive = true)
@@ -38,14 +38,14 @@ public class OdbcQueryExecuteRequest extends OdbcRequest {
     private final Object[] args;
 
     /**
-     * @param cacheName Cache name.
+     * @param schema Schema.
      * @param sqlQry SQL query.
      * @param args Arguments list.
      */
-    public OdbcQueryExecuteRequest(String cacheName, String sqlQry, Object[] args) {
+    public OdbcQueryExecuteRequest(String schema, String sqlQry, Object[] args) {
         super(QRY_EXEC);
 
-        this.cacheName = cacheName.isEmpty() ? null : cacheName;
+        this.schema = schema.isEmpty() ? null : schema;
         this.sqlQry = sqlQry;
         this.args = args;
     }
@@ -65,10 +65,10 @@ public class OdbcQueryExecuteRequest extends OdbcRequest {
     }
 
     /**
-     * @return Cache name.
+     * @return Schema.
      */
-    @Nullable public String cacheName() {
-        return cacheName;
+    @Nullable public String schema() {
+        return schema;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaRequest.java
index b60a9e3..db00e63 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaRequest.java
@@ -24,47 +24,47 @@ import org.jetbrains.annotations.Nullable;
  * ODBC query get columns meta request.
  */
 public class OdbcQueryGetColumnsMetaRequest extends OdbcRequest {
-    /** Cache name. */
-    private final String cacheName;
+    /** Schema pattern. */
+    private final String schemaPattern;
 
-    /** Table name. */
-    private final String tableName;
+    /** Table pattern. */
+    private final String tablePattern;
 
-    /** Column name. */
-    private final String columnName;
+    /** Column pattern. */
+    private final String columnPattern;
 
     /**
-     * @param cacheName Cache name.
-     * @param tableName Table name.
-     * @param columnName Column name.
+     * @param schemaPattern Schema pattern.
+     * @param tablePattern Table pattern.
+     * @param columnPattern Column pattern.
      */
-    public OdbcQueryGetColumnsMetaRequest(String cacheName, String tableName, String columnName) {
+    public OdbcQueryGetColumnsMetaRequest(String schemaPattern, String tablePattern, String columnPattern) {
         super(META_COLS);
 
-        this.cacheName = cacheName;
-        this.tableName = tableName;
-        this.columnName = columnName;
+        this.schemaPattern = schemaPattern;
+        this.tablePattern = tablePattern;
+        this.columnPattern = columnPattern;
     }
 
     /**
-     * @return Cache name.
+     * @return Schema pattern.
      */
-    @Nullable public String cacheName() {
-        return cacheName;
+    @Nullable public String schemaPattern() {
+        return schemaPattern;
     }
 
     /**
-     * @return Table name.
+     * @return Table pattern.
      */
-    public String tableName() {
-        return tableName;
+    public String tablePattern() {
+        return tablePattern;
     }
 
     /**
-     * @return Column name.
+     * @return Column pattern.
      */
-    public String columnName() {
-        return columnName;
+    public String columnPattern() {
+        return columnPattern;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaRequest.java
index 1d468b1..0ae2916 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaRequest.java
@@ -23,19 +23,20 @@ import org.apache.ignite.internal.util.typedef.internal.S;
  * ODBC query get params meta request.
  */
 public class OdbcQueryGetParamsMetaRequest extends OdbcRequest {
-    /** Cache. */
-    private final String cacheName;
+    /** Schema. */
+    private final String schema;
 
     /** Query. */
     private final String query;
 
     /**
+     * @param schema Schema.
      * @param query SQL Query.
      */
-    public OdbcQueryGetParamsMetaRequest(String cacheName, String query) {
+    public OdbcQueryGetParamsMetaRequest(String schema, String query) {
         super(META_PARAMS);
 
-        this.cacheName = cacheName;
+        this.schema = schema;
         this.query = query;
     }
 
@@ -47,10 +48,10 @@ public class OdbcQueryGetParamsMetaRequest extends OdbcRequest {
     }
 
     /**
-     * @return Cache name.
+     * @return Schema name.
      */
-    public String cacheName() {
-        return cacheName;
+    public String schema() {
+        return schema;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
index e1b421b..a520d96 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
@@ -27,7 +27,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
-import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cache.query.QueryCursor;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
@@ -40,6 +39,7 @@ import org.apache.ignite.internal.processors.odbc.SqlListenerRequestHandler;
 import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
 import org.apache.ignite.internal.processors.odbc.odbc.escape.OdbcEscapeUtils;
 import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+import org.apache.ignite.internal.processors.query.GridQueryIndexing;
 import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
 import org.apache.ignite.internal.util.GridSpinBusyLock;
 import org.apache.ignite.internal.util.typedef.F;
@@ -173,20 +173,9 @@ public class OdbcRequestHandler implements SqlListenerRequestHandler {
 
             qry.setDistributedJoins(distributedJoins);
             qry.setEnforceJoinOrder(enforceJoinOrder);
+            qry.setSchema(req.schema());
 
-            IgniteCache<Object, Object> cache0 = ctx.grid().cache(req.cacheName());
-
-            if (cache0 == null)
-                return new OdbcResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Cache doesn't exist (did you configure it?): " + req.cacheName());
-
-            IgniteCache<Object, Object> cache = cache0.withKeepBinary();
-
-            if (cache == null)
-                return new OdbcResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Can not get cache with keep binary: " + req.cacheName());
-
-            QueryCursor qryCur = cache.query(qry);
+            QueryCursor qryCur = ctx.query().querySqlFieldsNoCache(qry, true);
 
             qryCursors.put(qryId, new IgniteBiTuple<QueryCursor, Iterator>(qryCur, null));
 
@@ -290,38 +279,47 @@ public class OdbcRequestHandler implements SqlListenerRequestHandler {
         try {
             List<OdbcColumnMeta> meta = new ArrayList<>();
 
-            String cacheName;
-            String tableName;
+            String schemaPattern;
+            String tablePattern;
 
-            if (req.tableName().contains(".")) {
+            if (req.tablePattern().contains(".")) {
                 // Parsing two-part table name.
-                String[] parts = req.tableName().split("\\.");
+                String[] parts = req.tablePattern().split("\\.");
 
-                cacheName = OdbcUtils.removeQuotationMarksIfNeeded(parts[0]);
+                schemaPattern = OdbcUtils.removeQuotationMarksIfNeeded(parts[0]);
 
-                tableName = parts[1];
+                tablePattern = parts[1];
             }
             else {
-                cacheName = OdbcUtils.removeQuotationMarksIfNeeded(req.cacheName());
+                schemaPattern = OdbcUtils.removeQuotationMarksIfNeeded(req.schemaPattern());
 
-                tableName = req.tableName();
+                tablePattern = req.tablePattern();
             }
 
-            Collection<GridQueryTypeDescriptor> tablesMeta = ctx.query().types(cacheName);
+            GridQueryIndexing indexing = ctx.query().getIndexing();
+
+            for (String cacheName : ctx.cache().cacheNames()) {
+                String cacheSchema = indexing.schema(cacheName);
 
-            for (GridQueryTypeDescriptor table : tablesMeta) {
-                if (!matches(table.name(), tableName))
+                if (!matches(cacheSchema, schemaPattern))
                     continue;
 
-                for (Map.Entry<String, Class<?>> field : table.fields().entrySet()) {
-                    if (!matches(field.getKey(), req.columnName()))
+                Collection<GridQueryTypeDescriptor> tablesMeta = ctx.query().types(cacheName);
+
+                for (GridQueryTypeDescriptor table : tablesMeta) {
+                    if (!matches(table.name(), tablePattern))
                         continue;
 
-                    OdbcColumnMeta columnMeta = new OdbcColumnMeta(req.cacheName(), table.name(),
+                    for (Map.Entry<String, Class<?>> field : table.fields().entrySet()) {
+                        if (!matches(field.getKey(), req.columnPattern()))
+                            continue;
+
+                    OdbcColumnMeta columnMeta = new OdbcColumnMeta(cacheSchema, table.name(),
                         field.getKey(), field.getValue());
 
-                    if (!meta.contains(columnMeta))
-                        meta.add(columnMeta);
+                        if (!meta.contains(columnMeta))
+                            meta.add(columnMeta);
+                    }
                 }
             }
 
@@ -346,11 +344,15 @@ public class OdbcRequestHandler implements SqlListenerRequestHandler {
         try {
             List<OdbcTableMeta> meta = new ArrayList<>();
 
-            String realSchema = OdbcUtils.removeQuotationMarksIfNeeded(req.schema());
+            String schemaPattern = OdbcUtils.removeQuotationMarksIfNeeded(req.schema());
+
+            GridQueryIndexing indexing = ctx.query().getIndexing();
 
             for (String cacheName : ctx.cache().cacheNames())
             {
-                if (!matches(cacheName, realSchema))
+                String cacheSchema = indexing.schema(cacheName);
+
+                if (!matches(cacheSchema, schemaPattern))
                     continue;
 
                 Collection<GridQueryTypeDescriptor> tablesMeta = ctx.query().types(cacheName);
@@ -388,7 +390,7 @@ public class OdbcRequestHandler implements SqlListenerRequestHandler {
      */
     private SqlListenerResponse getParamsMeta(OdbcQueryGetParamsMetaRequest req) {
         try {
-            PreparedStatement stmt = ctx.query().prepareNativeStatement(req.cacheName(), req.query());
+            PreparedStatement stmt = ctx.query().getIndexing().prepareNativeStatement(req.schema(), req.query());
 
             ParameterMetaData pmd = stmt.getParameterMetaData();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
index a344df9..65f2ebf 100644
--- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
+++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
@@ -155,6 +155,8 @@
     <None Include="..\..\config\queries-default.xml">
       <Filter>Configs</Filter>
     </None>
-    <None Include="..\..\config\queries-test-default.xml" />
+    <None Include="..\..\config\queries-test-default.xml">
+      <Filter>Configs</Filter>
+    </None>
   </ItemGroup>
 </Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
index 3681ea1..82f7274 100644
--- a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
@@ -154,7 +154,7 @@ struct ApiRobustnessTestSuiteFixture
      */
     void CheckFetchScrollUnsupportedOrientation(SQLUSMALLINT orientation)
     {
-        Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+        Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
         SQLRETURN ret;
 
@@ -293,7 +293,7 @@ BOOST_AUTO_TEST_CASE(TestSQLDriverConnect)
 
     Prepare();
 
-    SQLCHAR connectStr[] = "DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache";
+    SQLCHAR connectStr[] = "DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache";
 
     SQLCHAR outStr[ODBC_BUFFER_SIZE];
     SQLSMALLINT outStrLen;
@@ -332,7 +332,7 @@ BOOST_AUTO_TEST_CASE(TestSQLConnect)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR buffer[ODBC_BUFFER_SIZE];
     SQLSMALLINT resLen = 0;
@@ -363,7 +363,7 @@ BOOST_AUTO_TEST_CASE(TestSQLPrepare)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR sql[] = "SELECT strField FROM TestType";
 
@@ -395,7 +395,7 @@ BOOST_AUTO_TEST_CASE(TestSQLExecDirect)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR sql[] = "SELECT strField FROM TestType";
 
@@ -436,7 +436,7 @@ BOOST_AUTO_TEST_CASE(TestSQLExtendedFetch)
         testCache.Put(i, obj);
     }
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR sql[] = "SELECT strField FROM TestType";
 
@@ -476,7 +476,7 @@ BOOST_AUTO_TEST_CASE(TestSQLNumResultCols)
         testCache.Put(i, obj);
     }
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR sql[] = "SELECT strField FROM TestType";
 
@@ -500,7 +500,7 @@ BOOST_AUTO_TEST_CASE(TestSQLTables)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR catalogName[] = "";
     SQLCHAR schemaName[] = "";
@@ -528,7 +528,7 @@ BOOST_AUTO_TEST_CASE(TestSQLColumns)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR catalogName[] = "";
     SQLCHAR schemaName[] = "";
@@ -556,7 +556,7 @@ BOOST_AUTO_TEST_CASE(TestSQLBindCol)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLINTEGER ind1;
     SQLLEN len1 = 0;
@@ -597,7 +597,7 @@ BOOST_AUTO_TEST_CASE(TestSQLBindParameter)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLINTEGER ind1;
     SQLLEN len1 = 0;
@@ -644,7 +644,7 @@ BOOST_AUTO_TEST_CASE(TestSQLNativeSql)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR sql[] = "SELECT strField FROM TestType";
     SQLCHAR buffer[ODBC_BUFFER_SIZE];
@@ -679,7 +679,7 @@ BOOST_AUTO_TEST_CASE(TestSQLColAttribute)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR sql[] = "SELECT strField FROM TestType";
 
@@ -719,7 +719,7 @@ BOOST_AUTO_TEST_CASE(TestSQLDescribeCol)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR sql[] = "SELECT strField FROM TestType";
 
@@ -755,7 +755,7 @@ BOOST_AUTO_TEST_CASE(TestSQLRowCount)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR sql[] = "SELECT strField FROM TestType";
 
@@ -778,7 +778,7 @@ BOOST_AUTO_TEST_CASE(TestSQLForeignKeys)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR catalogName[] = "";
     SQLCHAR schemaName[] = "cache";
@@ -863,7 +863,7 @@ BOOST_AUTO_TEST_CASE(TestSQLGetStmtAttr)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR buffer[ODBC_BUFFER_SIZE];
     SQLINTEGER resLen = 0;
@@ -884,7 +884,7 @@ BOOST_AUTO_TEST_CASE(TestSQLSetStmtAttr)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLULEN val = 1;
 
@@ -903,7 +903,7 @@ BOOST_AUTO_TEST_CASE(TestSQLPrimaryKeys)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR catalogName[] = "";
     SQLCHAR schemaName[] = "cache";
@@ -929,7 +929,7 @@ BOOST_AUTO_TEST_CASE(TestSQLNumParams)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR sql[] = "SELECT strField FROM TestType";
 
@@ -953,7 +953,7 @@ BOOST_AUTO_TEST_CASE(TestSQLGetDiagField)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     // Should fail.
     SQLRETURN ret = SQLGetTypeInfo(stmt, SQL_INTERVAL_MONTH);
@@ -979,7 +979,7 @@ BOOST_AUTO_TEST_CASE(TestSQLGetDiagRec)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     // Should fail.
     SQLRETURN ret = SQLGetTypeInfo(stmt, SQL_INTERVAL_MONTH);
@@ -1018,7 +1018,7 @@ BOOST_AUTO_TEST_CASE(TestSQLGetData)
         testCache.Put(i, obj);
     }
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR sql[] = "SELECT strField FROM TestType";
 
@@ -1062,7 +1062,7 @@ BOOST_AUTO_TEST_CASE(TestSQLGetEnvAttr)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR buffer[ODBC_BUFFER_SIZE];
     SQLINTEGER resLen = 0;
@@ -1083,7 +1083,7 @@ BOOST_AUTO_TEST_CASE(TestSQLSpecialColumns)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR catalogName[] = "";
     SQLCHAR schemaName[] = "cache";
@@ -1152,7 +1152,7 @@ BOOST_AUTO_TEST_CASE(TestSQLError)
     // There are no checks because we do not really care what is the result of these
     // calls as long as they do not cause segmentation fault.
 
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLCHAR state[6] = { 0 };
     SQLINTEGER nativeCode = 0;
@@ -1194,7 +1194,7 @@ BOOST_AUTO_TEST_CASE(TestSQLError)
 
 BOOST_AUTO_TEST_CASE(TestSQLDiagnosticRecords)
 {
-    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;cache=cache");
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLHANDLE hnd;
     SQLRETURN ret;

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/configuration_test.cpp b/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
index ecf3c4b..a2cd280 100644
--- a/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
@@ -35,7 +35,7 @@ namespace
     const std::string testDriverName = "Ignite Driver";
     const std::string testServerHost = "testhost.com";
     const uint16_t testServerPort = 4242;
-    const std::string testCacheName = "TestCache";
+    const std::string testSchemaName = "TestSchema";
     const std::string testDsn = "Ignite DSN";
     const int32_t testPageSize = 4321;
     const bool testDistributedJoins = true;
@@ -113,7 +113,7 @@ void CheckConnectionConfig(const Configuration& cfg)
     BOOST_CHECK_EQUAL(cfg.GetHost(), testServerHost);
     BOOST_CHECK_EQUAL(cfg.GetTcpPort(), testServerPort);
     BOOST_CHECK_EQUAL(cfg.GetAddress(), testAddress);
-    BOOST_CHECK_EQUAL(cfg.GetCache(), testCacheName);
+    BOOST_CHECK_EQUAL(cfg.GetSchema(), testSchemaName);
     BOOST_CHECK_EQUAL(cfg.GetDsn(), std::string());
     BOOST_CHECK_EQUAL(cfg.GetPageSize(), testPageSize);
     BOOST_CHECK_EQUAL(cfg.IsDistributedJoins(), testDistributedJoins);
@@ -122,11 +122,11 @@ void CheckConnectionConfig(const Configuration& cfg)
     std::stringstream constructor;
 
     constructor << "address=" << testAddress << ';'
-                << "cache=" << testCacheName << ';'
                 << "distributed_joins=" << (testDistributedJoins ? "true" : "false") << ';'
                 << "driver={" << testDriverName << "};"
                 << "enforce_join_order=" << (testEnforceJoinOrder ? "true" : "false") << ';'
-                << "page_size=" << testPageSize << ';';
+                << "page_size=" << testPageSize << ';'
+                << "schema=" << testSchemaName << ';';
 
     const std::string& expectedStr = constructor.str();
 
@@ -137,7 +137,7 @@ void CheckDsnConfig(const Configuration& cfg)
 {
     BOOST_CHECK_EQUAL(cfg.GetDriver(), testDriverName);
     BOOST_CHECK_EQUAL(cfg.GetDsn(), testDsn);
-    BOOST_CHECK_EQUAL(cfg.GetCache(), Configuration::DefaultValue::cache);
+    BOOST_CHECK_EQUAL(cfg.GetSchema(), Configuration::DefaultValue::schema);
     BOOST_CHECK_EQUAL(cfg.GetAddress(), Configuration::DefaultValue::address);
     BOOST_CHECK_EQUAL(cfg.GetHost(), std::string());
     BOOST_CHECK_EQUAL(cfg.GetTcpPort(), Configuration::DefaultValue::port);
@@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(CheckTestValuesNotEquealDefault)
     BOOST_CHECK_NE(testDriverName, Configuration::DefaultValue::driver);
     BOOST_CHECK_NE(testAddress, Configuration::DefaultValue::address);
     BOOST_CHECK_NE(testServerPort, Configuration::DefaultValue::port);
-    BOOST_CHECK_NE(testCacheName, Configuration::DefaultValue::cache);
+    BOOST_CHECK_NE(testSchemaName, Configuration::DefaultValue::schema);
     BOOST_CHECK_NE(testDsn, Configuration::DefaultValue::dsn);
     BOOST_CHECK_NE(testPageSize, Configuration::DefaultValue::pageSize);
     BOOST_CHECK_NE(testDistributedJoins, Configuration::DefaultValue::distributedJoins);
@@ -168,10 +168,10 @@ BOOST_AUTO_TEST_CASE(TestConnectStringUppercase)
 
     constructor << "DRIVER={" << testDriverName << "};"
                 << "ADDRESS=" << testAddress << ';'
-                << "CACHE=" << testCacheName << ';'
                 << "DISTRIBUTED_JOINS=" << (testDistributedJoins ? "TRUE" : "FALSE") << ';'
                 << "ENFORCE_JOIN_ORDER=" << (testEnforceJoinOrder ? "TRUE" : "FALSE") << ';'
-                << "PAGE_SIZE=" << testPageSize;
+                << "PAGE_SIZE=" << testPageSize << ';'
+                << "SCHEMA=" << testSchemaName;
 
     const std::string& connectStr = constructor.str();
 
@@ -189,9 +189,9 @@ BOOST_AUTO_TEST_CASE(TestConnectStringLowercase)
     constructor << "driver={" << testDriverName << "};"
                 << "address=" << testAddress << ';'
                 << "page_size=" << testPageSize << ';'
-                << "cache=" << testCacheName << ';'
                 << "distributed_joins=" << (testDistributedJoins ? "true" : "false") << ';'
-                << "enforce_join_order=" << (testEnforceJoinOrder ? "true" : "false");
+                << "enforce_join_order=" << (testEnforceJoinOrder ? "true" : "false") << ';'
+                << "schema=" << testSchemaName;
 
     const std::string& connectStr = constructor.str();
 
@@ -209,9 +209,9 @@ BOOST_AUTO_TEST_CASE(TestConnectStringZeroTerminated)
     constructor << "driver={" << testDriverName << "};"
                 << "address=" << testAddress << ';'
                 << "page_size=" << testPageSize << ';'
-                << "cache=" << testCacheName << ';'
                 << "distributed_joins=" << (testDistributedJoins ? "true" : "false") << ';'
-                << "enforce_join_order=" << (testEnforceJoinOrder ? "true" : "false");
+                << "enforce_join_order=" << (testEnforceJoinOrder ? "true" : "false") << ';'
+                << "schema=" << testSchemaName;
 
     const std::string& connectStr = constructor.str();
 
@@ -229,9 +229,9 @@ BOOST_AUTO_TEST_CASE(TestConnectStringMixed)
     constructor << "Driver={" << testDriverName << "};"
                 << "Address=" << testAddress << ';'
                 << "Page_Size=" << testPageSize << ';'
-                << "Cache=" << testCacheName << ';'
                 << "Distributed_Joins=" << (testDistributedJoins ? "True" : "False") << ';'
-                << "Enforce_Join_Order=" << (testEnforceJoinOrder ? "True" : "False");
+                << "Enforce_Join_Order=" << (testEnforceJoinOrder ? "True" : "False") << ';'
+                << "Schema=" << testSchemaName;
 
     const std::string& connectStr = constructor.str();
 
@@ -249,9 +249,9 @@ BOOST_AUTO_TEST_CASE(TestConnectStringWhitepaces)
     constructor << "DRIVER = {" << testDriverName << "} ;\n"
                 << " ADDRESS =" << testAddress << "; "
                 << "   PAGE_SIZE= " << testPageSize << ';'
-                << "CACHE = \n\r" << testCacheName << ';'
                 << "   DISTRIBUTED_JOINS=" << (testDistributedJoins ? "TRUE" : "FALSE") << ';'
-                << "ENFORCE_JOIN_ORDER=   " << (testEnforceJoinOrder ? "TRUE  " : "FALSE  ");
+                << "ENFORCE_JOIN_ORDER=   " << (testEnforceJoinOrder ? "TRUE  " : "FALSE  ") << ';'
+                << "SCHEMA = \n\r" << testSchemaName;
 
     const std::string& connectStr = constructor.str();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc-test/src/queries_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/queries_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
index 4f7a6e2..25595c8 100644
--- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
@@ -160,7 +160,7 @@ struct QueriesTestSuiteFixture
     template<typename T>
     void CheckTwoRowsInt(SQLSMALLINT type)
     {
-        Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+        Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
         SQLRETURN ret;
 
@@ -375,12 +375,12 @@ BOOST_FIXTURE_TEST_SUITE(QueriesTestSuite, QueriesTestSuiteFixture)
 
 BOOST_AUTO_TEST_CASE(TestLegacyConnection)
 {
-    Connect("DRIVER={Apache Ignite};SERVER=127.0.0.1;PORT=11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};SERVER=127.0.0.1;PORT=11110;SCHEMA=cache");
 }
 
 BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_1_0)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache;PROTOCOL_VERSION=2.1.0");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.1.0");
 }
 
 BOOST_AUTO_TEST_CASE(TestTwoRowsInt8)
@@ -425,7 +425,7 @@ BOOST_AUTO_TEST_CASE(TestTwoRowsUint64)
 
 BOOST_AUTO_TEST_CASE(TestTwoRowsString)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
     SQLRETURN ret;
 
@@ -528,7 +528,7 @@ BOOST_AUTO_TEST_CASE(TestTwoRowsString)
 
 BOOST_AUTO_TEST_CASE(TestOneRowString)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
     SQLRETURN ret;
 
@@ -596,7 +596,7 @@ BOOST_AUTO_TEST_CASE(TestOneRowString)
 
 BOOST_AUTO_TEST_CASE(TestOneRowStringLen)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
     SQLRETURN ret;
 
@@ -648,7 +648,7 @@ BOOST_AUTO_TEST_CASE(TestOneRowStringLen)
 
 BOOST_AUTO_TEST_CASE(TestOneRowObject)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache2");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache2");
 
     SQLRETURN ret;
 
@@ -705,7 +705,7 @@ BOOST_AUTO_TEST_CASE(TestOneRowObject)
 
 BOOST_AUTO_TEST_CASE(TestDataAtExecution)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
     SQLRETURN ret;
 
@@ -830,7 +830,7 @@ BOOST_AUTO_TEST_CASE(TestDataAtExecution)
 
 BOOST_AUTO_TEST_CASE(TestNullFields)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
     SQLRETURN ret;
 
@@ -964,7 +964,7 @@ BOOST_AUTO_TEST_CASE(TestDistributedJoins)
         cache1.Put(i, entry);
     }
 
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
     SQLRETURN ret;
 
@@ -998,7 +998,7 @@ BOOST_AUTO_TEST_CASE(TestDistributedJoins)
 
     Disconnect();
 
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache;DISTRIBUTED_JOINS=true;");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;DISTRIBUTED_JOINS=true;");
 
     // Binding colums.
     for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
@@ -1021,7 +1021,7 @@ BOOST_AUTO_TEST_CASE(TestDistributedJoins)
 
 BOOST_AUTO_TEST_CASE(TestInsertSelect)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
     const int recordsNum = 100;
 
@@ -1081,7 +1081,7 @@ BOOST_AUTO_TEST_CASE(TestInsertSelect)
 
 BOOST_AUTO_TEST_CASE(TestInsertUpdateSelect)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
     const int recordsNum = 100;
 
@@ -1155,7 +1155,7 @@ BOOST_AUTO_TEST_CASE(TestInsertUpdateSelect)
 
 BOOST_AUTO_TEST_CASE(TestInsertDeleteSelect)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
     const int recordsNum = 100;
 
@@ -1223,7 +1223,7 @@ BOOST_AUTO_TEST_CASE(TestInsertDeleteSelect)
 
 BOOST_AUTO_TEST_CASE(TestInsertMergeSelect)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
     const int recordsNum = 100;
 
@@ -1312,7 +1312,7 @@ void CheckMeta(char columns[n][k], SQLLEN columnsLen[n])
 
 BOOST_AUTO_TEST_CASE(TestTablesMeta)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache2");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache2");
 
     SQLRETURN ret;
 
@@ -1376,7 +1376,7 @@ void CheckObjectData(int8_t* data, int32_t len, T const& value)
 
 BOOST_AUTO_TEST_CASE(TestKeyVal)
 {
-    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache2");
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache2");
 
     SQLRETURN ret;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc-test/src/sql_test_suite_fixture.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/sql_test_suite_fixture.cpp b/modules/platforms/cpp/odbc-test/src/sql_test_suite_fixture.cpp
index 0f82fd0..f905ff7 100644
--- a/modules/platforms/cpp/odbc-test/src/sql_test_suite_fixture.cpp
+++ b/modules/platforms/cpp/odbc-test/src/sql_test_suite_fixture.cpp
@@ -51,7 +51,7 @@ namespace ignite
         BOOST_REQUIRE(dbc != NULL);
 
         // Connect string
-        SQLCHAR connectStr[] = "DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache";
+        SQLCHAR connectStr[] = "DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache";
 
         SQLCHAR outstr[ODBC_BUFFER_SIZE];
         SQLSMALLINT outstrlen;

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h b/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
index c0d102b..5850d50 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
@@ -50,8 +50,8 @@ namespace ignite
                     /** Connection attribute keyword for Driver attribute. */
                     static const std::string driver;
 
-                    /** Connection attribute keyword for cache attribute. */
-                    static const std::string cache;
+                    /** Connection attribute keyword for schema attribute. */
+                    static const std::string schema;
 
                     /** Connection attribute keyword for address attribute. */
                     static const std::string address;
@@ -84,8 +84,8 @@ namespace ignite
                     /** Default value for Driver attribute. */
                     static const std::string driver;
 
-                    /** Default value for cache attribute. */
-                    static const std::string cache;
+                    /** Default value for schema attribute. */
+                    static const std::string schema;
 
                     /** Default value for address attribute. */
                     static const std::string address;
@@ -229,23 +229,23 @@ namespace ignite
                 void SetHost(const std::string& server);
 
                 /**
-                 * Get cache.
+                 * Get schema.
                  *
-                 * @return Cache name.
+                 * @return Schema.
                  */
-                const std::string& GetCache() const
+                const std::string& GetSchema() const
                 {
-                    return GetStringValue(Key::cache, DefaultValue::cache);
+                    return GetStringValue(Key::schema, DefaultValue::schema);
                 }
 
                 /**
-                 * Set cache.
+                 * Set schema.
                  *
-                 * @param cache Cache name.
+                 * @param schema Schema name.
                  */
-                void SetCache(const std::string& cache)
+                void SetSchema(const std::string& schema)
                 {
-                    arguments[Key::cache] = cache;
+                    arguments[Key::schema] = schema;
                 }
 
                 /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
index c3f27a2..1f91767 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
@@ -107,11 +107,11 @@ namespace ignite
             void Receive(std::vector<int8_t>& msg);
 
             /**
-             * Get name of the assotiated cache.
+             * Get name of the assotiated schema.
              *
-             * @return Cache name.
+             * @return Schema name.
              */
-            const std::string& GetCache() const;
+            const std::string& GetSchema() const;
 
             /**
              * Get configuration.

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/include/ignite/odbc/message.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/message.h b/modules/platforms/cpp/odbc/include/ignite/odbc/message.h
index 54c00fd..85d5b36 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/message.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/message.h
@@ -105,7 +105,7 @@ namespace ignite
              * Write request using provided writer.
              * @param writer Writer.
              */
-            void Write(ignite::impl::binary::BinaryWriterImpl& writer) const
+            void Write(impl::binary::BinaryWriterImpl& writer) const
             {
                 writer.WriteInt8(RequestType::HANDSHAKE);
 
@@ -139,13 +139,13 @@ namespace ignite
             /**
              * Constructor.
              *
-             * @param cache Cache name.
+             * @param schema Schema.
              * @param sql SQL query.
              * @param params Query arguments.
              */
-            QueryExecuteRequest(const std::string& cache, const std::string& sql,
+            QueryExecuteRequest(const std::string& schema, const std::string& sql,
                 const app::ParameterBindingMap& params) :
-                cache(cache),
+                schema(schema),
                 sql(sql),
                 params(params)
             {
@@ -164,10 +164,10 @@ namespace ignite
              * Write request using provided writer.
              * @param writer Writer.
              */
-            void Write(ignite::impl::binary::BinaryWriterImpl& writer) const
+            void Write(impl::binary::BinaryWriterImpl& writer) const
             {
                 writer.WriteInt8(RequestType::EXECUTE_SQL_QUERY);
-                utility::WriteString(writer, cache);
+                utility::WriteString(writer, schema);
                 utility::WriteString(writer, sql);
 
                 writer.WriteInt32(static_cast<int32_t>(params.size()));
@@ -190,8 +190,8 @@ namespace ignite
             }
 
         private:
-            /** Cache name. */
-            std::string cache;
+            /** Schema name. */
+            std::string schema;
 
             /** SQL query. */
             std::string sql;
@@ -408,11 +408,11 @@ namespace ignite
             /**
              * Constructor.
              *
-             * @param cacheName Cache name.
+             * @param schema Schema.
              * @param sqlQuery SQL query itself.
              */
-            QueryGetParamsMetaRequest(const std::string& cacheName, const std::string& sqlQuery) :
-                cacheName(cacheName),
+            QueryGetParamsMetaRequest(const std::string& schema, const std::string& sqlQuery) :
+                schema(schema),
                 sqlQuery(sqlQuery)
             {
                 // No-op.
@@ -430,17 +430,17 @@ namespace ignite
              * Write request using provided writer.
              * @param writer Writer.
              */
-            void Write(ignite::impl::binary::BinaryWriterImpl& writer) const
+            void Write(impl::binary::BinaryWriterImpl& writer) const
             {
                 writer.WriteInt8(RequestType::GET_PARAMS_METADATA);
 
-                utility::WriteString(writer, cacheName);
+                utility::WriteString(writer, schema);
                 utility::WriteString(writer, sqlQuery);
             }
 
         private:
-            /** Cache name. */
-            std::string cacheName;
+            /** Schema. */
+            std::string schema;
 
             /** SQL query. */
             std::string sqlQuery;

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h
index 2439696..46d00cf 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h
@@ -46,8 +46,8 @@ namespace ignite
                             NAME_LABEL,
                             ADDRESS_EDIT,
                             ADDRESS_LABEL,
-                            CACHE_EDIT,
-                            CACHE_LABEL,
+                            SCHEMA_EDIT,
+                            SCHEMA_LABEL,
                             PAGE_SIZE_EDIT,
                             PAGE_SIZE_LABEL,
                             DISTRIBUTED_JOINS_CHECK_BOX,
@@ -119,11 +119,11 @@ namespace ignite
                     /** DSN address edit field. */
                     std::auto_ptr<Window> addressEdit;
 
-                    /** DSN cache edit field label. */
-                    std::auto_ptr<Window> cacheLabel;
+                    /** DSN schema edit field label. */
+                    std::auto_ptr<Window> schemaLabel;
 
-                    /** DSN cache edit field. */
-                    std::auto_ptr<Window> cacheEdit;
+                    /** DSN schema edit field. */
+                    std::auto_ptr<Window> schemaEdit;
 
                     /** DSN fetch page size edit field label. */
                     std::auto_ptr<Window> pageSizeLabel;

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp
index 36cb5e8..ffb7120 100644
--- a/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp
+++ b/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp
@@ -38,8 +38,8 @@ namespace ignite
                     nameEdit(),
                     addressLabel(),
                     addressEdit(),
-                    cacheLabel(),
-                    cacheEdit(),
+                    schemaLabel(),
+                    schemaEdit(),
                     pageSizeLabel(),
                     pageSizeEdit(),
                     distributedJoinsCheckBox(),
@@ -115,9 +115,9 @@ namespace ignite
 
                     rowPos += interval + rowSize;
 
-                    val = config.GetCache().c_str();
-                    cacheLabel = CreateLabel(labelPosX, rowPos, labelSizeX, rowSize, "Cache name:", ChildId::CACHE_LABEL);
-                    cacheEdit = CreateEdit(editPosX, rowPos, editSizeX, rowSize, val, ChildId::CACHE_EDIT);
+                    val = config.GetSchema().c_str();
+                    schemaLabel = CreateLabel(labelPosX, rowPos, labelSizeX, rowSize, "Schema name:", ChildId::SCHEMA_LABEL);
+                    schemaEdit = CreateEdit(editPosX, rowPos, editSizeX, rowSize, val, ChildId::SCHEMA_EDIT);
 
                     rowPos += interval + rowSize;
 
@@ -248,7 +248,7 @@ namespace ignite
                 {
                     std::string dsn;
                     std::string address;
-                    std::string cache;
+                    std::string schema;
                     std::string pageSizeStr;
                     std::string version;
 
@@ -257,7 +257,7 @@ namespace ignite
 
                     nameEdit->GetText(dsn);
                     addressEdit->GetText(address);
-                    cacheEdit->GetText(cache);
+                    schemaEdit->GetText(schema);
                     protocolVersionComboBox->GetText(version);
                     pageSizeEdit->GetText(pageSizeStr);
 
@@ -275,7 +275,7 @@ namespace ignite
                     LOG_MSG("Retriving arguments:");
                     LOG_MSG("DSN:                " << dsn);
                     LOG_MSG("Address:            " << address);
-                    LOG_MSG("Cache:              " << cache);
+                    LOG_MSG("Schema:             " << schema);
                     LOG_MSG("Page size:          " << pageSize);
                     LOG_MSG("Protocol version:   " << version);
                     LOG_MSG("Distributed Joins:  " << (distributedJoins ? "true" : "false"));
@@ -286,7 +286,7 @@ namespace ignite
 
                     cfg.SetDsn(dsn);
                     cfg.SetAddress(address);
-                    cfg.SetCache(cache);
+                    cfg.SetSchema(schema);
                     cfg.SetPageSize(pageSize);
                     cfg.SetProtocolVersion(version);
                     cfg.SetDistributedJoins(distributedJoins);

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/src/config/configuration.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/config/configuration.cpp b/modules/platforms/cpp/odbc/src/config/configuration.cpp
index 07f1368..854cb2b 100644
--- a/modules/platforms/cpp/odbc/src/config/configuration.cpp
+++ b/modules/platforms/cpp/odbc/src/config/configuration.cpp
@@ -34,7 +34,7 @@ namespace ignite
         {
             const std::string Configuration::Key::dsn               = "dsn";
             const std::string Configuration::Key::driver            = "driver";
-            const std::string Configuration::Key::cache             = "cache";
+            const std::string Configuration::Key::schema            = "schema";
             const std::string Configuration::Key::address           = "address";
             const std::string Configuration::Key::server            = "server";
             const std::string Configuration::Key::port              = "port";
@@ -45,7 +45,7 @@ namespace ignite
 
             const std::string Configuration::DefaultValue::dsn      = "Apache Ignite DSN";
             const std::string Configuration::DefaultValue::driver   = "Apache Ignite";
-            const std::string Configuration::DefaultValue::cache    = "";
+            const std::string Configuration::DefaultValue::schema   = "PUBLIC";
             const std::string Configuration::DefaultValue::address  = "";
             const std::string Configuration::DefaultValue::server   = "";
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/src/connection.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp
index b9c15e5..f43a562 100644
--- a/modules/platforms/cpp/odbc/src/connection.cpp
+++ b/modules/platforms/cpp/odbc/src/connection.cpp
@@ -280,9 +280,9 @@ namespace ignite
             return len;
         }
 
-        const std::string& Connection::GetCache() const
+        const std::string& Connection::GetSchema() const
         {
-            return config.GetCache();
+            return config.GetSchema();
         }
 
         const config::Configuration& Connection::GetConfiguration() const

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/src/dsn_config.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/dsn_config.cpp b/modules/platforms/cpp/odbc/src/dsn_config.cpp
index 2edeab0..cabd06e 100644
--- a/modules/platforms/cpp/odbc/src/dsn_config.cpp
+++ b/modules/platforms/cpp/odbc/src/dsn_config.cpp
@@ -96,7 +96,7 @@ namespace ignite
 
             uint16_t port = ReadDsnInt(dsn, Configuration::Key::port, config.GetTcpPort());
 
-            std::string cache = ReadDsnString(dsn, Configuration::Key::cache, config.GetCache().c_str());
+            std::string schema = ReadDsnString(dsn, Configuration::Key::schema, config.GetSchema().c_str());
 
             bool distributedJoins = ReadDsnBool(dsn, Configuration::Key::distributedJoins, config.IsDistributedJoins());
 
@@ -113,7 +113,7 @@ namespace ignite
             config.SetAddress(address);
             config.SetHost(server);
             config.SetTcpPort(port);
-            config.SetCache(cache);
+            config.SetSchema(schema);
             config.SetDistributedJoins(distributedJoins);
             config.SetEnforceJoinOrder(enforceJoinOrder);
             config.SetProtocolVersion(version);

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp b/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
index cca3eb5..8ba9323 100644
--- a/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
@@ -309,7 +309,7 @@ namespace ignite
                     LOG_MSG("\n[" << i << "] SchemaName:     " << meta[i].GetSchemaName()
                          << "\n[" << i << "] TableName:      " << meta[i].GetTableName()
                          << "\n[" << i << "] ColumnName:     " << meta[i].GetColumnName()
-                         << "\n[" << i << "] ColumnType:     " << meta[i].GetDataType());
+                         << "\n[" << i << "] ColumnType:     " << static_cast<int32_t>(meta[i].GetDataType()));
                 }
 
                 return SqlResult::AI_SUCCESS;

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/src/query/data_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/data_query.cpp b/modules/platforms/cpp/odbc/src/query/data_query.cpp
index 33e763f..2ad679b 100644
--- a/modules/platforms/cpp/odbc/src/query/data_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/data_query.cpp
@@ -169,9 +169,9 @@ namespace ignite
 
             SqlResult::Type DataQuery::MakeRequestExecute()
             {
-                const std::string& cacheName = connection.GetCache();
+                const std::string& schema = connection.GetSchema();
 
-                QueryExecuteRequest req(cacheName, sql, params);
+                QueryExecuteRequest req(schema, sql, params);
                 QueryExecuteResponse rsp;
 
                 try
@@ -199,12 +199,12 @@ namespace ignite
                 resultMeta.assign(rsp.GetMeta().begin(), rsp.GetMeta().end());
 
                 LOG_MSG("Query id: " << cursor->GetQueryId());
-                for (size_t i = 0; i < rsp.GetMeta().size(); ++i)
+                for (size_t i = 0; i < resultMeta.size(); ++i)
                 {
-                    LOG_MSG("\n[" << i << "] SchemaName:     " << rsp.GetMeta()[i].GetSchemaName()
-                        <<  "\n[" << i << "] TypeName:       " << rsp.GetMeta()[i].GetTableName()
-                        <<  "\n[" << i << "] ColumnName:     " << rsp.GetMeta()[i].GetColumnName()
-                        <<  "\n[" << i << "] ColumnType:     " << rsp.GetMeta()[i].GetDataType());
+                    LOG_MSG("\n[" << i << "] SchemaName:     " << resultMeta[i].GetSchemaName()
+                        <<  "\n[" << i << "] TypeName:       " << resultMeta[i].GetTableName()
+                        <<  "\n[" << i << "] ColumnName:     " << resultMeta[i].GetColumnName()
+                        <<  "\n[" << i << "] ColumnType:     " << static_cast<int32_t>(resultMeta[i].GetDataType()));
                 }
 
                 return SqlResult::AI_SUCCESS;

http://git-wip-us.apache.org/repos/asf/ignite/blob/2ba6ab42/modules/platforms/cpp/odbc/src/statement.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/statement.cpp b/modules/platforms/cpp/odbc/src/statement.cpp
index 99ec42e..3b078ae 100644
--- a/modules/platforms/cpp/odbc/src/statement.cpp
+++ b/modules/platforms/cpp/odbc/src/statement.cpp
@@ -488,13 +488,13 @@ namespace ignite
             if (currentQuery.get())
                 currentQuery->Close();
 
-            std::string cache(schema);
+            std::string schema0(schema);
 
-            if (cache.empty())
-                cache = connection.GetCache();
+            if (schema0.empty())
+                schema0 = connection.GetSchema();
 
             currentQuery.reset(new query::ColumnMetadataQuery(*this,
-                connection, cache, table, column));
+                connection, schema, table, column));
 
             return currentQuery->Execute();
         }
@@ -1026,10 +1026,10 @@ namespace ignite
 
             query::DataQuery* qry = static_cast<query::DataQuery*>(qry0);
 
-            const std::string& cacheName = connection.GetCache();
+            const std::string& schema = connection.GetSchema();
             const std::string& sql = qry->GetSql();
 
-            QueryGetParamsMetaRequest req(cacheName, sql);
+            QueryGetParamsMetaRequest req(schema, sql);
             QueryGetParamsMetaResponse rsp;
 
             try


[39/50] [abbrv] ignite git commit: IGNITE-5309: Added schema to SqlFieldsQuery for C++

Posted by sb...@apache.org.
IGNITE-5309: Added schema to SqlFieldsQuery for C++


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/2485b984
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/2485b984
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/2485b984

Branch: refs/heads/ignite-5075
Commit: 2485b984d78331605ff184a893e4fb22c15c77f9
Parents: 2ba6ab4
Author: Igor Sapego <is...@gridgain.com>
Authored: Mon Jun 5 17:14:29 2017 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Mon Jun 5 17:14:29 2017 +0300

----------------------------------------------------------------------
 .../ignite/cache/query/SqlFieldsQuery.java      | 12 +++--
 .../platform/cache/PlatformCache.java           |  4 +-
 .../core-test/config/cache-query-default.xml    | 27 ++++++----
 .../cpp/core-test/src/cache_query_test.cpp      | 47 +++++++++++++++--
 .../ignite/cache/query/query_sql_fields.h       | 53 +++++++++++++++++---
 .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs  |  1 +
 6 files changed, 118 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/2485b984/modules/core/src/main/java/org/apache/ignite/cache/query/SqlFieldsQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/query/SqlFieldsQuery.java b/modules/core/src/main/java/org/apache/ignite/cache/query/SqlFieldsQuery.java
index 93910dc..2838fe3 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/query/SqlFieldsQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/query/SqlFieldsQuery.java
@@ -291,18 +291,22 @@ public class SqlFieldsQuery extends Query<List<?>> {
     }
 
     /**
-     * Get schema.
+     * Get schema for the query.
+     * If not set, current cache name is used, which means you can
+     * omit schema name for tables within the current cache.
      *
-     * @return Schema.
+     * @return Schema. Null if schema is not set.
      */
     @Nullable public String getSchema() {
         return schema;
     }
 
     /**
-     * Set schema.
+     * Set schema for the query.
+     * If not set, current cache name is used, which means you can
+     * omit schema name for tables within the current cache.
      *
-     * @param schema Schema.
+     * @param schema Schema. Null to unset schema.
      * @return {@code this} for chaining.
      */
     public SqlFieldsQuery setSchema(@Nullable String schema) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/2485b984/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
index 13a8ca1..6207995 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
@@ -1312,6 +1312,7 @@ public class PlatformCache extends PlatformAbstractTarget {
         int timeout = reader.readInt();
         boolean replicated = reader.readBoolean();
         boolean collocated = reader.readBoolean();
+        String schema = reader.readString();
 
         return new SqlFieldsQuery(sql)
                 .setPageSize(pageSize)
@@ -1321,7 +1322,8 @@ public class PlatformCache extends PlatformAbstractTarget {
                 .setEnforceJoinOrder(enforceJoinOrder)
                 .setTimeout(timeout, TimeUnit.MILLISECONDS)
                 .setReplicatedOnly(replicated)
-                .setCollocated(collocated);
+                .setCollocated(collocated)
+                .setSchema(schema);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/2485b984/modules/platforms/cpp/core-test/config/cache-query-default.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/config/cache-query-default.xml b/modules/platforms/cpp/core-test/config/cache-query-default.xml
index 1c1e5f3..38636e5 100644
--- a/modules/platforms/cpp/core-test/config/cache-query-default.xml
+++ b/modules/platforms/cpp/core-test/config/cache-query-default.xml
@@ -94,12 +94,6 @@
                     <property name="atomicityMode" value="TRANSACTIONAL"/>
                     <property name="writeSynchronizationMode" value="FULL_SYNC"/>
 
-                    <property name="affinity">
-                        <bean class="org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction">
-                            <property name="partitions" value="256"/>
-                        </bean>
-                    </property>
-
                     <property name="queryEntities">
                         <list>
                             <bean class="org.apache.ignite.cache.QueryEntity">
@@ -121,18 +115,29 @@
                     <property name="atomicityMode" value="TRANSACTIONAL"/>
                     <property name="writeSynchronizationMode" value="FULL_SYNC"/>
 
-                    <property name="affinity">
-                        <bean class="org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction">
-                            <property name="partitions" value="256"/>
-                        </bean>
+                    <!-- Configure type metadata to enable queries. -->
+                    <property name="queryEntities">
+                        <list>
+                            <bean class="org.apache.ignite.cache.QueryEntity">
+                                <property name="keyType" value="java.lang.Integer"/>
+                                <property name="valueType" value="java.sql.Time"/>
+                            </bean>
+                        </list>
                     </property>
+                </bean>
+
+                <bean class="org.apache.ignite.configuration.CacheConfiguration">
+                    <property name="name" value="IntCache"/>
+                    <property name="cacheMode" value="PARTITIONED"/>
+                    <property name="atomicityMode" value="TRANSACTIONAL"/>
+                    <property name="writeSynchronizationMode" value="FULL_SYNC"/>
 
                     <!-- Configure type metadata to enable queries. -->
                     <property name="queryEntities">
                         <list>
                             <bean class="org.apache.ignite.cache.QueryEntity">
                                 <property name="keyType" value="java.lang.Integer"/>
-                                <property name="valueType" value="java.sql.Time"/>
+                                <property name="valueType" value="java.lang.Integer"/>
                             </bean>
                         </list>
                     </property>

http://git-wip-us.apache.org/repos/asf/ignite/blob/2485b984/modules/platforms/cpp/core-test/src/cache_query_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/src/cache_query_test.cpp b/modules/platforms/cpp/core-test/src/cache_query_test.cpp
index 65dcda5..e763e08 100644
--- a/modules/platforms/cpp/core-test/src/cache_query_test.cpp
+++ b/modules/platforms/cpp/core-test/src/cache_query_test.cpp
@@ -1094,14 +1094,14 @@ BOOST_AUTO_TEST_CASE(TestScanQueryPartitioned)
 
             std::stringstream stream;
             stream << "A" << key;
-            BOOST_REQUIRE(entry.GetValue().GetName().compare(stream.str()) == 0);
+            BOOST_REQUIRE_EQUAL(entry.GetValue().GetName().compare(stream.str()), 0);
 
-            BOOST_REQUIRE(entry.GetValue().GetAge() == key * 10);
+            BOOST_REQUIRE_EQUAL(entry.GetValue().GetAge(), key * 10);
         }
     }
 
     // Ensure that all keys were read.
-    BOOST_REQUIRE(keys.size() == entryCnt);
+    BOOST_CHECK_EQUAL(keys.size(), entryCnt);
 }
 
 /**
@@ -1915,4 +1915,45 @@ BOOST_AUTO_TEST_CASE(TestKeyValFields)
     }
 }
 
+/**
+ * Test query for Public schema.
+ */
+BOOST_AUTO_TEST_CASE(TestFieldsQuerySetSchema)
+{
+    Cache<int32_t, Time> timeCache = grid.GetCache<int32_t, Time>("TimeCache");
+
+    int32_t entryCnt = 1000; // Number of entries.
+
+    for (int i = 0; i < entryCnt; i++)
+    {
+        int secs = i % 60;
+        int mins = i / 60;
+        timeCache.Put(i, MakeTimeGmt(4, mins, secs));
+    }
+
+    Cache<int32_t, int32_t> intCache = grid.GetCache<int32_t, int32_t>("IntCache");
+
+    SqlFieldsQuery qry("select _key from Time where _val='04:11:02'");
+
+    BOOST_CHECK_EXCEPTION(intCache.Query(qry), IgniteError, ignite_test::IsGenericError);
+
+    qry.SetSchema("TimeCache");
+
+    QueryFieldsCursor cursor = intCache.Query(qry);
+
+    BOOST_REQUIRE(cursor.HasNext());
+
+    QueryFieldsRow row = cursor.GetNext();
+
+    BOOST_REQUIRE(row.HasNext());
+
+    int32_t key = row.GetNext<int32_t>();
+
+    BOOST_CHECK(key == 662);
+
+    BOOST_REQUIRE(!row.HasNext());
+
+    CheckEmpty(cursor);
+}
+
 BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/2485b984/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
index db26fc4..bf8d7ac 100644
--- a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
+++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
@@ -49,6 +49,7 @@ namespace ignite
                  */
                 SqlFieldsQuery(const std::string& sql) :
                     sql(sql),
+                    schema(),
                     pageSize(1024),
                     loc(false),
                     distributedJoins(false),
@@ -66,6 +67,7 @@ namespace ignite
                  */
                 SqlFieldsQuery(const std::string& sql, bool loc) :
                     sql(sql),
+                    schema(),
                     pageSize(1024),
                     loc(false),
                     distributedJoins(false),
@@ -82,6 +84,7 @@ namespace ignite
                  */
                 SqlFieldsQuery(const SqlFieldsQuery& other) :
                     sql(other.sql),
+                    schema(other.schema),
                     pageSize(other.pageSize),
                     loc(other.loc),
                     distributedJoins(other.distributedJoins),
@@ -133,12 +136,15 @@ namespace ignite
                 {
                     if (this != &other)
                     {
-                        std::swap(sql, other.sql);
-                        std::swap(pageSize, other.pageSize);
-                        std::swap(loc, other.loc);
-                        std::swap(distributedJoins, other.distributedJoins);
-                        std::swap(enforceJoinOrder, other.enforceJoinOrder);
-                        std::swap(args, other.args);
+                        using std::swap;
+
+                        swap(sql, other.sql);
+                        swap(sql, other.schema);
+                        swap(pageSize, other.pageSize);
+                        swap(loc, other.loc);
+                        swap(distributedJoins, other.distributedJoins);
+                        swap(enforceJoinOrder, other.enforceJoinOrder);
+                        swap(args, other.args);
                     }
                 }
 
@@ -276,6 +282,31 @@ namespace ignite
                 }
 
                 /**
+                 * Set schema name for the query.
+                 * If not set, current cache name is used, which means you can
+                 * omit schema name for tables within the current cache.
+                 * 
+                 * @param schema Schema. Empty string to unset.
+                 */
+                void SetSchema(const std::string& schema)
+                {
+                    this->schema = schema;
+                }
+
+                /**
+                 * Get schema name for the query.
+                 *
+                 * If not set, current cache name is used, which means you can
+                 * omit schema name for tables within the current cache.
+                 *
+                 * @return Schema. Empty string if not set.
+                 */
+                const std::string& GetSchema() const
+                {
+                    return schema;
+                }
+
+                /**
                  * Write query info to the stream.
                  *
                  * @param writer Writer.
@@ -295,15 +326,23 @@ namespace ignite
 
                     writer.WriteBool(distributedJoins);
                     writer.WriteBool(enforceJoinOrder);
-                    writer.WriteInt32(0);  // Timeout, ms
+                    writer.WriteInt32(0);     // Timeout, ms
                     writer.WriteBool(false);  // ReplicatedOnly
                     writer.WriteBool(false);  // Colocated
+
+                    if (schema.empty())
+                        writer.WriteNull();
+                    else
+                        writer.WriteString(schema);
                 }
 
             private:
                 /** SQL string. */
                 std::string sql;
 
+                /** SQL Schema. */
+                std::string schema;
+
                 /** Page size. */
                 int32_t pageSize;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/2485b984/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
index 95787eb..e280a8f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
@@ -1089,6 +1089,7 @@ namespace Apache.Ignite.Core.Impl.Cache
                 writer.WriteInt((int) qry.Timeout.TotalMilliseconds);
                 writer.WriteBoolean(qry.ReplicatedOnly);
                 writer.WriteBoolean(qry.Colocated);
+                writer.WriteString(null); // Schema
             });
         
             return new FieldsQueryCursor<T>(cursor, Marshaller, _flagKeepBinary, readerFunc);


[28/50] [abbrv] ignite git commit: IGNITE-5388 Added support to configuration of Ignite 2.x and Ignite 1.x.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/modules/states/configuration/summary/summary.worker.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/summary/summary.worker.js b/modules/web-console/frontend/app/modules/states/configuration/summary/summary.worker.js
index 5933f6c..6bf1182 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/summary/summary.worker.js
+++ b/modules/web-console/frontend/app/modules/states/configuration/summary/summary.worker.js
@@ -59,19 +59,20 @@ spec:\n\
 
 // eslint-disable-next-line no-undef
 onmessage = function(e) {
-    const {cluster, data, demo} = e.data;
+    const {cluster, data, demo, targetVer} = e.data;
 
     const zip = new JSZip();
 
     if (!data.docker)
-        data.docker = docker.generate(cluster, 'latest');
+        data.docker = docker.generate(cluster, targetVer);
 
     zip.file('Dockerfile', data.docker);
     zip.file('.dockerignore', docker.ignoreFile());
 
-    const cfg = generator.igniteConfiguration(cluster, false);
-    const clientCfg = generator.igniteConfiguration(cluster, true);
-    const clientNearCaches = _.filter(cluster.caches, (cache) => _.get(cache, 'clientNearConfiguration.enabled'));
+    const cfg = generator.igniteConfiguration(cluster, targetVer.ignite, false);
+    const clientCfg = generator.igniteConfiguration(cluster, targetVer.ignite, true);
+    const clientNearCaches = _.filter(cluster.caches, (cache) =>
+        cache.mode === 'PARTITIONED' && _.get(cache, 'clientNearConfiguration.enabled'));
 
     const secProps = properties.generate(cfg);
 
@@ -118,7 +119,7 @@ onmessage = function(e) {
     zip.file(`${startupPath}/ClientNodeCodeStartup.java`, java.nodeStartup(cluster, 'startup.ClientNodeCodeStartup',
         'ClientConfigurationFactory.createConfiguration()', 'config.ClientConfigurationFactory', clientNearCaches));
 
-    zip.file('pom.xml', maven.generate(cluster));
+    zip.file('pom.xml', maven.generate(cluster, targetVer));
 
     zip.file('README.txt', readme.generate());
     zip.file('jdbc-drivers/README.txt', readme.generateJDBC());

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/primitives/btn-group/index.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/btn-group/index.pug b/modules/web-console/frontend/app/primitives/btn-group/index.pug
index c047b25..702da60 100644
--- a/modules/web-console/frontend/app/primitives/btn-group/index.pug
+++ b/modules/web-console/frontend/app/primitives/btn-group/index.pug
@@ -14,19 +14,23 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 
-mixin btn-group(actions, tip)
+mixin btn-group(disabled, options, tip)
     .btn-group.panel-tip-container&attributes(attributes)
         button.btn.btn-primary(
-            ng-click=`${actions[0].click}`
+            ng-click=`${options[0].click}`
+
+            data-ng-disabled=disabled && `${disabled}`
 
             bs-tooltip=''
             data-title=tip
 
             data-trigger='hover'
             data-placement='bottom'
-        ) #{actions[0].text}
+        ) #{options[0].text}
         button.btn.dropdown-toggle.btn-primary(
-            bs-dropdown=`${JSON.stringify(actions)}`
+            data-ng-disabled=disabled && `${disabled}` || `!${JSON.stringify(options)}.length`
+
+            bs-dropdown=`${JSON.stringify(options)}`
 
             data-toggle='dropdown'
             data-container='body'

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/primitives/btn/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/btn/index.scss b/modules/web-console/frontend/app/primitives/btn/index.scss
index e10bef6..bba4ecc 100644
--- a/modules/web-console/frontend/app/primitives/btn/index.scss
+++ b/modules/web-console/frontend/app/primitives/btn/index.scss
@@ -58,6 +58,7 @@
     font-size: 14px;
     line-height: 16px;
     text-decoration: none;
+    cursor: pointer;
 
     .icon {
         &, &-right, &-left {
@@ -82,6 +83,11 @@
         line-height: inherit !important;
         font-size: 16px;
     }
+
+    &[disabled] {
+        -webkit-pointer-events: none;
+        pointer-events: none;
+    }
 }
 
 .btn-ignite--primary {

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/primitives/dropdown/index.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/dropdown/index.pug b/modules/web-console/frontend/app/primitives/dropdown/index.pug
index 7015433..3a5f1b1 100644
--- a/modules/web-console/frontend/app/primitives/dropdown/index.pug
+++ b/modules/web-console/frontend/app/primitives/dropdown/index.pug
@@ -16,7 +16,7 @@
 
 mixin ignite-form-field-bsdropdown(label, model, name, disabled, required, options, tip)
     .dropdown--ignite.ignite-form-field
-        button.btn-ignite.btn-ignite--primary-outline(
+        .btn-ignite.btn-ignite--primary-outline(
             data-ng-model=model
 
             data-ng-required=required && `${required}`
@@ -27,7 +27,6 @@ mixin ignite-form-field-bsdropdown(label, model, name, disabled, required, optio
             data-trigger='hover focus'
             data-placement='bottom-right'
             data-container='self'
-            data-animation=''
 
             tabindex='0'
             aria-haspopup='true'

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/app/primitives/dropdown/index.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/primitives/dropdown/index.scss b/modules/web-console/frontend/app/primitives/dropdown/index.scss
index 443324c..a3252cc 100644
--- a/modules/web-console/frontend/app/primitives/dropdown/index.scss
+++ b/modules/web-console/frontend/app/primitives/dropdown/index.scss
@@ -17,10 +17,12 @@
 
 @import '../../../public/stylesheets/variables';
 
-.dropdown--ignite {
+.ignite-form-field {
     font-style: normal;
 
     ul.dropdown-menu {
+        z-index: 1;
+        min-width: calc(100% + 2px);
         margin-top: 2px;
         padding: 0;
 
@@ -44,3 +46,18 @@
         }
     }
 }
+
+.dropdown--ignite {
+    button, .btn-ignite {
+        position: relative;
+
+        &::after {
+            content: '';
+            position: absolute;
+            bottom: -4px;
+            display: block;
+            height: 4px;
+            width: 100%;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/caches-controller.js b/modules/web-console/frontend/controllers/caches-controller.js
index bf97692..23a0608 100644
--- a/modules/web-console/frontend/controllers/caches-controller.js
+++ b/modules/web-console/frontend/controllers/caches-controller.js
@@ -18,9 +18,40 @@
 import infoMessageTemplateUrl from 'views/templates/message.tpl.pug';
 
 // Controller for Caches screen.
-export default ['cachesController', [
-    '$scope', '$http', '$state', '$filter', '$timeout', '$modal', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteInput', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils', 'IgniteLegacyTable',
-    function($scope, $http, $state, $filter, $timeout, $modal, LegacyUtils, Messages, Confirm, Input, Loading, ModelNormalizer, UnsavedChangesGuard, Resource, ErrorPopover, FormUtils, LegacyTable) {
+export default ['$scope', '$http', '$state', '$filter', '$timeout', '$modal', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteInput', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils', 'IgniteLegacyTable', 'IgniteVersion',
+    function($scope, $http, $state, $filter, $timeout, $modal, LegacyUtils, Messages, Confirm, Input, Loading, ModelNormalizer, UnsavedChangesGuard, Resource, ErrorPopover, FormUtils, LegacyTable, Version) {
+        this.available = Version.available.bind(Version);
+
+        const rebuildDropdowns = () => {
+            $scope.affinityFunction = [
+                {value: 'Rendezvous', label: 'Rendezvous'},
+                {value: 'Custom', label: 'Custom'},
+                {value: null, label: 'Default'}
+            ];
+
+            if (this.available(['1.0.0', '2.0.0']))
+                $scope.affinityFunction.splice(1, 0, {value: 'Fair', label: 'Fair'});
+        };
+
+        rebuildDropdowns();
+
+        const filterModel = () => {
+            if ($scope.backupItem) {
+                if (this.available('2.0.0')) {
+                    if (_.get($scope.backupItem, 'affinity.kind') === 'Fair')
+                        $scope.backupItem.affinity.kind = null;
+                }
+            }
+        };
+
+        Version.currentSbj.subscribe({
+            next: () => {
+                rebuildDropdowns();
+
+                filterModel();
+            }
+        });
+
         UnsavedChangesGuard.install($scope);
 
         const emptyCache = {empty: true};
@@ -34,6 +65,7 @@ export default ['cachesController', [
                     hibernateProperties: []
                 }
             },
+            writeBehindCoalescing: true,
             nearConfiguration: {},
             sqlFunctionClasses: []
         };
@@ -82,6 +114,22 @@ export default ['cachesController', [
             }, []);
         }
 
+        const setOffHeapMode = (item) => {
+            if (_.isNil(item.offHeapMaxMemory))
+                return;
+
+            return item.offHeapMode = Math.sign(item.offHeapMaxMemory);
+        };
+
+        const setOffHeapMaxMemory = (value) => {
+            const item = $scope.backupItem;
+
+            if (_.isNil(value) || value <= 0)
+                return item.offHeapMaxMemory = value;
+
+            item.offHeapMaxMemory = item.offHeapMaxMemory > 0 ? item.offHeapMaxMemory : null;
+        };
+
         $scope.tablePairSave = LegacyTable.tablePairSave;
         $scope.tablePairSaveVisible = LegacyTable.tablePairSaveVisible;
         $scope.tableNewItem = LegacyTable.tableNewItem;
@@ -220,6 +268,8 @@ export default ['cachesController', [
                         form.$setDirty();
                 }, true);
 
+                $scope.$watch('backupItem.offHeapMode', setOffHeapMaxMemory);
+
                 $scope.$watch('ui.activePanels.length', () => {
                     ErrorPopover.hide();
                 });
@@ -263,8 +313,12 @@ export default ['cachesController', [
                     $scope.ui.inputForm.$setPristine();
                 }
 
+                setOffHeapMode($scope.backupItem);
+
                 __original_value = ModelNormalizer.normalize($scope.backupItem);
 
+                filterModel();
+
                 if (LegacyUtils.getQueryVariable('new'))
                     $state.go('base.configuration.caches');
             }
@@ -416,9 +470,18 @@ export default ['cachesController', [
             if (LegacyUtils.isEmptyString(item.name))
                 return ErrorPopover.show('cacheNameInput', 'Cache name should not be empty!', $scope.ui, 'general');
 
+            if (item.memoryMode === 'ONHEAP_TIERED' && item.offHeapMaxMemory > 0 && !LegacyUtils.isDefined(item.evictionPolicy.kind))
+                return ErrorPopover.show('evictionPolicyKindInput', 'Eviction policy should be configured!', $scope.ui, 'memory');
+
             if (!LegacyUtils.checkFieldValidators($scope.ui))
                 return false;
 
+            if (item.memoryMode === 'OFFHEAP_VALUES' && !_.isEmpty(item.domains))
+                return ErrorPopover.show('memoryModeInput', 'Query indexing could not be enabled while values are stored off-heap!', $scope.ui, 'memory');
+
+            if (item.memoryMode === 'OFFHEAP_TIERED' && item.offHeapMaxMemory === -1)
+                return ErrorPopover.show('offHeapModeInput', 'Invalid value!', $scope.ui, 'memory');
+
             if (!checkEvictionPolicy(item.evictionPolicy))
                 return false;
 
@@ -587,4 +650,4 @@ export default ['cachesController', [
                 });
         };
     }
-]];
+];

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/clusters-controller.js b/modules/web-console/frontend/controllers/clusters-controller.js
index dba56fc..6861fe7 100644
--- a/modules/web-console/frontend/controllers/clusters-controller.js
+++ b/modules/web-console/frontend/controllers/clusters-controller.js
@@ -16,16 +16,68 @@
  */
 
 // Controller for Clusters screen.
-export default ['clustersController', [
-    '$rootScope', '$scope', '$http', '$state', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteInput', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteEventGroups', 'DemoInfo', 'IgniteLegacyTable', 'IgniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils',
-    function($root, $scope, $http, $state, $timeout, LegacyUtils, Messages, Confirm, Input, Loading, ModelNormalizer, UnsavedChangesGuard, igniteEventGroups, DemoInfo, LegacyTable, Resource, ErrorPopover, FormUtils) {
+export default ['$rootScope', '$scope', '$http', '$state', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteInput', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteEventGroups', 'DemoInfo', 'IgniteLegacyTable', 'IgniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils', 'IgniteVersion',
+    function($root, $scope, $http, $state, $timeout, LegacyUtils, Messages, Confirm, Input, Loading, ModelNormalizer, UnsavedChangesGuard, igniteEventGroups, DemoInfo, LegacyTable, Resource, ErrorPopover, FormUtils, Version) {
+        let __original_value;
+
+        this.available = Version.available.bind(Version);
+
+        const rebuildDropdowns = () => {
+            $scope.eventStorage = [
+                {value: 'Memory', label: 'Memory'},
+                {value: 'Custom', label: 'Custom'}
+            ];
+
+            $scope.marshallerVariant = [
+                {value: 'JdkMarshaller', label: 'JdkMarshaller'},
+                {value: null, label: 'Default'}
+            ];
+
+            if (this.available('2.0.0')) {
+                $scope.eventStorage.push({value: null, label: 'Disabled'});
+
+                $scope.eventGroups = _.filter(igniteEventGroups, ({value}) => value !== 'EVTS_SWAPSPACE');
+            }
+            else {
+                $scope.eventGroups = igniteEventGroups;
+
+                $scope.marshallerVariant.splice(0, 0, {value: 'OptimizedMarshaller', label: 'OptimizedMarshaller'});
+            }
+        };
+
+        rebuildDropdowns();
+
+        const filterModel = () => {
+            if ($scope.backupItem) {
+                if (this.available('2.0.0')) {
+                    const evtGrps = _.map($scope.eventGroups, 'value');
+
+                    _.remove(__original_value, (evtGrp) => !_.includes(evtGrps, evtGrp));
+                    _.remove($scope.backupItem.includeEventTypes, (evtGrp) => !_.includes(evtGrps, evtGrp));
+
+                    if (_.get($scope.backupItem, 'marshaller.kind') === 'OptimizedMarshaller')
+                        $scope.backupItem.marshaller.kind = null;
+                }
+                else if ($scope.backupItem && !_.get($scope.backupItem, 'eventStorage.kind'))
+                    _.set($scope.backupItem, 'eventStorage.kind', 'Memory');
+            }
+        };
+
+        Version.currentSbj.subscribe({
+            next: () => {
+                rebuildDropdowns();
+
+                filterModel();
+            }
+        });
+
         UnsavedChangesGuard.install($scope);
 
         const emptyCluster = {empty: true};
 
-        let __original_value;
-
         const blank = {
+            activeOnStart: true,
+            cacheSanityCheckEnabled: true,
             atomicConfiguration: {},
             binaryConfiguration: {},
             cacheKeyConfiguration: [],
@@ -48,8 +100,17 @@ export default ['clustersController', [
             sslContextFactory: {
                 trustManagers: []
             },
+            swapSpaceSpi: {},
             transactionConfiguration: {},
-            collision: {}
+            collision: {},
+            memoryConfiguration: {
+                memoryPolicies: []
+            },
+            hadoopConfiguration: {
+                nativeLibraryNames: []
+            },
+            serviceConfigurations: [],
+            executorConfiguration: []
         };
 
         const pairFields = {
@@ -149,6 +210,12 @@ export default ['clustersController', [
                     else
                         $scope.backupItem.checkpointSpi = [newCheckpointCfg];
                 }
+                else if (field.type === 'memoryPolicies')
+                    $scope.backupItem.memoryConfiguration.memoryPolicies.push({});
+                else if (field.type === 'serviceConfigurations')
+                    $scope.backupItem.serviceConfigurations.push({});
+                else if (field.type === 'executorConfigurations')
+                    $scope.backupItem.executorConfiguration.push({});
                 else
                     LegacyTable.tableNewItem(field);
             }
@@ -231,7 +298,10 @@ export default ['clustersController', [
             {value: 'Kubernetes', label: 'Kubernetes'}
         ];
 
-        $scope.eventGroups = igniteEventGroups;
+        $scope.swapSpaceSpis = [
+            {value: 'FileSwapSpaceSpi', label: 'File-based swap'},
+            {value: null, label: 'Not set'}
+        ];
 
         $scope.clusters = [];
 
@@ -285,6 +355,18 @@ export default ['clustersController', [
                             scanners: []
                         }};
                     }
+
+                    if (!cluster.memoryConfiguration)
+                        cluster.memoryConfiguration = { memoryPolicies: [] };
+
+                    if (!cluster.hadoopConfiguration)
+                        cluster.hadoopConfiguration = { nativeLibraryNames: [] };
+
+                    if (!cluster.serviceConfigurations)
+                        cluster.serviceConfigurations = [];
+
+                    if (!cluster.executorConfiguration)
+                        cluster.executorConfiguration = [];
                 });
 
                 if ($state.params.linkId)
@@ -328,6 +410,9 @@ export default ['clustersController', [
                             (selCache) => selCache === cache.value
                         )
                     );
+
+                    $scope.clusterCachesEmpty = _.clone($scope.clusterCaches);
+                    $scope.clusterCachesEmpty.push({label: 'Not set'});
                 }, true);
 
                 $scope.$watch('ui.activePanels.length', () => {
@@ -349,6 +434,7 @@ export default ['clustersController', [
             });
 
         $scope.clusterCaches = [];
+        $scope.clusterCachesEmpty = [];
 
         $scope.selectItem = function(item, backup) {
             function selectItem() {
@@ -380,6 +466,8 @@ export default ['clustersController', [
 
                 __original_value = ModelNormalizer.normalize($scope.backupItem);
 
+                filterModel();
+
                 if (LegacyUtils.getQueryVariable('new'))
                     $state.go('base.configuration.clusters');
             }
@@ -602,6 +690,36 @@ export default ['clustersController', [
             }));
         }
 
+        function checkMemoryConfiguration(item) {
+            const memory = item.memoryConfiguration;
+
+            if ((memory.systemCacheMaxSize || 104857600) < (memory.systemCacheInitialSize || 41943040))
+                return ErrorPopover.show('systemCacheMaxSize', 'System cache maximum size should be greater than initial size', $scope.ui, 'memoryConfiguration');
+
+            const pageSize = memory.pageSize;
+
+            if (pageSize > 0 && (pageSize & (pageSize - 1) !== 0)) {
+                ErrorPopover.show('MemoryConfigurationPageSize', 'Page size must be power of 2', $scope.ui, 'memoryConfiguration');
+
+                return false;
+            }
+
+            const dfltPlc = memory.defaultMemoryPolicyName;
+
+            if (!_.isEmpty(dfltPlc) && !_.find(memory.memoryPolicies, (plc) => plc.name === dfltPlc))
+                return ErrorPopover.show('defaultMemoryPolicyName', 'Memory policy with that name should be configured', $scope.ui, 'memoryConfiguration');
+
+            return _.isNil(_.find(memory.memoryPolicies, (curPlc, curIx) => {
+                if (_.find(memory.memoryPolicies, (plc, ix) => curIx > ix && (curPlc.name || 'default') === (plc.name || 'default'))) {
+                    ErrorPopover.show('MemoryPolicyName' + curIx, 'Memory policy with that name is already configured', $scope.ui, 'memoryConfiguration');
+
+                    return true;
+                }
+
+                return false;
+            }));
+        }
+
         function checkODBC(item) {
             if (_.get(item, 'odbc.odbcEnabled') && _.get(item, 'marshaller.kind'))
                 return ErrorPopover.show('odbcEnabledInput', 'ODBC can only be used with BinaryMarshaller', $scope.ui, 'odbcConfiguration');
@@ -609,6 +727,38 @@ export default ['clustersController', [
             return true;
         }
 
+        function checkSwapConfiguration(item) {
+            const swapKind = item.swapSpaceSpi && item.swapSpaceSpi.kind;
+
+            if (swapKind && item.swapSpaceSpi[swapKind]) {
+                const swap = item.swapSpaceSpi[swapKind];
+
+                const sparsity = swap.maximumSparsity;
+
+                if (LegacyUtils.isDefined(sparsity) && (sparsity < 0 || sparsity >= 1))
+                    return ErrorPopover.show('maximumSparsityInput', 'Maximum sparsity should be more or equal 0 and less than 1!', $scope.ui, 'swap');
+
+                const readStripesNumber = swap.readStripesNumber;
+
+                if (readStripesNumber && !(readStripesNumber === -1 || (readStripesNumber & (readStripesNumber - 1)) === 0))
+                    return ErrorPopover.show('readStripesNumberInput', 'Read stripe size must be positive and power of two!', $scope.ui, 'swap');
+            }
+
+            return true;
+        }
+
+        function checkServiceConfiguration(item) {
+            return _.isNil(_.find(_.get(item, 'serviceConfigurations'), (curSrv, curIx) => {
+                if (_.find(item.serviceConfigurations, (srv, ix) => curIx > ix && curSrv.name === srv.name)) {
+                    ErrorPopover.show('ServiceName' + curIx, 'Service configuration with that name is already configured', $scope.ui, 'serviceConfiguration');
+
+                    return true;
+                }
+
+                return false;
+            }));
+        }
+
         function checkSslConfiguration(item) {
             const r = item.connector;
 
@@ -632,7 +782,15 @@ export default ['clustersController', [
             if (item.rebalanceThreadPoolSize && item.systemThreadPoolSize && item.systemThreadPoolSize <= item.rebalanceThreadPoolSize)
                 return ErrorPopover.show('rebalanceThreadPoolSizeInput', 'Rebalance thread pool size exceed or equals System thread pool size!', $scope.ui, 'pools');
 
-            return true;
+            return _.isNil(_.find(_.get(item, 'executorConfiguration'), (curExec, curIx) => {
+                if (_.find(item.executorConfiguration, (srv, ix) => curIx > ix && curExec.name === srv.name)) {
+                    ErrorPopover.show('ExecutorName' + curIx, 'Executor configuration with that name is already configured', $scope.ui, 'pools');
+
+                    return true;
+                }
+
+                return false;
+            }));
         }
 
         // Check cluster logical consistency.
@@ -669,9 +827,18 @@ export default ['clustersController', [
             if (!checkLoadBalancingConfiguration(item))
                 return false;
 
+            if (!checkMemoryConfiguration(item))
+                return false;
+
             if (!checkODBC(item))
                 return false;
 
+            if (!checkSwapConfiguration(item))
+                return false;
+
+            if (!checkServiceConfiguration(item))
+                return false;
+
             if (!checkSslConfiguration(item))
                 return false;
 
@@ -726,6 +893,11 @@ export default ['clustersController', [
         $scope.saveItem = function() {
             const item = $scope.backupItem;
 
+            const swapConfigured = item.swapSpaceSpi && item.swapSpaceSpi.kind;
+
+            if (!swapConfigured && _.find(clusterCaches(item), (cache) => cache.swapEnabled))
+                _.merge(item, {swapSpaceSpi: {kind: 'FileSwapSpaceSpi'}});
+
             if (validate(item))
                 save(item);
         };
@@ -812,4 +984,4 @@ export default ['clustersController', [
                 });
         };
     }
-]];
+];

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/controllers/domains-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/domains-controller.js b/modules/web-console/frontend/controllers/domains-controller.js
index 3c8830b..992c829 100644
--- a/modules/web-console/frontend/controllers/domains-controller.js
+++ b/modules/web-console/frontend/controllers/domains-controller.js
@@ -18,8 +18,7 @@
 import templateUrl from 'views/configuration/domains-import.tpl.pug';
 
 // Controller for Domain model screen.
-export default ['domainsController', [
-    '$rootScope', '$scope', '$http', '$state', '$filter', '$timeout', '$modal', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteFocus', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteInput', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'AgentManager', 'IgniteLegacyTable', 'IgniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils', 'JavaTypes', 'SqlTypes', 'IgniteActivitiesData',
+export default ['$rootScope', '$scope', '$http', '$state', '$filter', '$timeout', '$modal', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteFocus', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteInput', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'AgentManager', 'IgniteLegacyTable', 'IgniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils', 'JavaTypes', 'SqlTypes', 'IgniteActivitiesData',
     function($root, $scope, $http, $state, $filter, $timeout, $modal, LegacyUtils, Messages, Focus, Confirm, ConfirmBatch, Input, Loading, ModelNormalizer, UnsavedChangesGuard, agentMgr, LegacyTable, Resource, ErrorPopover, FormUtils, JavaTypes, SqlTypes, ActivitiesData) {
         UnsavedChangesGuard.install($scope);
 
@@ -462,7 +461,7 @@ export default ['domainsController', [
 
                 $scope.importDomain.loadingOptions = LOADING_JDBC_DRIVERS;
 
-                agentMgr.startAgentWatch('Back to Domain models', 'import domain model from database')
+                agentMgr.startAgentWatch('Back to Domain models')
                     .then(() => {
                         ActivitiesData.post({
                             group: 'configuration',
@@ -1875,4 +1874,4 @@ export default ['domainsController', [
                 });
         };
     }
-]];
+];

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/controllers/igfs-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/igfs-controller.js b/modules/web-console/frontend/controllers/igfs-controller.js
index 504e28d..5d9f4a2 100644
--- a/modules/web-console/frontend/controllers/igfs-controller.js
+++ b/modules/web-console/frontend/controllers/igfs-controller.js
@@ -16,9 +16,10 @@
  */
 
 // Controller for IGFS screen.
-export default ['igfsController', [
-    '$scope', '$http', '$state', '$filter', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteInput', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteLegacyTable', 'IgniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils',
-    function($scope, $http, $state, $filter, $timeout, LegacyUtils, Messages, Confirm, Input, Loading, ModelNormalizer, UnsavedChangesGuard, LegacyTable, Resource, ErrorPopover, FormUtils) {
+export default ['$scope', '$http', '$state', '$filter', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteInput', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteLegacyTable', 'IgniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils', 'IgniteVersion',
+    function($scope, $http, $state, $filter, $timeout, LegacyUtils, Messages, Confirm, Input, Loading, ModelNormalizer, UnsavedChangesGuard, LegacyTable, Resource, ErrorPopover, FormUtils, Version) {
+        this.available = Version.available.bind(Version);
+
         UnsavedChangesGuard.install($scope);
 
         const emptyIgfs = {empty: true};
@@ -411,4 +412,4 @@ export default ['igfsController', [
                 });
         };
     }
-]];
+];

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/public/stylesheets/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/style.scss b/modules/web-console/frontend/public/stylesheets/style.scss
index 4054fb1..3ecb300 100644
--- a/modules/web-console/frontend/public/stylesheets/style.scss
+++ b/modules/web-console/frontend/public/stylesheets/style.scss
@@ -73,6 +73,16 @@ hr {
         cursor: default;
         pointer-events: none;
     }
+
+    version-picker {
+        margin-top: 10px;
+
+        & + hr {
+            margin-top: 10px;
+            margin-bottom: 10px;
+            margin-right: 20px;
+        }
+    }
 }
 
 .theme-line .sidebar-nav {
@@ -319,15 +329,6 @@ h1, h2, h3, h4, h5, h6 {
     }
 }
 
-.greedy {
-    min-height: 100%;
-    height: #{"calc(100vh - 270px)"};
-}
-
-.signin-greedy {
-    height: #{"calc(100vh - 300px)"};
-}
-
 body {
     overflow-x: hidden;
     display: flex;

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/test/unit/Version.test.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/test/unit/Version.test.js b/modules/web-console/frontend/test/unit/Version.test.js
index d8c8f65..b8477bf 100644
--- a/modules/web-console/frontend/test/unit/Version.test.js
+++ b/modules/web-console/frontend/test/unit/Version.test.js
@@ -23,39 +23,72 @@ import { suite, test } from 'mocha';
 import { assert } from 'chai';
 
 suite('VersionServiceTestsSuite', () => {
+    test('Parse 1.7.0-SNAPSHOT', () => {
+        const version = INSTANCE.parse('1.7.0-SNAPSHOT');
+        assert.equal(version.major, 1);
+        assert.equal(version.minor, 7);
+        assert.equal(version.maintenance, 0);
+        assert.equal(version.stage, 'SNAPSHOT');
+        assert.equal(version.revTs, 0);
+        assert.isNull(version.revHash);
+    });
+
+    test('Parse strip -DEV 1.7.0-DEV', () => {
+        const version = INSTANCE.parse('1.7.0-DEV');
+        assert.equal(version.major, 1);
+        assert.equal(version.minor, 7);
+        assert.equal(version.maintenance, 0);
+        assert.equal(version.stage, '');
+    });
+
+    test('Parse strip -n/a 1.7.0-n/a', () => {
+        const version = INSTANCE.parse('1.7.0-n/a');
+        assert.equal(version.major, 1);
+        assert.equal(version.minor, 7);
+        assert.equal(version.maintenance, 0);
+        assert.equal(version.stage, '');
+    });
+
     test('Check patch version', () => {
-        assert.equal(INSTANCE.compare('1.7.2', '1.7.1'), 1);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('1.7.2'), INSTANCE.parse('1.7.1')), 1);
     });
 
     test('Check minor version', () => {
-        assert.equal(INSTANCE.compare('1.8.1', '1.7.1'), 1);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('1.8.1'), INSTANCE.parse('1.7.1')), 1);
     });
 
     test('Check major version', () => {
-        assert.equal(INSTANCE.compare('2.7.1', '1.7.1'), 1);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('2.7.1'), INSTANCE.parse('1.7.1')), 1);
     });
 
     test('Version a > b', () => {
-        assert.equal(INSTANCE.compare('1.7.0', '1.5.0'), 1);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('1.7.0'), INSTANCE.parse('1.5.0')), 1);
     });
 
     test('Version a = b', () => {
-        assert.equal(INSTANCE.compare('1.0.0', '1.0.0'), 0);
-        assert.equal(INSTANCE.compare('1.2.0', '1.2.0'), 0);
-        assert.equal(INSTANCE.compare('1.2.3', '1.2.3'), 0);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('1.0.0'), INSTANCE.parse('1.0.0')), 0);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('1.2.0'), INSTANCE.parse('1.2.0')), 0);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('1.2.3'), INSTANCE.parse('1.2.3')), 0);
 
-        assert.equal(INSTANCE.compare('1.0.0-1', '1.0.0-1'), 0);
-        assert.equal(INSTANCE.compare('1.2.0-1', '1.2.0-1'), 0);
-        assert.equal(INSTANCE.compare('1.2.3-1', '1.2.3-1'), 0);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('1.0.0-1'), INSTANCE.parse('1.0.0-1')), 0);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('1.2.0-1'), INSTANCE.parse('1.2.0-1')), 0);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('1.2.3-1'), INSTANCE.parse('1.2.3-1')), 0);
     });
 
     test('Version a < b', () => {
-        assert.equal(INSTANCE.compare('1.5.1', '1.5.2'), -1);
+        assert.equal(INSTANCE.compare(INSTANCE.parse('1.5.1'), INSTANCE.parse('1.5.2')), -1);
     });
 
     test('Check since call', () => {
         assert.equal(INSTANCE.since('1.5.0', '1.5.0'), true);
         assert.equal(INSTANCE.since('1.6.0', '1.5.0'), true);
+        assert.equal(INSTANCE.since('1.5.4', ['1.5.5', '1.6.0'], ['1.6.2']), false);
+        assert.equal(INSTANCE.since('1.5.5', ['1.5.5', '1.6.0'], ['1.6.2']), true);
+        assert.equal(INSTANCE.since('1.5.11', ['1.5.5', '1.6.0'], ['1.6.2']), true);
+        assert.equal(INSTANCE.since('1.6.0', ['1.5.5', '1.6.0'], ['1.6.2']), false);
+        assert.equal(INSTANCE.since('1.6.1', ['1.5.5', '1.6.0'], '1.6.2'), false);
+        assert.equal(INSTANCE.since('1.6.2', ['1.5.5', '1.6.0'], ['1.6.2']), true);
+        assert.equal(INSTANCE.since('1.6.3', ['1.5.5', '1.6.0'], '1.6.2'), true);
     });
 
     test('Check wrong since call', () => {
@@ -70,44 +103,4 @@ suite('VersionServiceTestsSuite', () => {
     test('Check wrong before call', () => {
         assert.equal(INSTANCE.before('1.5.0', '1.3.0'), false);
     });
-
-    test('Check includes call', () => {
-        assert.equal(INSTANCE.includes('1.5.4', ['1.5.5', '1.6.0'], ['1.6.2']), false);
-        assert.equal(INSTANCE.includes('1.5.5', ['1.5.5', '1.6.0'], ['1.6.2']), true);
-        assert.equal(INSTANCE.includes('1.5.11', ['1.5.5', '1.6.0'], ['1.6.2']), true);
-        assert.equal(INSTANCE.includes('1.6.0', ['1.5.5', '1.6.0'], ['1.6.2']), false);
-        assert.equal(INSTANCE.includes('1.6.1', ['1.5.5', '1.6.0'], ['1.6.2']), false);
-        assert.equal(INSTANCE.includes('1.6.2', ['1.5.5', '1.6.0'], ['1.6.2']), true);
-        assert.equal(INSTANCE.includes('1.6.3', ['1.5.5', '1.6.0'], ['1.6.2']), true);
-    });
-
-    test('Check wrong before call', () => {
-        assert.equal(INSTANCE.before('1.5.0', '1.3.0'), false);
-    });
-
-    test('Parse 1.7.0-SNAPSHOT', () => {
-        const version = INSTANCE.parse('1.7.0-SNAPSHOT');
-        assert.equal(version.major, 1);
-        assert.equal(version.minor, 7);
-        assert.equal(version.maintenance, 0);
-        assert.equal(version.stage, 'SNAPSHOT');
-        assert.equal(version.revTs, 0);
-        assert.isNull(version.revHash);
-    });
-
-    test('Parse strip -DEV 1.7.0-DEV', () => {
-        const version = INSTANCE.parse('1.7.0-DEV');
-        assert.equal(version.major, 1);
-        assert.equal(version.minor, 7);
-        assert.equal(version.maintenance, 0);
-        assert.equal(version.stage, '');
-    });
-
-    test('Parse strip -n/a 1.7.0-n/a', () => {
-        const version = INSTANCE.parse('1.7.0-n/a');
-        assert.equal(version.major, 1);
-        assert.equal(version.minor, 7);
-        assert.equal(version.maintenance, 0);
-        assert.equal(version.stage, '');
-    });
 });

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/configuration/caches.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/configuration/caches.tpl.pug b/modules/web-console/frontend/views/configuration/caches.tpl.pug
index fca41a8..43b5d57 100644
--- a/modules/web-console/frontend/views/configuration/caches.tpl.pug
+++ b/modules/web-console/frontend/views/configuration/caches.tpl.pug
@@ -18,7 +18,7 @@ include /app/helpers/jade/mixins
 
 .docs-header
     h1 Configure Ignite Caches
-.docs-body(ng-controller='cachesController')
+.docs-body
     ignite-information
         ul
             li Configure #[a(href='https://apacheignite.readme.io/docs/data-grid' target='_blank') memory] settings

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/configuration/clusters.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/configuration/clusters.tpl.pug b/modules/web-console/frontend/views/configuration/clusters.tpl.pug
index 4a1df33..744ec7c 100644
--- a/modules/web-console/frontend/views/configuration/clusters.tpl.pug
+++ b/modules/web-console/frontend/views/configuration/clusters.tpl.pug
@@ -18,7 +18,7 @@ include /app/helpers/jade/mixins
 
 .docs-header
     h1 Configure Ignite Clusters
-.docs-body(ng-controller='clustersController')
+.docs-body
     ignite-information
         ul
             li Configure #[a(href='https://apacheignite.readme.io/docs/clustering' target='_blank') clusters] properties
@@ -52,13 +52,24 @@ include /app/helpers/jade/mixins
                             include /app/modules/states/configuration/clusters/discovery
                             include /app/modules/states/configuration/clusters/events
                             include /app/modules/states/configuration/clusters/failover
+                            include /app/modules/states/configuration/clusters/hadoop
                             include /app/modules/states/configuration/clusters/igfs
                             include /app/modules/states/configuration/clusters/load-balancing
                             include /app/modules/states/configuration/clusters/logger
                             include /app/modules/states/configuration/clusters/marshaller
+
+                            //- Since ignite 2.0
+                            include /app/modules/states/configuration/clusters/memory
+
+                            include /app/modules/states/configuration/clusters/misc
                             include /app/modules/states/configuration/clusters/metrics
                             include /app/modules/states/configuration/clusters/odbc
+                            include /app/modules/states/configuration/clusters/service
                             include /app/modules/states/configuration/clusters/ssl
+
+                            //- Removed in ignite 2.0
+                            include /app/modules/states/configuration/clusters/swap
+                                
                             include /app/modules/states/configuration/clusters/thread
                             include /app/modules/states/configuration/clusters/time
                             include /app/modules/states/configuration/clusters/transactions

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/configuration/domains.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/configuration/domains.tpl.pug b/modules/web-console/frontend/views/configuration/domains.tpl.pug
index a8f9b5c..9e3e297 100644
--- a/modules/web-console/frontend/views/configuration/domains.tpl.pug
+++ b/modules/web-console/frontend/views/configuration/domains.tpl.pug
@@ -18,7 +18,7 @@ include /app/helpers/jade/mixins
 
 .docs-header
     h1 Configure Domain Model And SQL Queries
-.docs-body(ng-controller='domainsController')
+.docs-body
     ignite-information
         ul: li Import database schemas
             li Configure indexed types

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/configuration/igfs.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/configuration/igfs.tpl.pug b/modules/web-console/frontend/views/configuration/igfs.tpl.pug
index dfc9ed2..46ee4c0 100644
--- a/modules/web-console/frontend/views/configuration/igfs.tpl.pug
+++ b/modules/web-console/frontend/views/configuration/igfs.tpl.pug
@@ -18,7 +18,7 @@ include /app/helpers/jade/mixins
 
 .docs-header
     h1 Configure Ignite In-memory File Systems
-.docs-body(ng-controller='igfsController')
+.docs-body
     ignite-information(data-title='Configure IGFS only if you are going to use In-memory File System')
         ul
             li Ignite File System (#[a(href='https://apacheignite-fs.readme.io/docs/in-memory-file-system' target='_blank') IGFS]) is an in-memory file system allowing work with files and directories over existing cache infrastructure
@@ -45,6 +45,10 @@ include /app/helpers/jade/mixins
                             include /app/modules/states/configuration/igfs/secondary
                             include /app/modules/states/configuration/igfs/ipc
                             include /app/modules/states/configuration/igfs/fragmentizer
+
+                            //- Removed in ignite 2.0
+                            include /app/modules/states/configuration/igfs/dual
+
                             include /app/modules/states/configuration/igfs/misc
 
                             +advanced-options-toggle-default

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/configuration/sidebar.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/configuration/sidebar.tpl.pug b/modules/web-console/frontend/views/configuration/sidebar.tpl.pug
index bba6b25..1442331 100644
--- a/modules/web-console/frontend/views/configuration/sidebar.tpl.pug
+++ b/modules/web-console/frontend/views/configuration/sidebar.tpl.pug
@@ -15,8 +15,10 @@
     limitations under the License.
 
 .row
-    .col-xs-3.col-sm-3.col-md-2.border-right.section-left.greedy
+    .col-xs-3.col-sm-3.col-md-2.border-right.section-left
         .sidebar-nav(bs-affix)
+            version-picker
+            hr
             ul.menu(ignite-sidebar)
                 li(ng-repeat='item in sidebar.items')
                     a(ui-sref-active='active' ui-sref='{{::item.sref}}')

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/includes/header-left.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/includes/header-left.pug b/modules/web-console/frontend/views/includes/header-left.pug
index 4dda1cc..deba568 100644
--- a/modules/web-console/frontend/views/includes/header-left.pug
+++ b/modules/web-console/frontend/views/includes/header-left.pug
@@ -21,7 +21,6 @@
         data-placement='bottom-left'
         data-trigger='hover focus'
         data-container='self'
-        data-animation=''
     )
         span Configure
             span.caret
@@ -41,7 +40,6 @@
             data-placement='bottom-left'
             data-trigger='hover focus'
             data-container='self'
-            data-animation=''
             aria-haspopup='true'
             aria-expanded='false'
         )
@@ -56,7 +54,6 @@
         data-placement='bottom-left'
         data-trigger='hover focus'
         data-container='self'
-        data-animation=''
         aria-haspopup='true'
         aria-expanded='false'
     )

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/includes/header-right.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/includes/header-right.pug b/modules/web-console/frontend/views/includes/header-right.pug
index 62227e9..de67445 100644
--- a/modules/web-console/frontend/views/includes/header-right.pug
+++ b/modules/web-console/frontend/views/includes/header-right.pug
@@ -34,7 +34,6 @@ ignite-cluster-select.wch-nav-item(ng-if='!IgniteDemoMode')
         data-placement='bottom-right'
         data-trigger='hover focus'
         data-container='self'
-        data-animation=''
     )
         span {{$root.user.firstName}} {{$root.user.lastName}}
             span.caret

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/settings/admin.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/settings/admin.tpl.pug b/modules/web-console/frontend/views/settings/admin.tpl.pug
index a8df240..3c49eb6 100644
--- a/modules/web-console/frontend/views/settings/admin.tpl.pug
+++ b/modules/web-console/frontend/views/settings/admin.tpl.pug
@@ -15,7 +15,7 @@
     limitations under the License.
 
 .admin-page.row
-    .docs-content.greedy
+    .docs-content
         header
             h1 Admin panel
         .docs-body

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/settings/profile.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/settings/profile.tpl.pug b/modules/web-console/frontend/views/settings/profile.tpl.pug
index 6f91f8f..54c8105 100644
--- a/modules/web-console/frontend/views/settings/profile.tpl.pug
+++ b/modules/web-console/frontend/views/settings/profile.tpl.pug
@@ -18,7 +18,7 @@ mixin lbl(txt)
     label.col-sm-2.required.labelFormField #{txt}
 
 .row(ng-controller='profileController')
-    .docs-content.greedy
+    .docs-content
         .docs-header
             h1 User profile
             hr

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/signin.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/signin.tpl.pug b/modules/web-console/frontend/views/signin.tpl.pug
index a32733d..c7e2027 100644
--- a/modules/web-console/frontend/views/signin.tpl.pug
+++ b/modules/web-console/frontend/views/signin.tpl.pug
@@ -97,7 +97,7 @@ web-console-header
                         ignite-features
                 .col-xs-12.col-md-6
                     #carousel.carousel.slide
-                        // Indicators
+                        //- Indicators
                         ol.carousel-indicators
                             li.active(data-target='#carousel', data-slide-to='0')
                             li(data-target='#carousel', data-slide-to='1')
@@ -106,7 +106,7 @@ web-console-header
                             li(data-target='#carousel', data-slide-to='4')
                             li(data-target='#carousel', data-slide-to='5')
                             li(data-target='#carousel', data-slide-to='6')
-                        // Wrapper for slides
+                        //- Wrapper for slides
                         .carousel-inner(role='listbox')
                             .item.active
                                 img(src='/images/cluster.png', alt='Clusters screen')
@@ -143,7 +143,7 @@ web-console-header
                                 .carousel-caption
                                     h3 Query chart
                                     p View data in tabular form and as charts
-                        // Controls
+                        //- Controls
                         a.left.carousel-control(href='#carousel', ng-click='$event.preventDefault()', role='button', data-slide='prev')
                             span.fa.fa-chevron-left(aria-hidden='true')
                             span.sr-only Previous

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/views/sql/sql.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/sql/sql.tpl.pug b/modules/web-console/frontend/views/sql/sql.tpl.pug
index dd2754d..65597a3 100644
--- a/modules/web-console/frontend/views/sql/sql.tpl.pug
+++ b/modules/web-console/frontend/views/sql/sql.tpl.pug
@@ -133,8 +133,8 @@ mixin table-result-heading-query
                 +result-toolbar
         .col-xs-4
             .pull-right
-                -var actions = [{ text: "Export", click: 'exportCsv(paragraph)' }, { text: 'Export all', click: 'exportCsvAll(paragraph)' }]
-                +btn-group(actions, '{{ actionTooltip(paragraph, "export", false) }}')(ng-disabled='paragraph.loading')
+                -var options = [{ text: "Export", click: 'exportCsv(paragraph)' }, { text: 'Export all', click: 'exportCsvAll(paragraph)' }]
+                +btn-group('paragraph.loading', options, '{{ actionTooltip(paragraph, "export", false) }}')
 
 mixin table-result-heading-scan
     .total.row
@@ -148,8 +148,8 @@ mixin table-result-heading-scan
                 +result-toolbar
         .col-xs-4
             .pull-right
-                -var actions = [{ text: "Export", click: 'exportCsv(paragraph)' }, { text: 'Export all', click: 'exportCsvAll(paragraph)' }]
-                +btn-group(actions, '{{ actionTooltip(paragraph, "export", false) }}')(ng-disabled='paragraph.loading')
+                -var options = [{ text: "Export", click: 'exportCsv(paragraph)' }, { text: 'Export all', click: 'exportCsvAll(paragraph)' }]
+                +btn-group('paragraph.loading', options, '{{ actionTooltip(paragraph, "export", false) }}')
 
 mixin table-result-body
     .grid(ui-grid='paragraph.gridOptions' ui-grid-resize-columns ui-grid-exporter)

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/webpack/webpack.common.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/webpack/webpack.common.js b/modules/web-console/frontend/webpack/webpack.common.js
index 5fefd59..a303d6e 100644
--- a/modules/web-console/frontend/webpack/webpack.common.js
+++ b/modules/web-console/frontend/webpack/webpack.common.js
@@ -52,8 +52,7 @@ export default {
     output: {
         path: path.resolve('build'),
         filename: '[name].[chunkhash].js',
-        publicPath: '/',
-        sourceMapFilename: '[name].[chunkhash].map'
+        publicPath: '/'
     },
 
     // Resolves modules.
@@ -62,8 +61,9 @@ export default {
         // A list of module source folders.
         alias: {
             app,
-            images: path.resolve('public/images'),
-            views: path.resolve('views'),
+            images: path.join(basedir, 'public/images'),
+            views: path.join(basedir, 'views'),
+            Controllers: path.join(basedir, 'controllers'),
             IgniteModules
         }
     },

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/frontend/webpack/webpack.dev.babel.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/webpack/webpack.dev.babel.js b/modules/web-console/frontend/webpack/webpack.dev.babel.js
index dc5cd41..56371cda 100644
--- a/modules/web-console/frontend/webpack/webpack.dev.babel.js
+++ b/modules/web-console/frontend/webpack/webpack.dev.babel.js
@@ -87,10 +87,7 @@ export default merge(commonCfg, {
             aggregateTimeout: 1000,
             poll: 2000
         },
-        stats: {
-            colors: true,
-            chunks: false
-        },
+        stats: 'errors-only',
         host: devServerHost,
         port: devServerPort
     },

http://git-wip-us.apache.org/repos/asf/ignite/blob/e04df7d1/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/ClusterListener.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/ClusterListener.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/ClusterListener.java
index 27f5317..0da4469 100644
--- a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/ClusterListener.java
+++ b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/ClusterListener.java
@@ -219,11 +219,11 @@ public class ClusterListener {
         }
 
         /**  */
-        boolean isSameCluster(TopologySnapshot snapshot) {
-            if (snapshot == null || F.isEmpty(snapshot.nids))
-                return false;
+        boolean differentCluster(TopologySnapshot old) {
+            if (old == null || F.isEmpty(old.nids))
+                return true;
 
-            return Collections.disjoint(nids, snapshot.nids);
+            return Collections.disjoint(nids, old.nids);
         }
     }
 
@@ -241,7 +241,7 @@ public class ClusterListener {
 
                         TopologySnapshot newTop = new TopologySnapshot(nodes);
 
-                        if (newTop.isSameCluster(top))
+                        if (newTop.differentCluster(top))
                             log.info("Connection successfully established to cluster with nodes: {}", newTop.nid8());
 
                         top = newTop;
@@ -276,7 +276,7 @@ public class ClusterListener {
 
                         TopologySnapshot newTop = new TopologySnapshot(nodes);
 
-                        if (top == null || top.isSameCluster(newTop)) {
+                        if (top.differentCluster(newTop)) {
                             clusterDisconnect();
 
                             log.info("Connection successfully established to cluster with nodes: {}", newTop.nid8());


[15/50] [abbrv] ignite git commit: IGNITE-5326, IGNITE-5328: Added CREATE TABLE params for backups number and atomicity mode. This closes #2054.

Posted by sb...@apache.org.
IGNITE-5326, IGNITE-5328: Added CREATE TABLE params for backups number and atomicity mode. This closes #2054.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/bfb27815
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/bfb27815
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/bfb27815

Branch: refs/heads/ignite-5075
Commit: bfb278154b27cc968ad816eb7fadbe61f2a228ab
Parents: a93af29
Author: Alexander Paschenko <al...@gmail.com>
Authored: Fri Jun 2 15:26:07 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 15:26:07 2017 +0300

----------------------------------------------------------------------
 .../processors/query/GridQueryProcessor.java    | 25 ++++--
 .../query/h2/ddl/DdlStatementsProcessor.java    |  7 +-
 .../query/h2/sql/GridSqlCreateTable.java        | 48 ++++++++--
 .../query/h2/sql/GridSqlQueryParser.java        | 94 ++++++++++++++++----
 .../cache/index/H2DynamicTableSelfTest.java     | 76 ++++++++++++++--
 .../query/h2/sql/GridQueryParsingTest.java      | 24 ++---
 6 files changed, 219 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/bfb27815/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index ea8f890..1c1fa34 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -21,6 +21,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteDataStreamer;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.binary.Binarylizable;
+import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.QueryIndex;
@@ -1277,24 +1278,34 @@ public class GridQueryProcessor extends GridProcessorAdapter {
      *
      * @param schemaName Schema name to create table in.
      * @param entity Entity to create table from.
-     * @param templateCacheName Cache name to take settings from.
+     * @param templateName Template name.
+     * @param atomicityMode Atomicity mode.
+     * @param backups Backups.
      * @param ifNotExists Quietly ignore this command if table already exists.
      * @throws IgniteCheckedException If failed.
      */
     @SuppressWarnings("unchecked")
-    public void dynamicTableCreate(String schemaName, QueryEntity entity, String templateCacheName, boolean ifNotExists)
-        throws IgniteCheckedException {
-        CacheConfiguration<?, ?> templateCfg = ctx.cache().getConfigFromTemplate(templateCacheName);
+    public void dynamicTableCreate(String schemaName, QueryEntity entity, String templateName,
+        @Nullable CacheAtomicityMode atomicityMode, int backups, boolean ifNotExists) throws IgniteCheckedException {
+        assert !F.isEmpty(templateName);
+        assert backups >= 0;
+
+        CacheConfiguration<?, ?> templateCfg = ctx.cache().getConfigFromTemplate(templateName);
 
         if (templateCfg == null)
-            throw new SchemaOperationException(SchemaOperationException.CODE_CACHE_NOT_FOUND, templateCacheName);
+            throw new SchemaOperationException(SchemaOperationException.CODE_CACHE_NOT_FOUND, templateName);
 
         if (!F.isEmpty(templateCfg.getQueryEntities()))
-            throw new SchemaOperationException("Template cache already contains query entities which it should not " +
-                "[cacheName=" + templateCacheName + ']');
+            throw new SchemaOperationException("Template cannot contain query entities [template=" +
+                templateName + ']');
 
         CacheConfiguration<?, ?> newCfg = new CacheConfiguration<>(templateCfg);
 
+        if (atomicityMode != null)
+            newCfg.setAtomicityMode(atomicityMode);
+
+        newCfg.setBackups(backups);
+
         newCfg.setName(entity.getTableName());
         newCfg.setQueryEntities(Collections.singleton(entity));
         newCfg.setSqlSchema(schemaName);

http://git-wip-us.apache.org/repos/asf/ignite/blob/bfb27815/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
index d278e37..c9e3295 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
@@ -161,9 +161,10 @@ public class DdlStatementsProcessor {
                         throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_EXISTS,
                             cmd.tableName());
                 }
-                else
-                    ctx.query().dynamicTableCreate(cmd.schemaName(), toQueryEntity(cmd), cmd.templateCacheName(),
-                        cmd.ifNotExists());
+                else {
+                    ctx.query().dynamicTableCreate(cmd.schemaName(), toQueryEntity(cmd), cmd.templateName(),
+                        cmd.atomicityMode(), cmd.backups(), cmd.ifNotExists());
+                }
             }
             else if (stmt0 instanceof GridSqlDropTable) {
                 GridSqlDropTable cmd = (GridSqlDropTable)stmt0;

http://git-wip-us.apache.org/repos/asf/ignite/blob/bfb27815/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
index 52c9cc9..50348fe 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal.processors.query.h2.sql;
 
+import org.apache.ignite.cache.CacheAtomicityMode;
+
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -34,7 +36,13 @@ public class GridSqlCreateTable extends GridSqlStatement {
     private String tblName;
 
     /** Cache name upon which new cache configuration for this table must be based. */
-    private String tplCacheName;
+    private String templateName;
+
+    /** Atomicity mode for new cache. */
+    private CacheAtomicityMode atomicityMode;
+
+    /** Backups number for new cache. */
+    private int backups;
 
     /** Quietly ignore this command if table already exists. */
     private boolean ifNotExists;
@@ -51,15 +59,43 @@ public class GridSqlCreateTable extends GridSqlStatement {
     /**
      * @return Cache name upon which new cache configuration for this table must be based.
      */
-    public String templateCacheName() {
-        return tplCacheName;
+    public String templateName() {
+        return templateName;
+    }
+
+    /**
+     * @param templateName Cache name upon which new cache configuration for this table must be based.
+     */
+    public void templateName(String templateName) {
+        this.templateName = templateName;
+    }
+
+    /**
+     * @return Atomicity mode for new cache.
+     */
+    public CacheAtomicityMode atomicityMode() {
+        return atomicityMode;
+    }
+
+    /**
+     * @param atomicityMode Atomicity mode for new cache.
+     */
+    public void atomicityMode(CacheAtomicityMode atomicityMode) {
+        this.atomicityMode = atomicityMode;
+    }
+
+    /**
+     * @return Backups number for new cache.
+     */
+    public int backups() {
+        return backups;
     }
 
     /**
-     * @param tplCacheName Cache name upon which new cache configuration for this table must be based.
+     * @param backups Backups number for new cache.
      */
-    public void templateCacheName(String tplCacheName) {
-        this.tplCacheName = tplCacheName;
+    public void backups(int backups) {
+        this.backups = backups;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/bfb27815/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
index f310e0f..573384a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -29,6 +29,8 @@ import java.util.List;
 import java.util.Map;
 import javax.cache.CacheException;
 import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.cache.QueryIndexType;
 import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
@@ -395,11 +397,17 @@ public class GridSqlQueryParser {
     private static final String PARAM_NAME_VALUE_SEPARATOR = "=";
 
     /** */
-    private static final String PARAM_CACHE_TEMPLATE = "cacheTemplate";
+    private static final String PARAM_TEMPLATE = "TEMPLATE";
+
+    /** */
+    private static final String PARAM_BACKUPS = "BACKUPS";
+
+    /** */
+    private static final String PARAM_ATOMICITY = "ATOMICITY";
 
     /** Names of the params that need to be present in WITH clause of CREATE TABLE. */
     private static final String[] MANDATORY_CREATE_TABLE_PARAMS = {
-        PARAM_CACHE_TEMPLATE
+        PARAM_TEMPLATE
     };
 
     /** */
@@ -944,7 +952,11 @@ public class GridSqlQueryParser {
 
         res.ifNotExists(CREATE_TABLE_IF_NOT_EXISTS.get(createTbl));
 
-        List<String> extraParams = data.tableEngineParams;
+        List<String> extraParams = data.tableEngineParams != null ? new ArrayList<String>() : null;
+
+        if (data.tableEngineParams != null)
+            for (String s : data.tableEngineParams)
+                extraParams.addAll(F.asList(s.split(",")));
 
         res.params(extraParams);
 
@@ -955,24 +967,26 @@ public class GridSqlQueryParser {
                 String[] parts = p.split(PARAM_NAME_VALUE_SEPARATOR);
 
                 if (parts.length > 2)
-                    throw new IgniteSQLException("Invalid param syntax: key[=value] expected [paramStr=" + p + ']',
+                    throw new IgniteSQLException("Invalid parameter (key[=value] expected): " + p,
                         IgniteQueryErrorCode.PARSING);
 
-                String name = parts[0];
+                String name = parts[0].trim().toUpperCase();
 
-                String val = parts.length > 1 ? parts[1] : null;
+                String val = parts.length > 1 ? parts[1].trim() : null;
 
                 if (F.isEmpty(name))
-                    throw new IgniteSQLException("Invalid param syntax: no name given [paramStr=" + p + ']',
+                    throw new IgniteSQLException("Invalid parameter (key[=value] expected): " + p,
                         IgniteQueryErrorCode.PARSING);
 
-                params.put(name, val);
+                if (params.put(name, val) != null)
+                    throw new IgniteSQLException("Duplicate parameter: " + p, IgniteQueryErrorCode.PARSING);
             }
         }
 
-        for (String mandParamName : MANDATORY_CREATE_TABLE_PARAMS) {
-            if (!params.containsKey(mandParamName))
-                throw new IgniteSQLException("Mandatory param is missing [paramName=" + mandParamName + ']');
+        for (String paramName : MANDATORY_CREATE_TABLE_PARAMS) {
+            if (!params.containsKey(paramName))
+                throw new IgniteSQLException("Mandatory parameter is missing: " + paramName,
+                    IgniteQueryErrorCode.PARSING);
         }
 
         for (Map.Entry<String, String> e : params.entrySet())
@@ -1010,16 +1024,45 @@ public class GridSqlQueryParser {
         assert !F.isEmpty(name);
 
         switch (name) {
-            case PARAM_CACHE_TEMPLATE:
-                ensureParamValueNotEmpty(PARAM_CACHE_TEMPLATE, val);
+            case PARAM_TEMPLATE:
+                ensureNotEmpty(name, val);
+
+                res.templateName(val);
 
-                res.templateCacheName(val);
+                break;
+
+            case PARAM_BACKUPS:
+                ensureNotEmpty(name, val);
+
+                int backups = parseIntParam(PARAM_BACKUPS, val);
+
+                if (backups < 0)
+                    throw new IgniteSQLException("\"" + PARAM_BACKUPS + "\" cannot be negative: " + backups,
+                        IgniteQueryErrorCode.PARSING);
+
+                res.backups(backups);
+
+                break;
+
+            case PARAM_ATOMICITY:
+                ensureNotEmpty(name, val);
+
+                CacheAtomicityMode mode;
+
+                if (CacheAtomicityMode.TRANSACTIONAL.name().equalsIgnoreCase(val))
+                    mode = CacheAtomicityMode.TRANSACTIONAL;
+                else if (CacheAtomicityMode.ATOMIC.name().equalsIgnoreCase(val))
+                    mode = CacheAtomicityMode.ATOMIC;
+                else
+                    throw new IgniteSQLException("Invalid value of \"" + PARAM_ATOMICITY + "\" parameter " +
+                        "(should be either TRANSACTIONAL or ATOMIC): " + val, IgniteQueryErrorCode.PARSING);
+
+                res.atomicityMode(mode);
 
                 break;
 
             default:
-                throw new IgniteSQLException("Unknown CREATE TABLE param [paramName=" + name + ']',
-                    IgniteQueryErrorCode.PARSING);
+                throw new IgniteSQLException("Unsupported parameter: " + name, IgniteQueryErrorCode.PARSING);
         }
     }
 
@@ -1028,10 +1071,25 @@ public class GridSqlQueryParser {
      * @param name Param name.
      * @param val Param value to check.
      */
-    private static void ensureParamValueNotEmpty(String name, String val) {
+    private static void ensureNotEmpty(String name, String val) {
         if (F.isEmpty(val))
-            throw new IgniteSQLException("No value has been given for a CREATE TABLE param [paramName=" + name + ']',
+            throw new IgniteSQLException("Parameter value cannot be empty: " + name, IgniteQueryErrorCode.PARSING);
+    }
+
+    /**
+     * Parse given value as integer, or throw an {@link IgniteSQLException} if it's not of matching format.
+     * @param name param name.
+     * @param val param value.
+     * @return parsed int value.
+     */
+    private static int parseIntParam(String name, String val) {
+        try {
+            return Integer.parseInt(val);
+        }
+        catch (NumberFormatException e) {
+            throw new IgniteSQLException("Parameter value must be an integer [name=" + name + ", value=" + val + ']',
                 IgniteQueryErrorCode.PARSING);
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/bfb27815/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
index 6f0dec6..b43d3f2 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
@@ -99,7 +99,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     public void testCreateTable() throws Exception {
         executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\"");
+            "\"template=cache,backups=10\",\"atomicity=atomic\"");
 
         for (int i = 0; i < 4; i++) {
             IgniteEx node = grid(i);
@@ -110,6 +110,10 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
 
             assertNotNull(cacheDesc);
 
+            assertEquals(10, cacheDesc.cacheConfiguration().getBackups());
+
+            assertEquals(CacheAtomicityMode.ATOMIC, cacheDesc.cacheConfiguration().getAtomicityMode());
+
             assertTrue(cacheDesc.sql());
 
             QueryTypeDescriptorImpl desc = typeExisting(node, "Person", "Person");
@@ -144,6 +148,35 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     }
 
     /**
+     * Test that attempting to specify negative number of backups yields exception.
+     */
+    public void testNegativeBackups() {
+        assertCreateTableWithParamsThrows("bAckUPs = -5  ", "\"BACKUPS\" cannot be negative: -5");
+    }
+
+    /**
+     * Test that attempting to omit mandatory value of BACKUPS parameter yields an error.
+     */
+    public void testEmptyBackups() {
+        assertCreateTableWithParamsThrows(" bAckUPs =  ", "Parameter value cannot be empty: BACKUPS");
+    }
+
+    /**
+     * Test that attempting to omit mandatory value of ATOMICITY parameter yields an error.
+     */
+    public void testEmptyAtomicity() {
+        assertCreateTableWithParamsThrows("AtomicitY=  ", "Parameter value cannot be empty: ATOMICITY");
+    }
+
+    /**
+     * Test that attempting to omit mandatory value of ATOMICITY parameter yields an error.
+     */
+    public void testInvalidAtomicity() {
+        assertCreateTableWithParamsThrows("atomicity=InvalidValue",
+            "Invalid value of \"ATOMICITY\" parameter (should be either TRANSACTIONAL or ATOMIC): InvalidValue");
+    }
+
+    /**
      * Test that attempting to {@code CREATE TABLE} that already exists does not yield an error if the statement
      *     contains {@code IF NOT EXISTS} clause.
      * @throws Exception if failed.
@@ -151,11 +184,11 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     public void testCreateTableIfNotExists() throws Exception {
         executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\"");
+            "\"template=cache\"");
 
         executeDdl("CREATE TABLE IF NOT EXISTS \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\"");
+            "\"template=cache\"");
     }
 
     /**
@@ -166,13 +199,13 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     public void testCreateExistingTable() throws Exception {
         executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\"");
+            "\"template=cache\"");
 
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar" +
                     ", \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-                    "\"cacheTemplate=cache\"");
+                    "\"template=cache\"");
 
                 return null;
             }
@@ -186,7 +219,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     public void testDropTable() throws Exception {
         executeDdl("CREATE TABLE IF NOT EXISTS \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\"");
+            "\"template=cache\"");
 
         executeDdl("DROP TABLE \"Person\"");
 
@@ -250,7 +283,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     public void testDestroyDynamicSqlCache() throws Exception {
         executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\"");
+            "\"template=cache\"");
 
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
@@ -270,7 +303,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
     public void testSqlFlagCompatibilityCheck() throws Exception {
         executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar, \"name\" varchar, \"surname\" varchar, " +
-            "\"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH \"cacheTemplate=cache\"");
+            "\"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH \"template=cache\"");
 
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
@@ -282,6 +315,31 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     }
 
     /**
+     * Execute {@code CREATE TABLE} w/given params.
+     * @param params Engine parameters.
+     */
+    private void createTableWithParams(final String params) {
+        cache().query(new SqlFieldsQuery("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar" +
+            ", \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
+            "\"template=cache," + params + '"'));
+    }
+
+    /**
+     * Execute {@code CREATE TABLE} w/given params expecting a particular error.
+     * @param params Engine parameters.
+     * @param expErrMsg Expected error message.
+     */
+    private void assertCreateTableWithParamsThrows(final String params, String expErrMsg) {
+        GridTestUtils.assertThrows(null, new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                createTableWithParams(params);
+
+                return null;
+            }
+        }, IgniteSQLException.class, expErrMsg);
+    }
+
+    /**
      * Test that {@code CREATE TABLE} on non-public schema causes an exception.
      *
      * @throws Exception if failed.
@@ -292,7 +350,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
             @Override public Object call() throws Exception {
                 executeDdl("CREATE TABLE \"cache_idx\".\"Person\" (\"id\" int, \"city\" varchar," +
                     " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-                    "\"cacheTemplate=cache\"");
+                    "\"template=cache\"");
 
                 return null;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/bfb27815/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
index b66a343..8f9db2e 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
@@ -579,7 +579,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
                 c("surname", Value.STRING), c("age", Value.INT)),
             "CREATE TABLE IF NOT EXISTS sch1.\"Person\" (\"id\" integer, \"city\" varchar," +
                 " \"name\" varchar, \"surname\" varchar, \"age\" integer, PRIMARY KEY (\"id\", \"city\")) WITH " +
-                "\"cacheTemplate=cache\"");
+                "\"template=cache\"");
 
         assertCreateTableEquals(
             buildCreateTable("sch1", "Person", "cache", F.asList("id"),
@@ -587,7 +587,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
                 c("surname", Value.STRING), c("age", Value.INT)),
             "CREATE TABLE sch1.\"Person\" (\"id\" integer PRIMARY KEY, \"city\" varchar," +
                 " \"name\" varchar, \"surname\" varchar, \"age\" integer) WITH " +
-                "\"cacheTemplate=cache\"");
+                "\"template=cache\"");
 
         assertParseThrows("create table Person (id int)",
             IgniteSQLException.class, "No PRIMARY KEY defined for CREATE TABLE");
@@ -599,27 +599,27 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
             IgniteSQLException.class, "No cache value related columns found");
 
         assertParseThrows("create table Person (id int primary key, age int null)",
-            IgniteSQLException.class, "Mandatory param is missing [paramName=cacheTemplate]");
+            IgniteSQLException.class, "Mandatory parameter is missing: TEMPLATE");
 
-        assertParseThrows("create table Person (id int primary key, age int not null) WITH \"cacheTemplate=cache\"",
+        assertParseThrows("create table Person (id int primary key, age int not null) WITH \"template=cache\"",
             IgniteSQLException.class, "Non nullable columns are forbidden");
 
-        assertParseThrows("create table Person (id int primary key, age int unique) WITH \"cacheTemplate=cache\"",
+        assertParseThrows("create table Person (id int primary key, age int unique) WITH \"template=cache\"",
             IgniteSQLException.class, "Too many constraints - only PRIMARY KEY is supported for CREATE TABLE");
 
-        assertParseThrows("create table Person (id int auto_increment primary key, age int) WITH \"cacheTemplate=cache\"",
+        assertParseThrows("create table Person (id int auto_increment primary key, age int) WITH \"template=cache\"",
             IgniteSQLException.class, "AUTO_INCREMENT columns are not supported");
 
-        assertParseThrows("create table Person (id int primary key check id > 0, age int) WITH \"cacheTemplate=cache\"",
+        assertParseThrows("create table Person (id int primary key check id > 0, age int) WITH \"template=cache\"",
             IgniteSQLException.class, "Column CHECK constraints are not supported [colName=ID]");
 
-        assertParseThrows("create table Person (id int as age * 2 primary key, age int) WITH \"cacheTemplate=cache\"",
+        assertParseThrows("create table Person (id int as age * 2 primary key, age int) WITH \"template=cache\"",
             IgniteSQLException.class, "Computed columns are not supported [colName=ID]");
 
-        assertParseThrows("create table Person (id int primary key, age int default 5) WITH \"cacheTemplate=cache\"",
+        assertParseThrows("create table Person (id int primary key, age int default 5) WITH \"template=cache\"",
             IgniteSQLException.class, "DEFAULT expressions are not supported [colName=AGE]");
 
-        assertParseThrows("create table Int (_key int primary key, _val int) WITH \"cacheTemplate=cache\"",
+        assertParseThrows("create table Int (_key int primary key, _val int) WITH \"template=cache\"",
             IgniteSQLException.class, "Direct specification of _KEY and _VAL columns is forbidden");
     }
 
@@ -706,7 +706,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
     private static void assertCreateTableEquals(GridSqlCreateTable exp, GridSqlCreateTable actual) {
         assertEqualsIgnoreCase(exp.schemaName(), actual.schemaName());
         assertEqualsIgnoreCase(exp.tableName(), actual.tableName());
-        assertEquals(exp.templateCacheName(), actual.templateCacheName());
+        assertEquals(exp.templateName(), actual.templateName());
         assertEquals(exp.primaryKeyColumns(), actual.primaryKeyColumns());
         assertEquals(new ArrayList<>(exp.columns().keySet()), new ArrayList<>(actual.columns().keySet()));
 
@@ -733,7 +733,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
 
         res.tableName(tbl);
 
-        res.templateCacheName(tplCacheName);
+        res.templateName(tplCacheName);
 
         res.primaryKeyColumns(new LinkedHashSet<>(pkColNames));
 


[12/50] [abbrv] ignite git commit: IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.

Posted by sb...@apache.org.
IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e92707b6
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e92707b6
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e92707b6

Branch: refs/heads/ignite-5075
Commit: e92707b65ca9044070a200317079a600c8d92ded
Parents: fd838d5
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Fri Jun 2 14:33:33 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 14:33:34 2017 +0300

----------------------------------------------------------------------
 .../jdbc/suite/IgniteJdbcDriverTestSuite.java   |   17 +-
 .../jdbc/thin/JdbcConnectionSelfTest.java       |  195 --
 .../jdbc/thin/JdbcThinAbstractSelfTest.java     |   41 +
 .../jdbc/thin/JdbcThinComplexQuerySelfTest.java |  330 ++++
 .../jdbc/thin/JdbcThinConnectionSelfTest.java   |  214 +++
 .../jdbc/thin/JdbcThinEmptyCacheSelfTest.java   |  146 ++
 .../jdbc/thin/JdbcThinMetadataSelfTest.java     |  357 ++++
 .../jdbc/thin/JdbcThinNoDefaultSchemaTest.java  |  161 ++
 .../thin/JdbcThinPreparedStatementSelfTest.java |  771 ++++++++
 .../jdbc/thin/JdbcThinResultSetSelfTest.java    |  762 ++++++++
 .../jdbc/thin/JdbcThinStatementSelfTest.java    |  343 ++++
 .../org/apache/ignite/IgniteJdbcDriver.java     |    3 +
 .../org/apache/ignite/IgniteJdbcThinDriver.java |    7 +-
 .../internal/jdbc/thin/JdbcConnection.java      |  529 ------
 .../ignite/internal/jdbc/thin/JdbcTcpIo.java    |  207 ---
 .../internal/jdbc/thin/JdbcThinConnection.java  |  545 ++++++
 .../jdbc/thin/JdbcThinPreparedStatement.java    |  461 +++++
 .../internal/jdbc/thin/JdbcThinResultSet.java   | 1698 ++++++++++++++++++
 .../jdbc/thin/JdbcThinResultSetMetadata.java    |  161 ++
 .../internal/jdbc/thin/JdbcThinStatement.java   |  475 +++++
 .../internal/jdbc/thin/JdbcThinTcpIo.java       |  309 ++++
 .../internal/jdbc/thin/JdbcThinUtils.java       |  152 ++
 .../odbc/OdbcQueryGetColumnsMetaRequest.java    |   74 -
 .../odbc/OdbcQueryGetColumnsMetaResult.java     |   42 -
 .../odbc/OdbcQueryGetParamsMetaRequest.java     |   60 -
 .../odbc/OdbcQueryGetParamsMetaResult.java      |   40 -
 .../odbc/OdbcQueryGetTablesMetaRequest.java     |   85 -
 .../odbc/OdbcQueryGetTablesMetaResult.java      |   42 -
 .../internal/processors/odbc/OdbcTableMeta.java |   88 -
 .../odbc/SqlListenerAbstractMessageParser.java  |  265 ---
 .../odbc/SqlListenerAbstractObjectReader.java   |  137 --
 .../odbc/SqlListenerAbstractObjectWriter.java   |  111 --
 .../processors/odbc/SqlListenerColumnMeta.java  |  110 --
 .../processors/odbc/SqlListenerNioListener.java |   27 +-
 .../odbc/SqlListenerQueryCloseRequest.java      |   49 -
 .../odbc/SqlListenerQueryCloseResult.java       |   40 -
 .../odbc/SqlListenerQueryExecuteRequest.java    |   78 -
 .../odbc/SqlListenerQueryExecuteResult.java     |   54 -
 .../odbc/SqlListenerQueryFetchRequest.java      |   61 -
 .../odbc/SqlListenerQueryFetchResult.java       |   66 -
 .../processors/odbc/SqlListenerRequest.java     |   37 +-
 .../odbc/SqlListenerRequestHandler.java         |    8 +
 .../odbc/SqlListenerRequestHandlerImpl.java     |  494 -----
 .../processors/odbc/SqlListenerResponse.java    |   42 +-
 .../processors/odbc/SqlListenerUtils.java       |  250 +++
 .../processors/odbc/jdbc/JdbcColumnMeta.java    |  129 ++
 .../processors/odbc/jdbc/JdbcMessageParser.java |   53 +-
 .../processors/odbc/jdbc/JdbcObjectReader.java  |   33 -
 .../processors/odbc/jdbc/JdbcObjectWriter.java  |   33 -
 .../odbc/jdbc/JdbcQueryCloseRequest.java        |   72 +
 .../processors/odbc/jdbc/JdbcQueryCursor.java   |  132 ++
 .../odbc/jdbc/JdbcQueryExecuteRequest.java      |  147 ++
 .../odbc/jdbc/JdbcQueryExecuteResult.java       |  150 ++
 .../odbc/jdbc/JdbcQueryFetchRequest.java        |   87 +
 .../odbc/jdbc/JdbcQueryFetchResult.java         |   84 +
 .../odbc/jdbc/JdbcQueryMetadataRequest.java     |   73 +
 .../odbc/jdbc/JdbcQueryMetadataResult.java      |   93 +
 .../odbc/jdbc/JdbcRawBinarylizable.java         |   44 +
 .../processors/odbc/jdbc/JdbcRequest.java       |  108 ++
 .../odbc/jdbc/JdbcRequestHandler.java           |  285 +++
 .../processors/odbc/jdbc/JdbcResponse.java      |  104 ++
 .../processors/odbc/jdbc/JdbcResult.java        |   91 +
 .../processors/odbc/jdbc/JdbcUtils.java         |   73 +
 .../processors/odbc/odbc/OdbcColumnMeta.java    |  111 ++
 .../processors/odbc/odbc/OdbcMessageParser.java |  213 ++-
 .../processors/odbc/odbc/OdbcObjectReader.java  |   33 -
 .../processors/odbc/odbc/OdbcObjectWriter.java  |   32 -
 .../odbc/odbc/OdbcQueryCloseRequest.java        |   49 +
 .../odbc/odbc/OdbcQueryCloseResult.java         |   40 +
 .../odbc/odbc/OdbcQueryExecuteRequest.java      |   78 +
 .../odbc/odbc/OdbcQueryExecuteResult.java       |   54 +
 .../odbc/odbc/OdbcQueryFetchRequest.java        |   61 +
 .../odbc/odbc/OdbcQueryFetchResult.java         |   66 +
 .../odbc/OdbcQueryGetColumnsMetaRequest.java    |   74 +
 .../odbc/OdbcQueryGetColumnsMetaResult.java     |   42 +
 .../odbc/OdbcQueryGetParamsMetaRequest.java     |   60 +
 .../odbc/odbc/OdbcQueryGetParamsMetaResult.java |   40 +
 .../odbc/OdbcQueryGetTablesMetaRequest.java     |   85 +
 .../odbc/odbc/OdbcQueryGetTablesMetaResult.java |   42 +
 .../processors/odbc/odbc/OdbcRequest.java       |   63 +
 .../odbc/odbc/OdbcRequestHandler.java           |  505 ++++++
 .../processors/odbc/odbc/OdbcResponse.java      |   69 +
 .../processors/odbc/odbc/OdbcTableMeta.java     |   89 +
 83 files changed, 10686 insertions(+), 3055 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
index abfdf90..e0e6f31 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
@@ -31,6 +31,14 @@ import org.apache.ignite.jdbc.JdbcPojoQuerySelfTest;
 import org.apache.ignite.jdbc.JdbcPreparedStatementSelfTest;
 import org.apache.ignite.jdbc.JdbcResultSetSelfTest;
 import org.apache.ignite.jdbc.JdbcStatementSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinComplexQuerySelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinConnectionSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinEmptyCacheSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinMetadataSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinNoDefaultSchemaTest;
+import org.apache.ignite.jdbc.thin.JdbcThinPreparedStatementSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinResultSetSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinStatementSelfTest;
 
 /**
  * JDBC driver test suite.
@@ -85,7 +93,14 @@ public class IgniteJdbcDriverTestSuite extends TestSuite {
         suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcDynamicIndexTransactionalReplicatedSelfTest.class));
 
         // New thin JDBC
-        suite.addTest(new TestSuite(org.apache.ignite.jdbc.thin.JdbcConnectionSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinConnectionSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinStatementSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinResultSetSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinComplexQuerySelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinPreparedStatementSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinNoDefaultSchemaTest.class));
+        suite.addTest(new TestSuite(JdbcThinEmptyCacheSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinMetadataSelfTest.class));
 
         return suite;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcConnectionSelfTest.java
deleted file mode 100644
index d7e2bef..0000000
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcConnectionSelfTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.jdbc.thin;
-
-import java.sql.Connection;
-import java.sql.Driver;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.concurrent.Callable;
-import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.OdbcConfiguration;
-import org.apache.ignite.internal.binary.BinaryMarshaller;
-import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
-import org.apache.ignite.testframework.GridTestUtils;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Connection test.
- */
-public class JdbcConnectionSelfTest extends GridCommonAbstractTest {
-    /** IP finder. */
-    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
-
-    /** URL prefix. */
-    private static final String URL_PREFIX = "jdbc:ignite:thin://";
-
-    /** Host. */
-    private static final String HOST = "127.0.0.1";
-
-    /** {@inheritDoc} */
-    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
-        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
-
-        cfg.setCacheConfiguration(cacheConfiguration(DEFAULT_CACHE_NAME));
-
-        TcpDiscoverySpi disco = new TcpDiscoverySpi();
-
-        disco.setIpFinder(IP_FINDER);
-
-        cfg.setDiscoverySpi(disco);
-
-        cfg.setMarshaller(new BinaryMarshaller());
-
-        cfg.setOdbcConfiguration(new OdbcConfiguration());
-
-        return cfg;
-    }
-
-    /**
-     * @param name Cache name.
-     * @return Cache configuration.
-     * @throws Exception In case of error.
-     */
-    private CacheConfiguration cacheConfiguration(@NotNull String name) throws Exception {
-        CacheConfiguration cfg = defaultCacheConfiguration();
-
-        cfg.setName(name);
-
-        return cfg;
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void beforeTestsStarted() throws Exception {
-        try {
-            Driver drv = DriverManager.getDriver("jdbc:ignite://");
-
-            if (drv != null)
-                DriverManager.deregisterDriver(drv);
-        } catch (SQLException ignored) {
-            // No-op.
-        }
-
-        startGridsMultiThreaded(2);
-
-        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void afterTestsStopped() throws Exception {
-        stopAllGrids();
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    public void testDefaults() throws Exception {
-        String url = URL_PREFIX + HOST;
-
-        assert DriverManager.getConnection(url) != null;
-        assert DriverManager.getConnection(url + "/") != null;
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    public void testInvalidUrls() throws Exception {
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:80");
-
-                return null;
-            }
-        }, SQLException.class, "Failed to connect to Ignite cluster [host=127.0.0.1, port=80]");
-
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection("q");
-
-                return null;
-            }
-        }, SQLException.class, "URL is invalid");
-
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:-1");
-
-                return null;
-            }
-        }, SQLException.class, "Invalid port:");
-
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:0");
-
-                return null;
-            }
-        }, SQLException.class, "Invalid port:");
-
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:100000");
-
-                return null;
-            }
-        }, SQLException.class, "Invalid port:");
-
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "     :10000");
-
-                return null;
-            }
-        }, SQLException.class, "Host name is empty");
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    public void testClose() throws Exception {
-        String url = URL_PREFIX + HOST;
-
-        final Connection conn = DriverManager.getConnection(url);
-
-        assert conn != null;
-        assert !conn.isClosed();
-
-        conn.close();
-
-        assert conn.isClosed();
-
-        assert !conn.isValid(2): "Connection must be closed";
-
-        GridTestUtils.assertThrows(
-            log,
-            new Callable<Object>() {
-                @Override public Object call() throws Exception {
-                    conn.isValid(-2);
-
-                    return null;
-                }
-            },
-            SQLException.class,
-            "Invalid timeout"
-        );
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
new file mode 100644
index 0000000..bbefbd4
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.jdbc.thin;
+
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * Connection test.
+ */
+public class JdbcThinAbstractSelfTest extends GridCommonAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setOdbcConfiguration(new OdbcConfiguration());
+
+        return cfg;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexQuerySelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexQuerySelfTest.java
new file mode 100644
index 0000000..1714ab1
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexQuerySelfTest.java
@@ -0,0 +1,330 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.Serializable;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.affinity.AffinityKey;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Tests for complex queries (joins, etc.).
+ */
+public class JdbcThinComplexQuerySelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** Statement. */
+    private Statement stmt;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setCacheConfiguration(cacheConfiguration());
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        return cfg;
+    }
+
+    /**
+     * @return Cache configuration.
+     */
+    protected CacheConfiguration cacheConfiguration() {
+        CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+        cache.setAtomicityMode(TRANSACTIONAL);
+
+        return cache;
+    }
+
+
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGrids(3);
+
+        IgniteCache<String, Organization> orgCache = jcache(grid(0), cacheConfiguration(), "org",
+            String.class, Organization.class);
+
+        assert orgCache != null;
+
+        orgCache.put("o1", new Organization(1, "A"));
+        orgCache.put("o2", new Organization(2, "B"));
+
+        IgniteCache<AffinityKey, Person> personCache = jcache(grid(0), cacheConfiguration(), "pers",
+            AffinityKey.class, Person.class);
+
+        assert personCache != null;
+
+        personCache.put(new AffinityKey<>("p1", "o1"), new Person(1, "John White", 25, 1));
+        personCache.put(new AffinityKey<>("p2", "o1"), new Person(2, "Joe Black", 35, 1));
+        personCache.put(new AffinityKey<>("p3", "o2"), new Person(3, "Mike Green", 40, 2));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        Connection conn = DriverManager.getConnection(URL);
+
+        conn.setSchema("pers");
+
+        stmt = conn.createStatement();
+
+        assert stmt != null;
+        assert !stmt.isClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (stmt != null) {
+            stmt.getConnection().close();
+
+            stmt.close();
+
+            assert stmt.isClosed();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testJoin() throws Exception {
+        ResultSet rs = stmt.executeQuery(
+            "select p.id, p.name, o.name as orgName from \"pers\".Person p, \"org\".Organization o where p.orgId = o.id");
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            int id = rs.getInt("id");
+
+            if (id == 1) {
+                assert "John White".equals(rs.getString("name"));
+                assert "A".equals(rs.getString("orgName"));
+            }
+            else if (id == 2) {
+                assert "Joe Black".equals(rs.getString("name"));
+                assert "A".equals(rs.getString("orgName"));
+            }
+            else if (id == 3) {
+                assert "Mike Green".equals(rs.getString("name"));
+                assert "B".equals(rs.getString("orgName"));
+            }
+            else
+                assert false : "Wrong ID: " + id;
+
+            cnt++;
+        }
+
+        assert cnt == 3;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testJoinWithoutAlias() throws Exception {
+        ResultSet rs = stmt.executeQuery(
+            "select p.id, p.name, o.name from \"pers\".Person p, \"org\".Organization o where p.orgId = o.id");
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            int id = rs.getInt(1);
+
+            if (id == 1) {
+                assert "John White".equals(rs.getString("name"));
+                assert "John White".equals(rs.getString(2));
+                assert "A".equals(rs.getString(3));
+            }
+            else if (id == 2) {
+                assert "Joe Black".equals(rs.getString("name"));
+                assert "Joe Black".equals(rs.getString(2));
+                assert "A".equals(rs.getString(3));
+            }
+            else if (id == 3) {
+                assert "Mike Green".equals(rs.getString("name"));
+                assert "Mike Green".equals(rs.getString(2));
+                assert "B".equals(rs.getString(3));
+            }
+            else
+                assert false : "Wrong ID: " + id;
+
+            cnt++;
+        }
+
+        assert cnt == 3;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testIn() throws Exception {
+        ResultSet rs = stmt.executeQuery("select name from \"pers\".Person where age in (25, 35)");
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            assert "John White".equals(rs.getString("name")) ||
+                "Joe Black".equals(rs.getString("name"));
+
+            cnt++;
+        }
+
+        assert cnt == 2;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBetween() throws Exception {
+        ResultSet rs = stmt.executeQuery("select name from \"pers\".Person where age between 24 and 36");
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            assert "John White".equals(rs.getString("name")) ||
+                "Joe Black".equals(rs.getString("name"));
+
+            cnt++;
+        }
+
+        assert cnt == 2;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCalculatedValue() throws Exception {
+        ResultSet rs = stmt.executeQuery("select age * 2 from \"pers\".Person");
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            assert rs.getInt(1) == 50 ||
+                rs.getInt(1) == 70 ||
+                rs.getInt(1) == 80;
+
+            cnt++;
+        }
+
+        assert cnt == 3;
+    }
+
+    /**
+     * Person.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Person implements Serializable {
+        /** ID. */
+        @QuerySqlField
+        private final int id;
+
+        /** Name. */
+        @QuerySqlField(index = false)
+        private final String name;
+
+        /** Age. */
+        @QuerySqlField
+        private final int age;
+
+        /** Organization ID. */
+        @QuerySqlField
+        private final int orgId;
+
+        /**
+         * @param id ID.
+         * @param name Name.
+         * @param age Age.
+         * @param orgId Organization ID.
+         */
+        private Person(int id, String name, int age, int orgId) {
+            assert !F.isEmpty(name);
+            assert age > 0;
+            assert orgId > 0;
+
+            this.id = id;
+            this.name = name;
+            this.age = age;
+            this.orgId = orgId;
+        }
+    }
+
+    /**
+     * Organization.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Organization implements Serializable {
+        /** ID. */
+        @QuerySqlField
+        private final int id;
+
+        /** Name. */
+        @QuerySqlField(index = false)
+        private final String name;
+
+        /**
+         * @param id ID.
+         * @param name Name.
+         */
+        private Organization(int id, String name) {
+            this.id = id;
+            this.name = name;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
new file mode 100644
index 0000000..c3ce73a
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
@@ -0,0 +1,214 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.concurrent.Callable;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Connection test.
+ */
+public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL prefix. */
+    private static final String URL_PREFIX = "jdbc:ignite:thin://";
+
+    /** Host. */
+    private static final String HOST = "127.0.0.1";
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setCacheConfiguration(cacheConfiguration(DEFAULT_CACHE_NAME));
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        cfg.setMarshaller(new BinaryMarshaller());
+
+        return cfg;
+    }
+
+    /**
+     * @param name Cache name.
+     * @return Cache configuration.
+     * @throws Exception In case of error.
+     */
+    private CacheConfiguration cacheConfiguration(@NotNull String name) throws Exception {
+        CacheConfiguration cfg = defaultCacheConfiguration();
+
+        cfg.setName(name);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(2);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDefaults() throws Exception {
+        String url = URL_PREFIX + HOST;
+
+        assert DriverManager.getConnection(url) != null;
+        assert DriverManager.getConnection(url + "/") != null;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testFailedHandshake() throws Exception {
+        final ServerSocket srvSock = new ServerSocket(60000, 0, InetAddress.getByName("127.0.0.1"));
+
+        IgniteInternalFuture f = GridTestUtils.runAsync(new Runnable() {
+            @Override public void run() {
+                try {
+                    Socket s = srvSock.accept();
+
+                    s.close();
+                }
+                catch (IOException e) {
+                    log.error("Unexpected exception", e);
+                    fail();
+                }
+            }
+        });
+
+        try {
+            GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    DriverManager.getConnection(URL_PREFIX + "127.0.0.1:60000");
+
+                    return null;
+                }
+            }, SQLException.class, "Failed to connect to Ignite cluster [host=127.0.0.1, port=60000]");
+        }
+        finally {
+            f.get(3000);
+
+            srvSock.close();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testInvalidUrls() throws Exception {
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection("q");
+
+                return null;
+            }
+        }, SQLException.class, "No suitable driver found for q");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:-1");
+
+                return null;
+            }
+        }, SQLException.class, "Invalid port:");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:0");
+
+                return null;
+            }
+        }, SQLException.class, "Invalid port:");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:100000");
+
+                return null;
+            }
+        }, SQLException.class, "Invalid port:");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection(URL_PREFIX + "     :10000");
+
+                return null;
+            }
+        }, SQLException.class, "Host name is empty");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testClose() throws Exception {
+        String url = URL_PREFIX + HOST;
+
+        final Connection conn = DriverManager.getConnection(url);
+
+        assert conn != null;
+        assert !conn.isClosed();
+
+        conn.close();
+
+        assert conn.isClosed();
+
+        assert !conn.isValid(2): "Connection must be closed";
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    conn.isValid(-2);
+
+                    return null;
+                }
+            },
+            SQLException.class,
+            "Invalid timeout"
+        );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java
new file mode 100644
index 0000000..4775a79
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Tests for empty cache.
+ */
+public class JdbcThinEmptyCacheSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** Cache name. */
+    private static final String CACHE_NAME = "cache";
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** Statement. */
+    private Statement stmt;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        CacheConfiguration cache = defaultCacheConfiguration();
+
+        cache.setName(CACHE_NAME);
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+        cache.setIndexedTypes(
+            Byte.class, Byte.class
+        );
+
+        cfg.setCacheConfiguration(cache);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        cfg.setOdbcConfiguration(new OdbcConfiguration());
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGrid();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        Connection conn = DriverManager.getConnection(URL);
+
+        conn.setSchema(CACHE_NAME);
+
+        stmt = conn.createStatement();
+
+        assert stmt != null;
+        assert !stmt.isClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (stmt != null) {
+            stmt.getConnection().close();
+
+            stmt.close();
+
+            assert stmt.isClosed();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testSelectNumber() throws Exception {
+        ResultSet rs = stmt.executeQuery("select 1");
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            assert rs.getInt(1) == 1;
+            assert "1".equals(rs.getString(1));
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testSelectString() throws Exception {
+        ResultSet rs = stmt.executeQuery("select 'str'");
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            assertEquals("str", rs.getString(1));
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
new file mode 100644
index 0000000..2dae107
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
@@ -0,0 +1,357 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.Serializable;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.affinity.AffinityKey;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+
+import static java.sql.Types.INTEGER;
+import static java.sql.Types.OTHER;
+import static java.sql.Types.VARCHAR;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Metadata tests.
+ */
+public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        return cfg;
+    }
+
+    /**
+     * @return Cache configuration.
+     */
+    protected CacheConfiguration cacheConfiguration() {
+        CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+
+        return cache;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(3);
+
+        IgniteCache<String, Organization> orgCache = jcache(grid(0), cacheConfiguration(), "org",
+            String.class, Organization.class);
+
+        assert orgCache != null;
+
+        orgCache.put("o1", new Organization(1, "A"));
+        orgCache.put("o2", new Organization(2, "B"));
+
+        IgniteCache<AffinityKey, Person> personCache = jcache(grid(0), cacheConfiguration(), "pers",
+            AffinityKey.class, Person.class);
+
+        assert personCache != null;
+
+        personCache.put(new AffinityKey<>("p1", "o1"), new Person("John White", 25, 1));
+        personCache.put(new AffinityKey<>("p2", "o1"), new Person("Joe Black", 35, 1));
+        personCache.put(new AffinityKey<>("p3", "o2"), new Person("Mike Green", 40, 2));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testResultSetMetaData() throws Exception {
+        Connection conn = DriverManager.getConnection(URL);
+
+        conn.setSchema("pers");
+
+        Statement stmt = conn.createStatement();
+
+        ResultSet rs = stmt.executeQuery(
+            "select p.name, o.id as orgId from \"pers\".Person p, \"org\".Organization o where p.orgId = o.id");
+
+        assert rs != null;
+
+        ResultSetMetaData meta = rs.getMetaData();
+
+        assert meta != null;
+
+        assert meta.getColumnCount() == 2;
+
+        assert "Person".equalsIgnoreCase(meta.getTableName(1));
+        assert "name".equalsIgnoreCase(meta.getColumnName(1));
+        assert "name".equalsIgnoreCase(meta.getColumnLabel(1));
+        assert meta.getColumnType(1) == VARCHAR;
+        assert "VARCHAR".equals(meta.getColumnTypeName(1));
+        assert "java.lang.String".equals(meta.getColumnClassName(1));
+
+        assert "Organization".equalsIgnoreCase(meta.getTableName(2));
+        assert "orgId".equalsIgnoreCase(meta.getColumnName(2));
+        assert "orgId".equalsIgnoreCase(meta.getColumnLabel(2));
+        assert meta.getColumnType(2) == INTEGER;
+        assert "INTEGER".equals(meta.getColumnTypeName(2));
+        assert "java.lang.Integer".equals(meta.getColumnClassName(2));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetTables() throws Exception {
+        fail("https://issues.apache.org/jira/browse/IGNITE-5233");
+
+        try (Connection conn = DriverManager.getConnection(URL)) {
+            DatabaseMetaData meta = conn.getMetaData();
+
+            ResultSet rs = meta.getTables("", "pers", "%", new String[]{"TABLE"});
+            assertNotNull(rs);
+            assertTrue(rs.next());
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+            assertEquals("PERSON", rs.getString("TABLE_NAME"));
+
+            rs = meta.getTables("", "org", "%", new String[]{"TABLE"});
+            assertNotNull(rs);
+            assertTrue(rs.next());
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+            assertEquals("ORGANIZATION", rs.getString("TABLE_NAME"));
+
+            rs = meta.getTables("", "pers", "%", null);
+            assertNotNull(rs);
+            assertTrue(rs.next());
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+            assertEquals("PERSON", rs.getString("TABLE_NAME"));
+
+            rs = meta.getTables("", "org", "%", null);
+            assertNotNull(rs);
+            assertTrue(rs.next());
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+            assertEquals("ORGANIZATION", rs.getString("TABLE_NAME"));
+
+            rs = meta.getTables("", "PUBLIC", "", new String[]{"WRONG"});
+            assertFalse(rs.next());
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetColumns() throws Exception {
+        fail("https://issues.apache.org/jira/browse/IGNITE-5233");
+
+        try (Connection conn = DriverManager.getConnection(URL)) {
+            conn.setSchema("pers");
+
+            DatabaseMetaData meta = conn.getMetaData();
+
+            ResultSet rs = meta.getColumns("", "pers", "Person", "%");
+
+            assert rs != null;
+
+            Collection<String> names = new ArrayList<>(2);
+
+            names.add("NAME");
+            names.add("AGE");
+            names.add("ORGID");
+
+            int cnt = 0;
+
+            while (rs.next()) {
+                String name = rs.getString("COLUMN_NAME");
+
+                assert names.remove(name);
+
+                if ("NAME".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == VARCHAR;
+                    assert "VARCHAR".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 1;
+                } else if ("AGE".equals(name) || "ORGID".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == INTEGER;
+                    assert "INTEGER".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                }
+                if ("_KEY".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == OTHER;
+                    assert "OTHER".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                }
+                if ("_VAL".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == OTHER;
+                    assert "OTHER".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                }
+
+                cnt++;
+            }
+
+            assert names.isEmpty();
+            assert cnt == 3;
+
+            rs = meta.getColumns("", "org", "Organization", "%");
+
+            assert rs != null;
+
+            names.add("ID");
+            names.add("NAME");
+
+            cnt = 0;
+
+            while (rs.next()) {
+                String name = rs.getString("COLUMN_NAME");
+
+                assert names.remove(name);
+
+                if ("id".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == INTEGER;
+                    assert "INTEGER".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                } else if ("name".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == VARCHAR;
+                    assert "VARCHAR".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 1;
+                }
+                if ("_KEY".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == VARCHAR;
+                    assert "VARCHAR".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                }
+                if ("_VAL".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == OTHER;
+                    assert "OTHER".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                }
+
+                cnt++;
+            }
+
+            assert names.isEmpty();
+            assert cnt == 2;
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMetadataResultSetClose() throws Exception {
+        fail("https://issues.apache.org/jira/browse/IGNITE-5233");
+
+        try (Connection conn = DriverManager.getConnection(URL);
+             ResultSet tbls = conn.getMetaData().getTables(null, null, "%", null)) {
+            int colCnt = tbls.getMetaData().getColumnCount();
+
+            while (tbls.next()) {
+                for (int i = 0; i < colCnt; i++)
+                    tbls.getObject(i + 1);
+            }
+        }
+        catch (Exception e) {
+            log.error("Unexpected exception", e);
+
+            fail();
+        }
+    }
+
+    /**
+     * Person.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Person implements Serializable {
+        /** Name. */
+        @QuerySqlField(index = false)
+        private final String name;
+
+        /** Age. */
+        @QuerySqlField
+        private final int age;
+
+        /** Organization ID. */
+        @QuerySqlField
+        private final int orgId;
+
+        /**
+         * @param name Name.
+         * @param age Age.
+         * @param orgId Organization ID.
+         */
+        private Person(String name, int age, int orgId) {
+            assert !F.isEmpty(name);
+            assert age > 0;
+            assert orgId > 0;
+
+            this.name = name;
+            this.age = age;
+            this.orgId = orgId;
+        }
+    }
+
+    /**
+     * Organization.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Organization implements Serializable {
+        /** ID. */
+        @QuerySqlField
+        private final int id;
+
+        /** Name. */
+        @QuerySqlField(index = false)
+        private final String name;
+
+        /**
+         * @param id ID.
+         * @param name Name.
+         */
+        private Organization(int id, String name) {
+            this.id = id;
+            this.name = name;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
new file mode 100644
index 0000000..97008c8
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ *
+ */
+public class JdbcThinNoDefaultSchemaTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** First cache name. */
+    private static final String CACHE1_NAME = "cache1";
+
+    /** Second cache name. */
+    private static final String CACHE2_NAME = "cache2";
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** Grid count. */
+    private static final int GRID_CNT = 2;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setCacheConfiguration(cacheConfiguration(CACHE1_NAME), cacheConfiguration(CACHE2_NAME));
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        return cfg;
+    }
+
+    /**
+     * @param name Cache name.
+     * @return Cache configuration.
+     * @throws Exception In case of error.
+     */
+    @SuppressWarnings("unchecked")
+    private CacheConfiguration cacheConfiguration(@NotNull String name) throws Exception {
+        CacheConfiguration cfg = defaultCacheConfiguration();
+
+        cfg.setIndexedTypes(Integer.class, Integer.class);
+
+        cfg.setName(name);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(GRID_CNT);
+
+        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
+
+        Ignite ignite = ignite(0);
+
+        IgniteCache<Integer, Integer> cache1 = ignite.cache(CACHE1_NAME);
+        IgniteCache<Integer, Integer> cache2 = ignite.cache(CACHE2_NAME);
+
+        for (int i = 0; i < 10; i++) {
+            cache1.put(i, i * 2);
+            cache2.put(i, i * 3);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDefaults() throws Exception {
+        String url = URL;
+
+        try (Connection conn = DriverManager.getConnection(url)) {
+            assertNotNull(conn);
+        }
+
+        try (Connection conn = DriverManager.getConnection(url + '/')) {
+            assertNotNull(conn);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNoCacheNameQuery() throws Exception {
+        Connection conn = DriverManager.getConnection(URL);
+
+        conn.setSchema("cache1");
+
+        Statement stmt = conn.createStatement();
+
+        assertNotNull(stmt);
+        assertFalse(stmt.isClosed());
+
+        stmt.execute("select t._key, t._val from \"cache1\".Integer t");
+
+        ResultSet rs = stmt.getResultSet();
+
+        while(rs.next())
+            assertEquals(rs.getInt(2), rs.getInt(1) * 2);
+
+        stmt.execute("select t._key, t._val from \"cache2\".Integer t");
+
+        rs = stmt.getResultSet();
+
+        while(rs.next())
+            assertEquals(rs.getInt(2), rs.getInt(1) * 3);
+
+        stmt.execute("select t._key, t._val, v._val " +
+            "from \"cache1\".Integer t join \"cache2\".Integer v on t._key = v._key");
+
+        rs = stmt.getResultSet();
+
+        while(rs.next()) {
+            assertEquals(rs.getInt(2), rs.getInt(1) * 2);
+            assertEquals(rs.getInt(3), rs.getInt(1) * 3);
+        }
+
+        stmt.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
new file mode 100644
index 0000000..aead436
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
@@ -0,0 +1,771 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.concurrent.Callable;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+
+import static java.sql.Types.BIGINT;
+import static java.sql.Types.BINARY;
+import static java.sql.Types.BOOLEAN;
+import static java.sql.Types.DATE;
+import static java.sql.Types.DOUBLE;
+import static java.sql.Types.FLOAT;
+import static java.sql.Types.INTEGER;
+import static java.sql.Types.OTHER;
+import static java.sql.Types.SMALLINT;
+import static java.sql.Types.TIME;
+import static java.sql.Types.TIMESTAMP;
+import static java.sql.Types.TINYINT;
+import static java.sql.Types.VARCHAR;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Prepared statement test.
+ */
+public class JdbcThinPreparedStatementSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** SQL query. */
+    private static final String SQL_PART =
+        "select id, boolVal, byteVal, shortVal, intVal, longVal, floatVal, " +
+            "doubleVal, bigVal, strVal, arrVal, dateVal, timeVal, tsVal " +
+            "from TestObject ";
+
+    /** Connection. */
+    private Connection conn;
+
+    /** Statement. */
+    private PreparedStatement stmt;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+        cache.setIndexedTypes(
+            Integer.class, TestObject.class
+        );
+
+        cfg.setCacheConfiguration(cache);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        cfg.setOdbcConfiguration(new OdbcConfiguration());
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(3);
+
+        IgniteCache<Integer, TestObject> cache = grid(0).cache(DEFAULT_CACHE_NAME);
+
+        assert cache != null;
+
+        TestObject o = new TestObject(1);
+
+        o.boolVal = true;
+        o.byteVal = 1;
+        o.shortVal = 1;
+        o.intVal = 1;
+        o.longVal = 1L;
+        o.floatVal = 1.0f;
+        o.doubleVal = 1.0d;
+        o.bigVal = new BigDecimal(1);
+        o.strVal = "str";
+        o.arrVal = new byte[] {1};
+        o.dateVal = new Date(1);
+        o.timeVal = new Time(1);
+        o.tsVal = new Timestamp(1);
+        o.urlVal = new URL("http://abc.com/");
+
+        cache.put(1, o);
+        cache.put(2, new TestObject(2));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        conn = DriverManager.getConnection(URL);
+
+        conn.setSchema(DEFAULT_CACHE_NAME);
+
+        assert conn != null;
+        assert !conn.isClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (stmt != null) {
+            stmt.close();
+
+            assert stmt.isClosed();
+        }
+
+        if (conn != null) {
+            conn.close();
+
+            assert conn.isClosed();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testQueryExecuteException() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where boolVal is not distinct from ?");
+
+        stmt.setBoolean(1, true);
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                stmt.executeQuery(SQL_PART);
+
+                return null;
+            }
+        }, SQLException.class, "The method 'executeQuery(String)' is called on PreparedStatement instance.");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                stmt.execute(SQL_PART);
+
+                return null;
+            }
+        }, SQLException.class, "The method 'execute(String)' is called on PreparedStatement instance.");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBoolean() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where boolVal is not distinct from ?");
+
+        stmt.setBoolean(1, true);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, BOOLEAN);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testByte() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where byteVal is not distinct from ?");
+
+        stmt.setByte(1, (byte)1);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, TINYINT);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testShort() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where shortVal is not distinct from ?");
+
+        stmt.setShort(1, (short)1);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, SMALLINT);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testInteger() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where intVal is not distinct from ?");
+
+        stmt.setInt(1, 1);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, INTEGER);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLong() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where longVal is not distinct from ?");
+
+        stmt.setLong(1, 1L);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, BIGINT);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testFloat() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where floatVal is not distinct from ?");
+
+        stmt.setFloat(1, 1.0f);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, FLOAT);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDouble() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where doubleVal is not distinct from ?");
+
+        stmt.setDouble(1, 1.0d);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, DOUBLE);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBigDecimal() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where bigVal is not distinct from ?");
+
+        stmt.setBigDecimal(1, new BigDecimal(1));
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, OTHER);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testString() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where strVal is not distinct from ?");
+
+        stmt.setString(1, "str");
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, VARCHAR);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testArray() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where arrVal is not distinct from ?");
+
+        stmt.setBytes(1, new byte[] {1});
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, BINARY);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDate() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where dateVal is not distinct from ?");
+
+        stmt.setObject(1, new Date(1));
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, DATE);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testTime() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where timeVal is not distinct from ?");
+
+        stmt.setTime(1, new Time(1));
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, TIME);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testTimestamp() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where tsVal is not distinct from ?");
+
+        stmt.setTimestamp(1, new Timestamp(1));
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, TIMESTAMP);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * Test object.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class TestObject implements Serializable {
+        /** */
+        @QuerySqlField(index = false)
+        private final int id;
+
+        /** */
+        @QuerySqlField
+        private Boolean boolVal;
+
+        /** */
+        @QuerySqlField
+        private Byte byteVal;
+
+        /** */
+        @QuerySqlField
+        private Short shortVal;
+
+        /** */
+        @QuerySqlField
+        private Integer intVal;
+
+        /** */
+        @QuerySqlField
+        private Long longVal;
+
+        /** */
+        @QuerySqlField
+        private Float floatVal;
+
+        /** */
+        @QuerySqlField
+        private Double doubleVal;
+
+        /** */
+        @QuerySqlField
+        private BigDecimal bigVal;
+
+        /** */
+        @QuerySqlField
+        private String strVal;
+
+        /** */
+        @QuerySqlField
+        private byte[] arrVal;
+
+        /** */
+        @QuerySqlField
+        private Date dateVal;
+
+        /** */
+        @QuerySqlField
+        private Time timeVal;
+
+        /** */
+        @QuerySqlField
+        private Timestamp tsVal;
+
+        /** */
+        @QuerySqlField
+        private URL urlVal;
+
+        /**
+         * @param id ID.
+         */
+        private TestObject(int id) {
+            this.id = id;
+        }
+    }
+}
\ No newline at end of file


[35/50] [abbrv] ignite git commit: Corrected ServiceProcessor shutdown sequence

Posted by sb...@apache.org.
Corrected ServiceProcessor shutdown sequence


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/1d0b0765
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/1d0b0765
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/1d0b0765

Branch: refs/heads/ignite-5075
Commit: 1d0b0765134a81e6626a9ef1c70939085f954847
Parents: 31ac7e9a
Author: Konstantin Dudkov <kd...@ya.ru>
Authored: Mon Jun 5 11:06:44 2017 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Mon Jun 5 11:06:44 2017 +0300

----------------------------------------------------------------------
 .../service/GridServiceProcessor.java           | 86 +++++++++-----------
 1 file changed, 39 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1d0b0765/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
index c2fee02..fd8141c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
@@ -281,56 +281,52 @@ public class GridServiceProcessor extends GridProcessorAdapter implements Ignite
         if (ctx.isDaemon())
             return;
 
+        // Will not release it.
         busyLock.block();
 
-        try {
-            U.shutdownNow(GridServiceProcessor.class, depExe, log);
+        U.shutdownNow(GridServiceProcessor.class, depExe, log);
 
-            if (!ctx.clientNode())
-                ctx.event().removeDiscoveryEventListener(topLsnr);
+        if (!ctx.clientNode())
+            ctx.event().removeDiscoveryEventListener(topLsnr);
 
-            Collection<ServiceContextImpl> ctxs = new ArrayList<>();
+        Collection<ServiceContextImpl> ctxs = new ArrayList<>();
 
-            synchronized (locSvcs) {
-                for (Collection<ServiceContextImpl> ctxs0 : locSvcs.values())
-                    ctxs.addAll(ctxs0);
-            }
+        synchronized (locSvcs) {
+            for (Collection<ServiceContextImpl> ctxs0 : locSvcs.values())
+                ctxs.addAll(ctxs0);
+        }
 
-            for (ServiceContextImpl ctx : ctxs) {
-                ctx.setCancelled(true);
+        for (ServiceContextImpl ctx : ctxs) {
+            ctx.setCancelled(true);
 
-                Service svc = ctx.service();
+            Service svc = ctx.service();
 
-                if (svc != null)
-                    svc.cancel(ctx);
+            if (svc != null)
+                svc.cancel(ctx);
 
-                ctx.executor().shutdownNow();
-            }
+            ctx.executor().shutdownNow();
+        }
 
-            for (ServiceContextImpl ctx : ctxs) {
-                try {
-                    if (log.isInfoEnabled() && !ctxs.isEmpty())
-                        log.info("Shutting down distributed service [name=" + ctx.name() + ", execId8=" +
-                            U.id8(ctx.executionId()) + ']');
+        for (ServiceContextImpl ctx : ctxs) {
+            try {
+                if (log.isInfoEnabled() && !ctxs.isEmpty())
+                    log.info("Shutting down distributed service [name=" + ctx.name() + ", execId8=" +
+                        U.id8(ctx.executionId()) + ']');
 
-                    ctx.executor().awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
-                }
-                catch (InterruptedException ignore) {
-                    Thread.currentThread().interrupt();
+                ctx.executor().awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+            }
+            catch (InterruptedException ignore) {
+                Thread.currentThread().interrupt();
 
-                    U.error(log, "Got interrupted while waiting for service to shutdown (will continue stopping node): " +
-                        ctx.name());
-                }
+                U.error(log, "Got interrupted while waiting for service to shutdown (will continue stopping node): " +
+                    ctx.name());
             }
+        }
 
-            Exception err = new IgniteCheckedException("Operation has been cancelled (node is stopping).");
+        Exception err = new IgniteCheckedException("Operation has been cancelled (node is stopping).");
 
-            cancelFutures(depFuts, err);
-            cancelFutures(undepFuts, err);
-        }
-        finally {
-            busyLock.unblock();
-        }
+        cancelFutures(depFuts, err);
+        cancelFutures(undepFuts, err);
 
         if (log.isDebugEnabled())
             log.debug("Stopped service processor.");
@@ -462,10 +458,11 @@ public class GridServiceProcessor extends GridProcessorAdapter implements Ignite
      * @param name Service name.
      * @param svc Service.
      * @param cacheName Cache name.
-     * @param  affKey Affinity key.
+     * @param affKey Affinity key.
      * @return Future.
      */
-    public IgniteInternalFuture<?> deployKeyAffinitySingleton(String name, Service svc, String cacheName, Object affKey) {
+    public IgniteInternalFuture<?> deployKeyAffinitySingleton(String name, Service svc, String cacheName,
+        Object affKey) {
         A.notNull(affKey, "affKey");
 
         ServiceConfiguration cfg = new ServiceConfiguration();
@@ -878,7 +875,7 @@ public class GridServiceProcessor extends GridProcessorAdapter implements Ignite
         Collection<ServiceContextImpl> ctxs;
 
         synchronized (locSvcs) {
-             ctxs = locSvcs.get(name);
+            ctxs = locSvcs.get(name);
         }
 
         if (ctxs == null)
@@ -921,9 +918,9 @@ public class GridServiceProcessor extends GridProcessorAdapter implements Ignite
         while (true) {
             GridServiceAssignments assigns = new GridServiceAssignments(cfg, dep.nodeId(), topVer.topologyVersion());
 
-             Collection<ClusterNode> nodes;
+            Collection<ClusterNode> nodes;
 
-             // Call node filter outside of transaction.
+            // Call node filter outside of transaction.
             if (affKey == null) {
                 nodes = ctx.discovery().nodes(topVer);
 
@@ -1212,7 +1209,7 @@ public class GridServiceProcessor extends GridProcessorAdapter implements Ignite
      * @param cancelCnt Number of contexts to cancel.
      */
     private void cancel(Iterable<ServiceContextImpl> ctxs, int cancelCnt) {
-        for (Iterator<ServiceContextImpl> it = ctxs.iterator(); it.hasNext();) {
+        for (Iterator<ServiceContextImpl> it = ctxs.iterator(); it.hasNext(); ) {
             ServiceContextImpl svcCtx = it.next();
 
             // Flip cancelled flag.
@@ -1285,7 +1282,7 @@ public class GridServiceProcessor extends GridProcessorAdapter implements Ignite
             GridCloseableIterator<Map.Entry<Object, Object>> iter = qry.executeScanQuery();
 
             return cache.context().itHolder().iterator(iter,
-                new CacheIteratorConverter<Cache.Entry<Object, Object>, Map.Entry<Object,Object>>() {
+                new CacheIteratorConverter<Cache.Entry<Object, Object>, Map.Entry<Object, Object>>() {
                     @Override protected Cache.Entry<Object, Object> convert(Map.Entry<Object, Object> e) {
                         return new CacheEntryImpl<>(e.getKey(), e.getValue());
                     }
@@ -1510,10 +1507,6 @@ public class GridServiceProcessor extends GridProcessorAdapter implements Ignite
             if (!busyLock.enterBusy())
                 return;
 
-            //Must check that threadpool was not shutdown.
-            if (depExe.isShutdown())
-                return;
-
             try {
                 final AffinityTopologyVersion topVer;
 
@@ -1726,7 +1719,6 @@ public class GridServiceProcessor extends GridProcessorAdapter implements Ignite
             undeploy(e.getKey().name());
     }
 
-
     /**
      * @param name Name.
      */


[13/50] [abbrv] ignite git commit: IGNITE-5113: Fixed missing Apache headers.

Posted by sb...@apache.org.
IGNITE-5113: Fixed missing Apache headers.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/be3d6068
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/be3d6068
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/be3d6068

Branch: refs/heads/ignite-5075
Commit: be3d60688c788c99088126017693e43803b87124
Parents: e92707b
Author: devozerov <vo...@gridgain.com>
Authored: Fri Jun 2 14:44:07 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 14:44:07 2017 +0300

----------------------------------------------------------------------
 .../impls/storage/matrix/MapWrapperStorage.java    | 17 +++++++++++++++++
 .../ml/math/impls/vector/MapWrapperVector.java     | 17 +++++++++++++++++
 .../ignite/ml/clustering/ClusteringTesetSuite.java | 17 +++++++++++++++++
 3 files changed, 51 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/be3d6068/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MapWrapperStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MapWrapperStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MapWrapperStorage.java
index 13b8303..6cefb25 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MapWrapperStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MapWrapperStorage.java
@@ -1,3 +1,20 @@
+/*
+ * 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.ml.math.impls.storage.matrix;
 
 import org.apache.ignite.internal.util.GridArgumentCheck;

http://git-wip-us.apache.org/repos/asf/ignite/blob/be3d6068/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/MapWrapperVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/MapWrapperVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/MapWrapperVector.java
index 729a7ea..c04cc45 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/MapWrapperVector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/MapWrapperVector.java
@@ -1,3 +1,20 @@
+/*
+ * 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.ml.math.impls.vector;
 
 import org.apache.ignite.ml.math.Matrix;

http://git-wip-us.apache.org/repos/asf/ignite/blob/be3d6068/modules/ml/src/test/java/org/apache/ignite/ml/clustering/ClusteringTesetSuite.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/ClusteringTesetSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/ClusteringTesetSuite.java
index 122d0c1..fb756ba 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/ClusteringTesetSuite.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/ClusteringTesetSuite.java
@@ -1,3 +1,20 @@
+/*
+ * 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.ml.clustering;
 
 import org.junit.runner.RunWith;


[22/50] [abbrv] ignite git commit: IGNITE-5393 .NET: Fix NuGet suite build

Posted by sb...@apache.org.
IGNITE-5393 .NET: Fix NuGet suite build

This closes #2069


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/4024cd3a
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/4024cd3a
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/4024cd3a

Branch: refs/heads/ignite-5075
Commit: 4024cd3a3e2c3c9cd41a16018a15aaf8b0e3daad
Parents: 3d7b15b
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Jun 2 17:42:54 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Jun 2 17:42:54 2017 +0300

----------------------------------------------------------------------
 .../Apache.Ignite.Core.Tests.NuGet/NuGet.config |  2 +-
 .../StartupTest.cs                              |  1 -
 .../install-package.ps1                         | 31 ++++++++------------
 modules/platforms/dotnet/build.ps1              |  5 +++-
 4 files changed, 18 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/4024cd3a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/NuGet.config
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/NuGet.config b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/NuGet.config
index fc0c0b5..8ef3fb0 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/NuGet.config
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/NuGet.config
@@ -26,7 +26,7 @@
   </packageRestore>
   <packageSources>
 	<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
-    <add key="local" value="nupkg" />
+    <add key="local" value="..\nupkg" />
   </packageSources>
   <!-- Used to specify which one of the sources are active -->
   <activePackageSource>

http://git-wip-us.apache.org/repos/asf/ignite/blob/4024cd3a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/StartupTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/StartupTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/StartupTest.cs
index db62e09..0eb7a96 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/StartupTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/StartupTest.cs
@@ -17,7 +17,6 @@
 
 namespace Apache.Ignite.Core.Tests.NuGet
 {
-    using System;
     using System.Diagnostics;
     using System.IO;
     using System.Linq;

http://git-wip-us.apache.org/repos/asf/ignite/blob/4024cd3a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/install-package.ps1
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/install-package.ps1 b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/install-package.ps1
index 3289918..8d36e0e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/install-package.ps1
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/install-package.ps1
@@ -1,22 +1,6 @@
-$ng = (Get-Item .).FullName + '\nuget.exe'
+$ver = (gi ..\Apache.Ignite.Core\bin\Release\Apache.Ignite.Core.dll).VersionInfo.ProductVersion
 
-if (!(Test-Path $ng)) {
-    $ng = 'nuget'
-}
-
-$cfg = 'Release'
-$ver = (gi ..\Apache.Ignite.Core\bin\$cfg\Apache.Ignite.Core.dll).VersionInfo.ProductVersion
-
-rmdir nupkg -Force -Recurse
-rmdir pkg -Force -Recurse
-
-mkdir nupkg
-mkdir pkg
-
-# Find all nuspec files and run 'nuget pack' either directly, or on corresponding csproj files (if present).
-ls ..\*.nuspec -Recurse  `
-    | % { If (Test-Path ([io.path]::ChangeExtension($_.FullName, ".csproj"))){[io.path]::ChangeExtension($_.FullName, ".csproj")} Else {$_.FullName}  } `
-    | % { & $ng pack $_ -Prop Configuration=$cfg -Version $ver -Prop Platform=AnyCPU -OutputDirectory nupkg }
+rmdir packages -Force -Recurse
 
 # Replace versions in project files
 (Get-Content packages.config) `
@@ -26,6 +10,17 @@ ls ..\*.nuspec -Recurse  `
 (Get-Content Apache.Ignite.Core.Tests.NuGet.csproj) `
     -replace 'packages\\Apache.Ignite(.*?)\.\d.*?\\', ('packages\Apache.Ignite$1.' + "$ver\") `
     | Out-File Apache.Ignite.Core.Tests.NuGet.csproj  -Encoding utf8
+	
+# Detect NuGet
+$ng = "nuget"
+if ((Get-Command $ng -ErrorAction SilentlyContinue) -eq $null) { 
+    $ng = ".\nuget.exe"
+
+    if (-not (Test-Path $ng)) {
+        echo "Downloading NuGet..."
+        (New-Object System.Net.WebClient).DownloadFile("https://dist.nuget.org/win-x86-commandline/v3.3.0/nuget.exe", "nuget.exe");    
+    }
+}
 
 # restore packages
 & $ng restore

http://git-wip-us.apache.org/repos/asf/ignite/blob/4024cd3a/modules/platforms/dotnet/build.ps1
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/build.ps1 b/modules/platforms/dotnet/build.ps1
index 222076a..692959f 100644
--- a/modules/platforms/dotnet/build.ps1
+++ b/modules/platforms/dotnet/build.ps1
@@ -112,7 +112,10 @@ if (!$skipJava) {
     $libsDir = "$PSScriptRoot\bin\Libs"
     mkdir -Force $libsDir; del -Force $libsDir\*.*
     
-    ls modules\indexing\target,modules\core\target,modules\spring\target*.jar -recurse -include "ignite-core*","ignite-indexing*","ignite-shmem*","ignite-spring*","lucene*","h2*","cache-api*","commons-*","spring*" -exclude "*-sources*","*-javadoc*","*-tests*" | % { copy -Force $_ $libsDir }
+    ls modules\indexing\target,modules\core\target,modules\spring\target *.jar -recurse `
+	   -include "ignite-core*","ignite-indexing*","ignite-shmem*","ignite-spring*","lucene*","h2*","cache-api*","commons-*","spring*" `
+	   -exclude "*-sources*","*-javadoc*","*-tests*" `
+	   | % { copy -Force $_ $libsDir }
 
     # Restore directory
     cd $PSScriptRoot


[17/50] [abbrv] ignite git commit: ignite-4496 Review all logging for sensitive data leak

Posted by sb...@apache.org.
ignite-4496 Review all logging for sensitive data leak


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/43ab98be
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/43ab98be
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/43ab98be

Branch: refs/heads/ignite-5075
Commit: 43ab98bedd2735f349b08ac02983fa0511aa4692
Parents: b7d8d1b
Author: sboikov <sb...@gridgain.com>
Authored: Fri Jun 2 16:27:13 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jun 2 16:27:13 2017 +0300

----------------------------------------------------------------------
 .../org/apache/ignite/internal/SensitiveInfoTestLoggerProxy.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/43ab98be/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy.java b/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy.java
index 89d3ce0..9cfe40d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/SensitiveInfoTestLoggerProxy.java
@@ -73,7 +73,7 @@ public class SensitiveInfoTestLoggerProxy implements IgniteLogger, LifecycleAwar
     private static final boolean logGridName = System.getProperty(IGNITE_LOG_GRID_NAME) != null;
 
     /** Test sensitive mode. */
-    public static final boolean TEST_SENSITIVE = true;//System.getProperty(IGNITE_LOG_TEST_SENSITIVE) != null;
+    public static final boolean TEST_SENSITIVE = System.getProperty(IGNITE_LOG_TEST_SENSITIVE) != null;
 
     /** Prefix for all suspicious sensitive data. */
     private static final String SENSITIVE_PREFIX = "SENSITIVE> ";


[20/50] [abbrv] ignite git commit: Merge remote-tracking branch 'origin/master'

Posted by sb...@apache.org.
Merge remote-tracking branch 'origin/master'


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e4580b8c
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e4580b8c
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e4580b8c

Branch: refs/heads/ignite-5075
Commit: e4580b8c4b51d25ad294b67125b1a5a8ea5de455
Parents: 6f1a900 79ab48b
Author: devozerov <vo...@gridgain.com>
Authored: Fri Jun 2 17:15:03 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 17:15:03 2017 +0300

----------------------------------------------------------------------
 .../processors/rest/handlers/query/QueryCommandHandler.java   | 7 ++++---
 .../rest/handlers/query/GridQueryCommandHandlerTest.java      | 3 ++-
 2 files changed, 6 insertions(+), 4 deletions(-)
----------------------------------------------------------------------



[40/50] [abbrv] ignite git commit: IGNITE-5275: Implemented SqlConnectorConfiguration. Deprecated OdbcConfiguration. This closes #2080.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java
new file mode 100644
index 0000000..dedc5fd
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java
@@ -0,0 +1,245 @@
+/*
+ * 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.processors.sql;
+
+import junit.framework.TestCase;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.SqlConnectorConfiguration;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.Nullable;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * ODBC configuration validation tests.
+ */
+public class SqlConnectorConfigurationValidationSelfTest extends GridCommonAbstractTest {
+    /** Node index generator. */
+    private static final AtomicInteger NODE_IDX_GEN = new AtomicInteger();
+
+    /** Cache name. */
+    private static final String CACHE_NAME = "CACHE";
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * Test host.
+     *
+     * @throws Exception If failed.
+     */
+    public void testDefault() throws Exception {
+        check(new SqlConnectorConfiguration(), true);
+        assertJdbc(null, SqlConnectorConfiguration.DFLT_PORT);
+    }
+
+    /**
+     * Test host.
+     *
+     * @throws Exception If failed.
+     */
+    public void testHost() throws Exception {
+        check(new SqlConnectorConfiguration().setHost("126.0.0.1"), false);
+
+        check(new SqlConnectorConfiguration().setHost("127.0.0.1"), true);
+        assertJdbc("127.0.0.1", SqlConnectorConfiguration.DFLT_PORT);
+
+        check(new SqlConnectorConfiguration().setHost("0.0.0.0"), true);
+        assertJdbc("0.0.0.0", SqlConnectorConfiguration.DFLT_PORT + 1);
+
+    }
+
+    /**
+     * Test port.
+     *
+     * @throws Exception If failed.
+     */
+    public void testPort() throws Exception {
+        check(new SqlConnectorConfiguration().setPort(-1), false);
+        check(new SqlConnectorConfiguration().setPort(0), false);
+        check(new SqlConnectorConfiguration().setPort(512), false);
+        check(new SqlConnectorConfiguration().setPort(65536), false);
+
+        check(new SqlConnectorConfiguration().setPort(SqlConnectorConfiguration.DFLT_PORT), true);
+        assertJdbc(null, SqlConnectorConfiguration.DFLT_PORT);
+
+        check(new SqlConnectorConfiguration().setPort(SqlConnectorConfiguration.DFLT_PORT + 200), true);
+        assertJdbc(null, SqlConnectorConfiguration.DFLT_PORT + 200);
+    }
+
+
+    /**
+     * Test port.
+     *
+     * @throws Exception If failed.
+     */
+    public void testPortRange() throws Exception {
+        check(new SqlConnectorConfiguration().setPortRange(-1), false);
+
+        check(new SqlConnectorConfiguration().setPortRange(0), true);
+        assertJdbc(null, SqlConnectorConfiguration.DFLT_PORT);
+
+        check(new SqlConnectorConfiguration().setPortRange(10), true);
+        assertJdbc(null, SqlConnectorConfiguration.DFLT_PORT + 1);
+    }
+
+    /**
+     * Test socket buffers.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSocketBuffers() throws Exception {
+        check(new SqlConnectorConfiguration().setSocketSendBufferSize(-4 * 1024), false);
+        check(new SqlConnectorConfiguration().setSocketReceiveBufferSize(-4 * 1024), false);
+
+        check(new SqlConnectorConfiguration().setSocketSendBufferSize(4 * 1024), true);
+        assertJdbc(null, SqlConnectorConfiguration.DFLT_PORT);
+
+        check(new SqlConnectorConfiguration().setSocketReceiveBufferSize(4 * 1024), true);
+        assertJdbc(null, SqlConnectorConfiguration.DFLT_PORT + 1);
+    }
+
+    /**
+     * Test max open cursors per connection.
+     *
+     * @throws Exception If failed.
+     */
+    public void testMaxOpenCusrorsPerConnection() throws Exception {
+        check(new SqlConnectorConfiguration().setMaxOpenCursorsPerConnection(-1), false);
+
+        check(new SqlConnectorConfiguration().setMaxOpenCursorsPerConnection(0), true);
+        assertJdbc(null, SqlConnectorConfiguration.DFLT_PORT);
+
+        check(new SqlConnectorConfiguration().setMaxOpenCursorsPerConnection(100), true);
+        assertJdbc(null, SqlConnectorConfiguration.DFLT_PORT + 1);
+    }
+
+    /**
+     * Test thread pool size.
+     *
+     * @throws Exception If failed.
+     */
+    public void testThreadPoolSize() throws Exception {
+        check(new SqlConnectorConfiguration().setThreadPoolSize(0), false);
+        check(new SqlConnectorConfiguration().setThreadPoolSize(-1), false);
+
+        check(new SqlConnectorConfiguration().setThreadPoolSize(4), true);
+        assertJdbc(null, SqlConnectorConfiguration.DFLT_PORT);
+    }
+
+    /**
+     * Perform check.
+     *
+     * @param sqlCfg SQL configuration.
+     * @param success Success flag. * @throws Exception If failed.
+     */
+    @SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "unchecked"})
+    private void check(SqlConnectorConfiguration sqlCfg, boolean success) throws Exception {
+        final IgniteConfiguration cfg = super.getConfiguration();
+
+        cfg.setIgniteInstanceName(SqlConnectorConfigurationValidationSelfTest.class.getName() + "-" +
+            NODE_IDX_GEN.incrementAndGet());
+
+        cfg.setLocalHost("127.0.0.1");
+        cfg.setSqlConnectorConfiguration(sqlCfg);
+        cfg.setMarshaller(new BinaryMarshaller());
+
+        TcpDiscoverySpi spi = new TcpDiscoverySpi();
+        spi.setIpFinder(new TcpDiscoveryVmIpFinder(true));
+
+        cfg.setDiscoverySpi(spi);
+
+        CacheConfiguration ccfg = new CacheConfiguration(CACHE_NAME)
+            .setIndexedTypes(SqlConnectorKey.class, SqlConnectorValue.class);
+
+        cfg.setCacheConfiguration(ccfg);
+
+        if (success)
+            startGrid(cfg.getIgniteInstanceName(), cfg);
+        else {
+            GridTestUtils.assertThrows(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    startGrid(cfg.getIgniteInstanceName(), cfg);
+
+                    return null;
+                }
+            }, IgniteException.class, null);
+        }
+    }
+
+    /**
+     * Make sure that JDBC connection is possible at the given host and port.
+     *
+     * @param host Host.
+     * @param port Port.
+     * @throws Exception If failed.
+     */
+    private void assertJdbc(@Nullable String host, int port) throws Exception {
+        if (host == null)
+            host = "127.0.0.1";
+
+        String connStr = "jdbc:ignite:thin://" + host + ":" + port;
+
+        try (Connection conn = DriverManager.getConnection(connStr)) {
+            conn.setSchema(CACHE_NAME);
+
+            try (Statement stmt = conn.createStatement()) {
+                ResultSet rs = stmt.executeQuery("SELECT 1");
+
+                assertTrue(rs.next());
+
+                TestCase.assertEquals(1, rs.getInt(1));
+            }
+        }
+    }
+
+    /**
+     * Key class.
+     */
+    private static class SqlConnectorKey {
+        @QuerySqlField
+        public int key;
+    }
+
+    /**
+     * Value class.
+     */
+    private static class SqlConnectorValue {
+        @QuerySqlField
+        public int val;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
index fb6a86b..0d18517 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
@@ -122,6 +122,7 @@ import org.apache.ignite.internal.processors.query.h2.sql.BaseH2CompareQueryTest
 import org.apache.ignite.internal.processors.query.h2.sql.GridQueryParsingTest;
 import org.apache.ignite.internal.processors.query.h2.sql.H2CompareBigQueryDistributedJoinsTest;
 import org.apache.ignite.internal.processors.query.h2.sql.H2CompareBigQueryTest;
+import org.apache.ignite.internal.processors.sql.SqlConnectorConfigurationValidationSelfTest;
 import org.apache.ignite.spi.communication.tcp.GridOrderedMessageCancelSelfTest;
 import org.apache.ignite.testframework.IgniteTestSuite;
 
@@ -136,6 +137,8 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
     public static TestSuite suite() throws Exception {
         IgniteTestSuite suite = new IgniteTestSuite("Ignite Cache Queries Test Suite");
 
+        suite.addTestSuite(SqlConnectorConfigurationValidationSelfTest.class);
+
         suite.addTestSuite(SqlSchemaSelfTest.class);
 
         // Misc tests.

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/platforms/cpp/examples/odbc-example/config/example-odbc.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/examples/odbc-example/config/example-odbc.xml b/modules/platforms/cpp/examples/odbc-example/config/example-odbc.xml
index e19075e..4780f38 100644
--- a/modules/platforms/cpp/examples/odbc-example/config/example-odbc.xml
+++ b/modules/platforms/cpp/examples/odbc-example/config/example-odbc.xml
@@ -26,12 +26,6 @@
         http://www.springframework.org/schema/util
         http://www.springframework.org/schema/util/spring-util.xsd">
     <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
-
-        <!-- Enabling ODBC. -->
-        <property name="odbcConfiguration">
-            <bean class="org.apache.ignite.configuration.OdbcConfiguration"></bean>
-        </property>
-
         <property name="cacheConfiguration">
             <list>
                 <bean class="org.apache.ignite.configuration.CacheConfiguration">

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/platforms/cpp/odbc-test/config/queries-test-default.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/config/queries-test-default.xml b/modules/platforms/cpp/odbc-test/config/queries-test-default.xml
index c157695..2e7f374 100644
--- a/modules/platforms/cpp/odbc-test/config/queries-test-default.xml
+++ b/modules/platforms/cpp/odbc-test/config/queries-test-default.xml
@@ -28,10 +28,11 @@
     <import resource="queries-default.xml"/>
 
     <bean abstract="true" id="queries.cfg" parent="ignite.cfg">
-        <!-- Enabling ODBC. -->
-        <property name="odbcConfiguration">
-            <bean class="org.apache.ignite.configuration.OdbcConfiguration">
-                <property name="endpointAddress" value="127.0.0.1:11110"/>
+        <property name="sqlConnectorConfiguration">
+            <bean class="org.apache.ignite.configuration.SqlConnectorConfiguration">
+                <property name="host" value="127.0.0.1"/>
+                <property name="port" value="11110"/>
+                <property name="portRange" value="0"/>
             </bean>
         </property>
     </bean>

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/platforms/cpp/odbc-test/config/queries-test-noodbc-32.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/config/queries-test-noodbc-32.xml b/modules/platforms/cpp/odbc-test/config/queries-test-noodbc-32.xml
index 01cae20..568f685 100644
--- a/modules/platforms/cpp/odbc-test/config/queries-test-noodbc-32.xml
+++ b/modules/platforms/cpp/odbc-test/config/queries-test-noodbc-32.xml
@@ -28,6 +28,10 @@
     <import resource="queries-default.xml"/>
 
     <bean parent="ignite.cfg">
+        <property name="sqlConnectorConfiguration">
+            <null/>
+        </property>
+
         <property name="memoryConfiguration">
             <bean class="org.apache.ignite.configuration.MemoryConfiguration">
                 <property name="systemCacheInitialSize" value="#{40 * 1024 * 1024}"/>

http://git-wip-us.apache.org/repos/asf/ignite/blob/776cc6e7/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml b/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml
index b21287f..5cc6044 100644
--- a/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml
+++ b/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml
@@ -27,5 +27,9 @@
     <!-- Imports no-ODBC Ignite configuration -->
     <import resource="queries-default.xml"/>
 
-    <bean parent="ignite.cfg"/>
+    <bean parent="ignite.cfg">
+        <property name="sqlConnectorConfiguration">
+            <null/>
+        </property>
+    </bean>
 </beans>


[06/50] [abbrv] ignite git commit: IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcResponse.java
new file mode 100644
index 0000000..e1b5b30
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcResponse.java
@@ -0,0 +1,69 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * SQL listener response.
+ */
+public class OdbcResponse extends SqlListenerResponse {
+    /** Response object. */
+    @GridToStringInclude
+    private final Object obj;
+
+    /**
+     * Constructs successful rest response.
+     *
+     * @param obj Response object.
+     */
+    public OdbcResponse(Object obj) {
+        super(STATUS_SUCCESS, null);
+
+        this.obj = obj;
+    }
+
+    /**
+     * Constructs failed rest response.
+     *
+     * @param status Response status.
+     * @param err Error, {@code null} if success is {@code true}.
+     */
+    public OdbcResponse(int status, @Nullable String err) {
+        super(status, err);
+
+        assert status != STATUS_SUCCESS;
+
+        obj = null;
+    }
+
+    /**
+     * @return Response object.
+     */
+    public Object response() {
+        return obj;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(OdbcResponse.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTableMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTableMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTableMeta.java
new file mode 100644
index 0000000..d680435
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcTableMeta.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc.odbc;
+
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+
+import java.util.Objects;
+import org.apache.ignite.internal.processors.odbc.OdbcUtils;
+
+/**
+ * ODBC table-related metadata.
+ */
+public class OdbcTableMeta {
+    /** Catalog name. */
+    private final String catalog;
+
+    /** Schema name. */
+    private final String schema;
+
+    /** Table name. */
+    private final String table;
+
+    /** Table type. */
+    private final String tableType;
+
+    /**
+     * @param catalog Catalog name.
+     * @param schema Schema name.
+     * @param table Table name.
+     * @param tableType Table type.
+     */
+    public OdbcTableMeta(String catalog, String schema, String table, String tableType) {
+        this.catalog = catalog;
+        this.schema = OdbcUtils.addQuotationMarksIfNeeded(schema);
+        this.table = table;
+        this.tableType = tableType;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int hash = Objects.hashCode(catalog);
+
+        hash = 31 * hash + Objects.hashCode(schema);
+        hash = 31 * hash + Objects.hashCode(table);
+        hash = 31 * hash + Objects.hashCode(tableType);
+
+        return hash;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (o instanceof OdbcTableMeta) {
+            OdbcTableMeta other = (OdbcTableMeta) o;
+
+            return this == other ||
+                    Objects.equals(catalog, other.catalog) && Objects.equals(schema, other.schema) &&
+                    Objects.equals(table, other.table) && Objects.equals(tableType, other.tableType);
+        }
+
+        return false;
+    }
+
+    /**
+     * Write in a binary format.
+     *
+     * @param writer Binary writer.
+     */
+    public void writeBinary(BinaryRawWriterEx writer) {
+        writer.writeString(catalog);
+        writer.writeString(schema);
+        writer.writeString(table);
+        writer.writeString(tableType);
+    }
+}


[42/50] [abbrv] ignite git commit: IGNITE-5308 .NET: Add "schema" property to SqlFieldsQuery

Posted by sb...@apache.org.
IGNITE-5308 .NET: Add "schema" property to SqlFieldsQuery


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/3642d6c0
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/3642d6c0
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/3642d6c0

Branch: refs/heads/ignite-5075
Commit: 3642d6c0de956cf8556eb9b31bea4e5b6cf738d1
Parents: 776cc6e
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Mon Jun 5 17:52:10 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Mon Jun 5 17:52:10 2017 +0300

----------------------------------------------------------------------
 .../Cache/Query/CacheLinqTest.cs                | 12 ++++----
 .../Cache/Query/CacheQueriesTest.cs             | 32 ++++++++++++++++++++
 .../Cache/Query/SqlFieldsQuery.cs               | 12 ++++++--
 .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs  |  2 +-
 4 files changed, 49 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/3642d6c0/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 04ce965..5d52467 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
@@ -1325,12 +1325,12 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
                   "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".\"Person\" as _T0 where " +
                   "(_T0.\"_KEY\" > ?), Arguments=[10], " +
                   "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
-                  "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True]]"
+                  "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=]]"
                 : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
                   "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
                   "(_T0._KEY > ?), Arguments=[10], " +
                   "Local=True, PageSize=999, EnableDistributedJoins=False, EnforceJoinOrder=True, " +
-                  "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True]]", str);
+                  "Timeout=00:00:02.5000000, ReplicatedOnly=True, Colocated=True, Schema=]]", str);
 
             // Check fields query
             var fieldsQuery = (ICacheQueryable) cache.AsCacheQueryable().Select(x => x.Value.Name);
@@ -1354,11 +1354,11 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
                 ? "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
                   "[Sql=select _T0.\"Name\" from \"person_org\".\"Person\" as _T0, Arguments=[], Local=False, " +
                   "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
-                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False]]"
+                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]"
                 : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
                   "[Sql=select _T0.NAME from \"person_org\".Person as _T0, Arguments=[], Local=False, " +
                   "PageSize=1024, EnableDistributedJoins=False, EnforceJoinOrder=False, " +
-                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False]]", str);
+                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]", str);
             
             // Check distributed joins flag propagation
             var distrQuery = cache.AsCacheQueryable(new QueryOptions {EnableDistributedJoins = true})
@@ -1375,13 +1375,13 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
                   "(((_T0.\"_KEY\" > ?) and (_T0.\"age1\" > ?)) " +
                   "and (_T0.\"Name\" like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
                   "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
-                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False]]"
+                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]"
                 : "CacheQueryable [CacheName=person_org, TableName=Person, Query=SqlFieldsQuery " +
                   "[Sql=select _T0._KEY, _T0._VAL from \"person_org\".Person as _T0 where " +
                   "(((_T0._KEY > ?) and (_T0.AGE1 > ?)) " +
                   "and (_T0.NAME like \'%\' || ? || \'%\') ), Arguments=[10, 20, x], Local=False, " +
                   "PageSize=1024, EnableDistributedJoins=True, EnforceJoinOrder=False, " +
-                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False]]", str);
+                  "Timeout=00:00:00, ReplicatedOnly=False, Colocated=False, Schema=]]", str);
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/3642d6c0/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
index 60d2fdf..852aa87 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
@@ -579,6 +579,38 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
         }
 
         /// <summary>
+        /// Tests custom schema name.
+        /// </summary>
+        [Test]
+        public void TestCustomSchema()
+        {
+            var doubles = GetIgnite().GetOrCreateCache<int, double>(new CacheConfiguration("doubles", typeof(double)));
+            var strings = GetIgnite().GetOrCreateCache<int, string>(new CacheConfiguration("strings", typeof(string)));
+
+            doubles[1] = 36.6;
+            strings[1] = "foo";
+
+            // Default schema.
+            var res = doubles.QueryFields(new SqlFieldsQuery(
+                    "select S._val from double as D join \"strings\".string as S on S._key = D._key"))
+                .Select(x => (string) x[0])
+                .Single();
+
+            Assert.AreEqual("foo", res);
+
+            // Custom schema.
+            res = doubles.QueryFields(new SqlFieldsQuery(
+                    "select S._val from \"doubles\".double as D join string as S on S._key = D._key")
+                {
+                    Schema = strings.Name
+                })
+                .Select(x => (string)x[0])
+                .Single();
+
+            Assert.AreEqual("foo", res);
+        }
+
+        /// <summary>
         /// Tests the distributed joins flag.
         /// </summary>
         [Test]

http://git-wip-us.apache.org/repos/asf/ignite/blob/3642d6c0/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs
index 4809574..aa33415 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs
@@ -128,6 +128,14 @@ namespace Apache.Ignite.Core.Cache.Query
         public bool Colocated { get; set; }
 
         /// <summary>
+        /// Gets or sets the default schema name for the query.
+        /// <para />
+        /// If not set, current cache name is used,
+        /// which means you can omit schema name for tables within the current cache.
+        /// </summary>
+        public string Schema { get; set; }
+
+        /// <summary>
         /// Returns a <see cref="string" /> that represents this instance.
         /// </summary>
         /// <returns>
@@ -139,9 +147,9 @@ namespace Apache.Ignite.Core.Cache.Query
 
             return string.Format("SqlFieldsQuery [Sql={0}, Arguments=[{1}], Local={2}, PageSize={3}, " +
                                  "EnableDistributedJoins={4}, EnforceJoinOrder={5}, Timeout={6}, ReplicatedOnly={7}" +
-                                 ", Colocated={8}]", Sql, args, Local,
+                                 ", Colocated={8}, Schema={9}]", Sql, args, Local,
                                  PageSize, EnableDistributedJoins, EnforceJoinOrder, Timeout, ReplicatedOnly,
-                                 Colocated);
+                                 Colocated, Schema);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3642d6c0/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
index e280a8f..b1bf5eb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
@@ -1089,7 +1089,7 @@ namespace Apache.Ignite.Core.Impl.Cache
                 writer.WriteInt((int) qry.Timeout.TotalMilliseconds);
                 writer.WriteBoolean(qry.ReplicatedOnly);
                 writer.WriteBoolean(qry.Colocated);
-                writer.WriteString(null); // Schema
+                writer.WriteString(qry.Schema); // Schema
             });
         
             return new FieldsQueryCursor<T>(cursor, Marshaller, _flagKeepBinary, readerFunc);


[47/50] [abbrv] ignite git commit: IGNITE-5376: JDBC thin: added "collocated" and "replicatedOnly" flags (2).

Posted by sb...@apache.org.
IGNITE-5376: JDBC thin: added "collocated" and "replicatedOnly" flags (2).


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/986c07a0
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/986c07a0
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/986c07a0

Branch: refs/heads/ignite-5075
Commit: 986c07a0788b5c73c0f1afcd4fb8eee2f1a84a12
Parents: a973392
Author: devozerov <pp...@gmail.com>
Authored: Mon Jun 5 23:16:36 2017 +0300
Committer: devozerov <pp...@gmail.com>
Committed: Mon Jun 5 23:16:36 2017 +0300

----------------------------------------------------------------------
 .../java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java | 4 ++--
 .../ignite/internal/processors/odbc/SqlListenerNioListener.java  | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/986c07a0/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
index bf8234d..1905ea4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
@@ -53,10 +53,10 @@ public class JdbcThinTcpIo {
     private static final SqlListenerProtocolVersion CURRENT_VER = SqlListenerProtocolVersion.create(2, 1, 0);
 
     /** Initial output stream capacity for handshake. */
-    private static final int HANDSHAKE_MSG_SIZE = 10;
+    private static final int HANDSHAKE_MSG_SIZE = 12;
 
     /** Initial output for query message. */
-    private static final int QUERY_EXEC_MSG_INIT_CAP = 1024;
+    private static final int QUERY_EXEC_MSG_INIT_CAP = 256;
 
     /** Initial output for query fetch message. */
     private static final int QUERY_FETCH_MSG_SIZE = 13;

http://git-wip-us.apache.org/repos/asf/ignite/blob/986c07a0/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
index e00b001..fb3359a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
@@ -256,7 +256,7 @@ public class SqlListenerNioListener extends GridNioServerListenerAdapter<byte[]>
             SqlListenerRequestHandler handler = new JdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins,
                 enforceJoinOrder, collocated, replicatedOnly);
 
-            SqlListenerMessageParser parser = new OdbcMessageParser(ctx);
+            SqlListenerMessageParser parser = new JdbcMessageParser(ctx);
 
             return new SqlListenerConnectionContext(handler, parser);
         }


[25/50] [abbrv] ignite git commit: IGNITE-5374: SQL connector: disabled idle timeout.

Posted by sb...@apache.org.
IGNITE-5374: SQL connector: disabled idle timeout.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/2e93148f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/2e93148f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/2e93148f

Branch: refs/heads/ignite-5075
Commit: 2e93148fa79f484b5f03e913626cf60bc8cbff2f
Parents: b375c1e
Author: devozerov <pp...@gmail.com>
Authored: Sat Jun 3 16:56:14 2017 +0300
Committer: devozerov <pp...@gmail.com>
Committed: Sat Jun 3 16:56:14 2017 +0300

----------------------------------------------------------------------
 .../ignite/internal/processors/odbc/SqlListenerProcessor.java       | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/2e93148f/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessor.java
index cbe54df..7ac0929 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerProcessor.java
@@ -138,6 +138,7 @@ public class SqlListenerProcessor extends GridProcessorAdapter {
                             .socketReceiveBufferSize(odbcCfg.getSocketReceiveBufferSize())
                             .filters(filters)
                             .directMode(false)
+                            .idleTimeout(Long.MAX_VALUE)
                             .build();
 
                         srv0.start();


[14/50] [abbrv] ignite git commit: IGNITE-5305: CREATE TABLE and DROP TABLE now correctly pass schema name cache configuration. This closes #2055.

Posted by sb...@apache.org.
IGNITE-5305: CREATE TABLE and DROP TABLE now correctly pass schema name cache configuration. This closes #2055.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a93af295
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a93af295
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a93af295

Branch: refs/heads/ignite-5075
Commit: a93af295649cabc2e5d4b4a035c922570809e371
Parents: be3d606
Author: Alexander Paschenko <al...@gmail.com>
Authored: Fri Jun 2 14:51:56 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 14:51:56 2017 +0300

----------------------------------------------------------------------
 .../processors/query/GridQueryProcessor.java    |   1 +
 .../query/h2/ddl/DdlStatementsProcessor.java    |  10 ++
 .../cache/index/H2DynamicTableSelfTest.java     | 103 ++++++++++++++-----
 3 files changed, 90 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/a93af295/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index fef7d4c..ea8f890 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -1297,6 +1297,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
 
         newCfg.setName(entity.getTableName());
         newCfg.setQueryEntities(Collections.singleton(entity));
+        newCfg.setSqlSchema(schemaName);
 
         // Preserve user specified names as they are.
         newCfg.setSqlEscapeAll(true);

http://git-wip-us.apache.org/repos/asf/ignite/blob/a93af295/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
index 04a0c62..d278e37 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
@@ -33,6 +33,7 @@ import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
 import org.apache.ignite.internal.processors.query.GridQueryProperty;
 import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
 import org.apache.ignite.internal.processors.query.IgniteSQLException;
+import org.apache.ignite.internal.processors.query.QueryUtils;
 import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
 import org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn;
@@ -44,6 +45,7 @@ import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser;
 import org.apache.ignite.internal.processors.query.h2.sql.GridSqlStatement;
 import org.apache.ignite.internal.processors.query.schema.SchemaOperationException;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
+import org.apache.ignite.internal.util.typedef.F;
 import org.h2.command.Prepared;
 import org.h2.command.ddl.CreateIndex;
 import org.h2.command.ddl.CreateTable;
@@ -148,6 +150,10 @@ public class DdlStatementsProcessor {
             else if (stmt0 instanceof GridSqlCreateTable) {
                 GridSqlCreateTable cmd = (GridSqlCreateTable)stmt0;
 
+                if (!F.eq(QueryUtils.DFLT_SCHEMA, cmd.schemaName()))
+                    throw new SchemaOperationException("CREATE TABLE can only be executed on " +
+                        QueryUtils.DFLT_SCHEMA + " schema.");
+
                 GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName());
 
                 if (tbl != null) {
@@ -162,6 +168,10 @@ public class DdlStatementsProcessor {
             else if (stmt0 instanceof GridSqlDropTable) {
                 GridSqlDropTable cmd = (GridSqlDropTable)stmt0;
 
+                if (!F.eq(QueryUtils.DFLT_SCHEMA, cmd.schemaName()))
+                    throw new SchemaOperationException("DROP TABLE can only be executed on " +
+                        QueryUtils.DFLT_SCHEMA + " schema.");
+
                 GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName());
 
                 if (tbl == null) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/a93af295/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
index 4d74bac..6f0dec6 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
@@ -40,6 +40,7 @@ import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
 import org.apache.ignite.internal.processors.query.GridQueryProperty;
 import org.apache.ignite.internal.processors.query.IgniteSQLException;
 import org.apache.ignite.internal.processors.query.QueryTypeDescriptorImpl;
+import org.apache.ignite.internal.processors.query.QueryUtils;
 import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
 import org.apache.ignite.internal.util.typedef.F;
@@ -55,6 +56,9 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     /** */
     private final static String INDEXED_CACHE_NAME = CACHE_NAME + "_idx";
 
+    /** */
+    private final static String INDEXED_CACHE_NAME_2 = INDEXED_CACHE_NAME + "_2";
+
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         super.beforeTestsStarted();
@@ -77,12 +81,13 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
         super.beforeTest();
 
         client().getOrCreateCache(cacheConfigurationForIndexing());
+        client().getOrCreateCache(cacheConfigurationForIndexingInPublicSchema());
     }
 
     /** {@inheritDoc} */
     @Override protected void afterTest() throws Exception {
         if (client().cache("Person") != null)
-            cache().query(new SqlFieldsQuery("DROP TABLE IF EXISTS \"Person\".\"Person\""));
+            executeDdl("DROP TABLE IF EXISTS PUBLIC.\"Person\"");
 
         super.afterTest();
     }
@@ -92,9 +97,9 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testCreateTable() throws Exception {
-        cache().query(new SqlFieldsQuery("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
+        executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\""));
+            "\"cacheTemplate=cache\"");
 
         for (int i = 0; i < 4; i++) {
             IgniteEx node = grid(i);
@@ -132,7 +137,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
 
             assertProperty(desc, "age", Integer.class, false);
 
-            GridH2Table tbl = ((IgniteH2Indexing)node.context().query().getIndexing()).dataTable("Person", "Person");
+            GridH2Table tbl = ((IgniteH2Indexing)node.context().query().getIndexing()).dataTable("PUBLIC", "Person");
 
             assertNotNull(tbl);
         }
@@ -144,13 +149,13 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testCreateTableIfNotExists() throws Exception {
-        cache().query(new SqlFieldsQuery("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
+        executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\""));
+            "\"cacheTemplate=cache\"");
 
-        cache().query(new SqlFieldsQuery("CREATE TABLE IF NOT EXISTS \"Person\" (\"id\" int, \"city\" varchar," +
+        executeDdl("CREATE TABLE IF NOT EXISTS \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\""));
+            "\"cacheTemplate=cache\"");
     }
 
     /**
@@ -159,15 +164,15 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      */
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
     public void testCreateExistingTable() throws Exception {
-        cache().query(new SqlFieldsQuery("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
+        executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\""));
+            "\"cacheTemplate=cache\"");
 
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
-                cache().query(new SqlFieldsQuery("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar" +
+                executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar" +
                     ", \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-                    "\"cacheTemplate=cache\""));
+                    "\"cacheTemplate=cache\"");
 
                 return null;
             }
@@ -179,11 +184,11 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testDropTable() throws Exception {
-        cache().query(new SqlFieldsQuery("CREATE TABLE IF NOT EXISTS \"Person\" (\"id\" int, \"city\" varchar," +
+        executeDdl("CREATE TABLE IF NOT EXISTS \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\""));
+            "\"cacheTemplate=cache\"");
 
-        cache().query(new SqlFieldsQuery("DROP TABLE \"Person\".\"Person\""));
+        executeDdl("DROP TABLE \"Person\"");
 
         for (int i = 0; i < 4; i++) {
             IgniteEx node = grid(i);
@@ -199,10 +204,11 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     /**
      * Test that attempting to {@code DROP TABLE} that does not exist does not yield an error if the statement contains
      *     {@code IF EXISTS} clause.
+     *
      * @throws Exception if failed.
      */
     public void testDropMissingTableIfExists() throws Exception {
-        cache().query(new SqlFieldsQuery("DROP TABLE IF EXISTS \"cache_idx\".\"City\""));
+        executeDdl("DROP TABLE IF EXISTS \"City\"");
     }
 
     /**
@@ -213,7 +219,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     public void testDropMissingTable() throws Exception {
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
-                cache().query(new SqlFieldsQuery("DROP TABLE \"cache_idx\".\"City\""));
+                executeDdl("DROP TABLE \"City\"");
 
                 return null;
             }
@@ -228,12 +234,12 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     public void testDropNonDynamicTable() throws Exception {
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
-                cache().query(new SqlFieldsQuery("DROP TABLE \"Integer\""));
+                executeDdl("DROP TABLE PUBLIC.\"Integer\"");
 
                 return null;
             }
         }, IgniteSQLException.class,
-        "Only cache created with CREATE TABLE may be removed with DROP TABLE [cacheName=cache_idx]");
+        "Only cache created with CREATE TABLE may be removed with DROP TABLE [cacheName=cache_idx_2]");
     }
 
     /**
@@ -242,9 +248,9 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      */
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
     public void testDestroyDynamicSqlCache() throws Exception {
-        cache().query(new SqlFieldsQuery("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
+        executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\""));
+            "\"cacheTemplate=cache\"");
 
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
@@ -263,9 +269,8 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      */
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
     public void testSqlFlagCompatibilityCheck() throws Exception {
-        cache().query(new SqlFieldsQuery("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
-            " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"cacheTemplate=cache\""));
+        executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar, \"name\" varchar, \"surname\" varchar, " +
+            "\"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH \"cacheTemplate=cache\"");
 
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
@@ -277,6 +282,49 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     }
 
     /**
+     * Test that {@code CREATE TABLE} on non-public schema causes an exception.
+     *
+     * @throws Exception if failed.
+     */
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    public void testCreateTableNotPublicSchema() throws Exception {
+        GridTestUtils.assertThrows(null, new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                executeDdl("CREATE TABLE \"cache_idx\".\"Person\" (\"id\" int, \"city\" varchar," +
+                    " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
+                    "\"cacheTemplate=cache\"");
+
+                return null;
+            }
+        }, IgniteSQLException.class, "CREATE TABLE can only be executed on PUBLIC schema.");
+    }
+
+    /**
+     * Test that {@code DROP TABLE} on non-public schema causes an exception.
+     *
+     * @throws Exception if failed.
+     */
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    public void testDropTableNotPublicSchema() throws Exception {
+        GridTestUtils.assertThrows(null, new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                executeDdl("DROP TABLE \"cache_idx\".\"Person\"");
+
+                return null;
+            }
+        }, IgniteSQLException.class, "DROP TABLE can only be executed on PUBLIC schema.");
+    }
+
+    /**
+     * Execute DDL statement.
+     *
+     * @param sql Statement.
+     */
+    private void executeDdl(String sql) {
+        queryProcessor(client()).querySqlFieldsNoCache(new SqlFieldsQuery(sql).setSchema("PUBLIC"), true);
+    }
+
+    /**
      * Check that a property in given descriptor is present and has parameters as expected.
      * @param desc Descriptor.
      * @param name Property name.
@@ -390,4 +438,11 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
 
         return ccfg;
     }
+
+    /**
+     * @return Cache configuration with query entities in {@code PUBLIC} schema.
+     */
+    private CacheConfiguration cacheConfigurationForIndexingInPublicSchema() {
+        return cacheConfigurationForIndexing().setName(INDEXED_CACHE_NAME_2).setSqlSchema(QueryUtils.DFLT_SCHEMA);
+    }
 }


[26/50] [abbrv] ignite git commit: IGNITE-5397: Fixed execution of queries without cache and without tables. This closes #2075.

Posted by sb...@apache.org.
IGNITE-5397: Fixed execution of queries without cache and without tables. This closes #2075.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/1a9c942b
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/1a9c942b
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/1a9c942b

Branch: refs/heads/ignite-5075
Commit: 1a9c942b47a05e8dfaf4f3fd979a6ee94fda4e80
Parents: 2e93148
Author: devozerov <pp...@gmail.com>
Authored: Sat Jun 3 17:52:31 2017 +0300
Committer: devozerov <pp...@gmail.com>
Committed: Sat Jun 3 17:52:31 2017 +0300

----------------------------------------------------------------------
 .../processors/query/GridQueryProcessor.java    |   2 +-
 .../processors/query/h2/IgniteH2Indexing.java   |  19 +-
 .../query/h2/twostep/GridMapQueryExecutor.java  |  75 +++---
 .../h2/twostep/GridReduceQueryExecutor.java     |  28 +--
 .../h2/twostep/msg/GridH2QueryRequest.java      |  37 ++-
 .../cache/IgniteCacheAbstractQuerySelfTest.java |   4 +
 .../query/SqlPublicSchemaSelfTest.java          | 198 ---------------
 .../processors/query/SqlSchemaSelfTest.java     | 238 +++++++++++++++++++
 .../IgniteCacheQuerySelfTestSuite.java          |   5 +-
 9 files changed, 349 insertions(+), 257 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1a9c942b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index 62d826d..e729af5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -1810,7 +1810,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
             throw new IgniteException("Local query is not supported without specific cache.");
 
         if (qry.getSchema() == null)
-            throw new IgniteException("Query schema is not set.");
+            qry.setSchema(QueryUtils.DFLT_SCHEMA);
 
         if (!busyLock.enterBusy())
             throw new IllegalStateException("Failed to execute query (grid is stopping).");

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a9c942b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 12addbd..53201a7 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -1356,15 +1356,16 @@ public class IgniteH2Indexing implements GridQueryIndexing {
                 }
 
                 if (caches0.isEmpty())
-                    throw new IgniteSQLException("Failed to find at least one cache for SQL statement: " + sqlQry);
-
-                //Prohibit usage indices with different numbers of segments in same query.
-                List<Integer> cacheIds = new ArrayList<>(caches0);
-
-                checkCacheIndexSegmentation(cacheIds);
-
-                twoStepQry.cacheIds(cacheIds);
-                twoStepQry.local(qry.isLocal());
+                    twoStepQry.local(true);
+                else {
+                    //Prohibit usage indices with different numbers of segments in same query.
+                    List<Integer> cacheIds = new ArrayList<>(caches0);
+
+                    checkCacheIndexSegmentation(cacheIds);
+    
+                    twoStepQry.cacheIds(cacheIds);
+                    twoStepQry.local(qry.isLocal());
+                }
 
                 meta = H2Utils.meta(stmt.getMetaData());
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a9c942b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
index 23504ad..aa97197 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
@@ -81,6 +81,7 @@ import org.apache.ignite.plugin.extensions.communication.Message;
 import org.h2.jdbc.JdbcResultSet;
 import org.h2.result.ResultInterface;
 import org.h2.value.Value;
+import org.jetbrains.annotations.Nullable;
 import org.jsr166.ConcurrentHashMap8;
 
 import static org.apache.ignite.events.EventType.EVT_CACHE_QUERY_EXECUTED;
@@ -277,13 +278,16 @@ public class GridMapQueryExecutor {
      * @throws IgniteCheckedException If failed.
      */
     private boolean reservePartitions(
-        List<Integer> cacheIds,
+        @Nullable List<Integer> cacheIds,
         AffinityTopologyVersion topVer,
         final int[] explicitParts,
         List<GridReservable> reserved
     ) throws IgniteCheckedException {
         assert topVer != null;
 
+        if (F.isEmpty(cacheIds))
+            return true;
+
         Collection<Integer> partIds = wrap(explicitParts);
 
         for (int i = 0; i < cacheIds.size(); i++) {
@@ -433,8 +437,6 @@ public class GridMapQueryExecutor {
 
         final int[] parts = qryParts == null ? partsMap == null ? null : partsMap.get(ctx.localNodeId()) : qryParts;
 
-        assert !F.isEmpty(req.caches());
-
         final DistributedJoinMode joinMode = distributedJoinMode(
             req.isFlagSet(GridH2QueryRequest.FLAG_IS_LOCAL),
             req.isFlagSet(GridH2QueryRequest.FLAG_DISTRIBUTED_JOINS));
@@ -443,12 +445,16 @@ public class GridMapQueryExecutor {
         final boolean explain = req.isFlagSet(GridH2QueryRequest.FLAG_EXPLAIN);
         final boolean replicated = req.isFlagSet(GridH2QueryRequest.FLAG_REPLICATED);
 
-        int segments = explain || replicated ? 1 :
-            findFirstPartitioned(req.caches()).config().getQueryParallelism();
+        final List<Integer> cacheIds = req.caches();
+
+        int segments = explain || replicated || F.isEmpty(cacheIds) ? 1 :
+            findFirstPartitioned(cacheIds).config().getQueryParallelism();
 
         final Object[] params = req.parameters();
 
         for (int i = 1; i < segments; i++) {
+            assert !F.isEmpty(cacheIds);
+
             final int segment = i;
 
             ctx.closure().callLocal(
@@ -457,8 +463,9 @@ public class GridMapQueryExecutor {
                         onQueryRequest0(node,
                             req.requestId(),
                             segment,
+                            req.schemaName(),
                             req.queries(),
-                            req.caches(),
+                            cacheIds,
                             req.topologyVersion(),
                             partsMap,
                             parts,
@@ -466,7 +473,7 @@ public class GridMapQueryExecutor {
                             req.pageSize(),
                             joinMode,
                             enforceJoinOrder,
-                            replicated,
+                            false,
                             req.timeout(),
                             params);
 
@@ -479,8 +486,9 @@ public class GridMapQueryExecutor {
         onQueryRequest0(node,
             req.requestId(),
             0,
+            req.schemaName(),
             req.queries(),
-            req.caches(),
+            cacheIds,
             req.topologyVersion(),
             partsMap,
             parts,
@@ -497,6 +505,7 @@ public class GridMapQueryExecutor {
      * @param node Node authored request.
      * @param reqId Request ID.
      * @param segmentId index segment ID.
+     * @param schemaName Schema name.
      * @param qrys Queries to execute.
      * @param cacheIds Caches which will be affected by these queries.
      * @param topVer Topology version.
@@ -510,6 +519,7 @@ public class GridMapQueryExecutor {
         ClusterNode node,
         long reqId,
         int segmentId,
+        String schemaName,
         Collection<GridCacheSqlQuery> qrys,
         List<Integer> cacheIds,
         AffinityTopologyVersion topVer,
@@ -524,10 +534,8 @@ public class GridMapQueryExecutor {
         Object[] params
     ) {
         // Prepare to run queries.
-        GridCacheContext<?, ?> mainCctx = ctx.cache().context().cacheContext(cacheIds.get(0));
-
-        if (mainCctx == null)
-            throw new CacheException("Failed to find cache.");
+        GridCacheContext<?, ?> mainCctx =
+            !F.isEmpty(cacheIds) ? ctx.cache().context().cacheContext(cacheIds.get(0)) : null;
 
         NodeResults nodeRess = resultsForNode(node.id());
 
@@ -545,7 +553,7 @@ public class GridMapQueryExecutor {
                 }
             }
 
-            qr = new QueryResults(reqId, qrys.size(), mainCctx);
+            qr = new QueryResults(reqId, qrys.size(), mainCctx != null ? mainCctx.name() : null);
 
             if (nodeRess.put(reqId, segmentId, qr) != null)
                 throw new IllegalStateException();
@@ -579,8 +587,6 @@ public class GridMapQueryExecutor {
                 }
             }
 
-            String schemaName = h2.schema(mainCctx.name());
-
             Connection conn = h2.connectionForSchema(schemaName);
 
             H2Utils.setupConnection(conn, distributedJoinMode != OFF, enforceJoinOrder);
@@ -602,7 +608,7 @@ public class GridMapQueryExecutor {
                 // Run queries.
                 int qryIdx = 0;
 
-                boolean evt = ctx.event().isRecordable(EVT_CACHE_QUERY_EXECUTED);
+                boolean evt = mainCctx != null && ctx.event().isRecordable(EVT_CACHE_QUERY_EXECUTED);
 
                 for (GridCacheSqlQuery qry : qrys) {
                     ResultSet rs = null;
@@ -616,6 +622,8 @@ public class GridMapQueryExecutor {
                             qr.cancels[qryIdx]);
 
                         if (evt) {
+                            assert mainCctx != null;
+
                             ctx.event().record(new CacheQueryExecutedEvent<>(
                                 node,
                                 "SQL query executed.",
@@ -961,7 +969,7 @@ public class GridMapQueryExecutor {
         private final GridQueryCancel[] cancels;
 
         /** */
-        private final GridCacheContext<?,?> cctx;
+        private final String cacheName;
 
         /** */
         private volatile boolean canceled;
@@ -969,12 +977,12 @@ public class GridMapQueryExecutor {
         /**
          * @param qryReqId Query request ID.
          * @param qrys Number of queries.
-         * @param cctx Cache context.
+         * @param cacheName Cache name.
          */
         @SuppressWarnings("unchecked")
-        private QueryResults(long qryReqId, int qrys, GridCacheContext<?, ?> cctx) {
+        private QueryResults(long qryReqId, int qrys, @Nullable String cacheName) {
             this.qryReqId = qryReqId;
-            this.cctx = cctx;
+            this.cacheName = cacheName;
 
             results = new AtomicReferenceArray<>(qrys);
             cancels = new GridQueryCancel[qrys];
@@ -998,7 +1006,7 @@ public class GridMapQueryExecutor {
          * @param rs Result set.
          */
         void addResult(int qry, GridCacheSqlQuery q, UUID qrySrcNodeId, ResultSet rs, Object[] params) {
-            if (!results.compareAndSet(qry, null, new QueryResult(rs, cctx, qrySrcNodeId, q, params)))
+            if (!results.compareAndSet(qry, null, new QueryResult(rs, ctx, cacheName, qrySrcNodeId, q, params)))
                 throw new IllegalStateException();
         }
 
@@ -1054,8 +1062,11 @@ public class GridMapQueryExecutor {
         /** */
         private final ResultSet rs;
 
+        /** Kernal context. */
+        private final GridKernalContext ctx;
+
         /** */
-        private final GridCacheContext<?,?> cctx;
+        private final String cacheName;
 
         /** */
         private final GridCacheSqlQuery qry;
@@ -1083,18 +1094,20 @@ public class GridMapQueryExecutor {
 
         /**
          * @param rs Result set.
-         * @param cctx Cache context.
+         * @param ctx Kernal context.
+         * @param cacheName Cache name.
          * @param qrySrcNodeId Query source node.
          * @param qry Query.
          * @param params Query params.
          */
-        private QueryResult(ResultSet rs, GridCacheContext<?, ?> cctx, UUID qrySrcNodeId, GridCacheSqlQuery qry,
-            Object[] params) {
-            this.cctx = cctx;
+        private QueryResult(ResultSet rs, GridKernalContext ctx, @Nullable String cacheName,
+            UUID qrySrcNodeId, GridCacheSqlQuery qry, Object[] params) {
+            this.ctx = ctx;
+            this.cacheName = cacheName;
             this.qry = qry;
             this.params = params;
             this.qrySrcNodeId = qrySrcNodeId;
-            this.cpNeeded = cctx.isLocalNode(qrySrcNodeId);
+            this.cpNeeded = F.eq(ctx.localNodeId(), qrySrcNodeId);
 
             if (rs != null) {
                 this.rs = rs;
@@ -1127,7 +1140,7 @@ public class GridMapQueryExecutor {
             if (closed)
                 return true;
 
-            boolean readEvt = cctx.gridEvents().isRecordable(EVT_CACHE_QUERY_OBJECT_READ);
+            boolean readEvt = cacheName != null && ctx.event().isRecordable(EVT_CACHE_QUERY_OBJECT_READ);
 
             page++;
 
@@ -1163,12 +1176,12 @@ public class GridMapQueryExecutor {
                 assert row != null;
 
                 if (readEvt) {
-                    cctx.gridEvents().record(new CacheQueryReadEvent<>(
-                        cctx.localNode(),
+                    ctx.event().record(new CacheQueryReadEvent<>(
+                        ctx.discovery().localNode(),
                         "SQL fields query result set row read.",
                         EVT_CACHE_QUERY_OBJECT_READ,
                         CacheQueryType.SQL.name(),
-                        cctx.name(),
+                        cacheName,
                         null,
                         qry.query(),
                         null,

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a9c942b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
index 2d12635..f05fa5b 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
@@ -711,20 +711,20 @@ public class GridReduceQueryExecutor {
                 if (isReplicatedOnly)
                     flags |= GridH2QueryRequest.FLAG_REPLICATED;
 
-                if (send(nodes,
-                        new GridH2QueryRequest()
-                                .requestId(qryReqId)
-                                .topologyVersion(topVer)
-                                .pageSize(r.pageSize())
-                                .caches(qry.cacheIds())
-                                .tables(distributedJoins ? qry.tables() : null)
-                                .partitions(convert(partsMap))
-                                .queries(mapQrys)
-                                .parameters(params)
-                                .flags(flags)
-                                .timeout(timeoutMillis),
-                        parts == null ? null : new ExplicitPartitionsSpecializer(qryMap),
-                        false)) {
+                GridH2QueryRequest req = new GridH2QueryRequest()
+                    .requestId(qryReqId)
+                    .topologyVersion(topVer)
+                    .pageSize(r.pageSize())
+                    .caches(qry.cacheIds())
+                    .tables(distributedJoins ? qry.tables() : null)
+                    .partitions(convert(partsMap))
+                    .queries(mapQrys)
+                    .parameters(params)
+                    .flags(flags)
+                    .timeout(timeoutMillis)
+                    .schemaName(schemaName);
+
+                if (send(nodes, req, parts == null ? null : new ExplicitPartitionsSpecializer(qryMap), false)) {
                     awaitAllReplies(r, nodes, cancel);
 
                     Object state = r.state();

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a9c942b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2QueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2QueryRequest.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2QueryRequest.java
index beb1ae2..93a383c 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2QueryRequest.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2QueryRequest.java
@@ -125,6 +125,9 @@ public class GridH2QueryRequest implements Message, GridCacheQueryMarshallable {
     /** */
     private byte[] paramsBytes;
 
+    /** Schema name. */
+    private String schemaName;
+
     /**
      * Required by {@link Externalizable}
      */
@@ -148,6 +151,7 @@ public class GridH2QueryRequest implements Message, GridCacheQueryMarshallable {
         timeout = req.timeout;
         params = req.params;
         paramsBytes = req.paramsBytes;
+        schemaName = req.schemaName;
     }
 
     /**
@@ -343,6 +347,23 @@ public class GridH2QueryRequest implements Message, GridCacheQueryMarshallable {
         return this;
     }
 
+    /**
+     * @return Schema name.
+     */
+    public String schemaName() {
+        return schemaName;
+    }
+
+    /**
+     * @param schemaName Schema name.
+     * @return {@code this}.
+     */
+    public GridH2QueryRequest schemaName(String schemaName) {
+        this.schemaName = schemaName;
+
+        return this;
+    }
+
     /** {@inheritDoc} */
     @Override public void marshall(Marshaller m) {
         if (paramsBytes != null)
@@ -458,6 +479,12 @@ public class GridH2QueryRequest implements Message, GridCacheQueryMarshallable {
                     return false;
 
                 writer.incrementState();
+
+            case 11:
+                if (!writer.writeString("schemaName", schemaName))
+                    return false;
+
+                writer.incrementState();
         }
 
         return true;
@@ -559,6 +586,14 @@ public class GridH2QueryRequest implements Message, GridCacheQueryMarshallable {
                     return false;
 
                 reader.incrementState();
+
+            case 11:
+                schemaName = reader.readString("schemaName");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
         }
 
         return reader.afterMessageRead(GridH2QueryRequest.class);
@@ -571,7 +606,7 @@ public class GridH2QueryRequest implements Message, GridCacheQueryMarshallable {
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 11;
+        return 12;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a9c942b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
index 9c06900..d35030a 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
@@ -69,10 +69,14 @@ import org.apache.ignite.configuration.NearCacheConfiguration;
 import org.apache.ignite.events.CacheQueryExecutedEvent;
 import org.apache.ignite.events.CacheQueryReadEvent;
 import org.apache.ignite.events.Event;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.IgnitionEx;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
 import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQuerySelfTest;
 import org.apache.ignite.internal.processors.cache.query.QueryCursorEx;
 import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+import org.apache.ignite.internal.processors.query.GridQueryProcessor;
 import org.apache.ignite.internal.util.lang.GridPlainCallable;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.typedef.F;

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a9c942b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlPublicSchemaSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlPublicSchemaSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlPublicSchemaSelfTest.java
deleted file mode 100644
index cbd8972..0000000
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlPublicSchemaSelfTest.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.query;
-
-import org.apache.ignite.IgniteCache;
-import org.apache.ignite.cache.query.SqlFieldsQuery;
-import org.apache.ignite.cache.query.annotations.QuerySqlField;
-import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.internal.IgniteEx;
-import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-
-/**
- * Tests for public schema.
- */
-public class SqlPublicSchemaSelfTest extends GridCommonAbstractTest {
-    /** Person cache name. */
-    private static final String CACHE_PERSON = "PersonCache";
-
-    /** Person cache 2 name. */
-    private static final String CACHE_PERSON_2 = "PersonCache2";
-
-    /** Node. */
-    private IgniteEx node;
-
-    /** {@inheritDoc} */
-    @Override protected void beforeTest() throws Exception {
-        node = (IgniteEx)startGrid();
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void afterTest() throws Exception {
-        stopAllGrids();
-    }
-
-    /**
-     * Test simple query.
-     *
-     * @throws Exception If failed.
-     */
-    public void testSchemaChange() throws Exception {
-        IgniteCache<PersonKey, Person> cache = node.createCache(new CacheConfiguration<PersonKey, Person>()
-            .setName(CACHE_PERSON)
-            .setIndexedTypes(PersonKey.class, Person.class));
-
-        node.createCache(new CacheConfiguration<PersonKey, Person>()
-            .setName(CACHE_PERSON_2)
-            .setIndexedTypes(PersonKey.class, Person.class));
-
-        cache.put(new PersonKey(1), new Person("Vasya", 2));
-
-        // Normal calls.
-        assertEquals(1, cache.query(
-            new SqlFieldsQuery("SELECT id, name, orgId FROM Person")
-        ).getAll().size());
-
-        assertEquals(1, cache.query(
-            new SqlFieldsQuery("SELECT id, name, orgId FROM Person").setSchema(CACHE_PERSON)
-        ).getAll().size());
-
-        assertEquals(1, cache.query(
-            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PersonCache\".Person")
-        ).getAll().size());
-
-        // Call from default schema.
-        assertEquals(1, cache.query(
-            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PersonCache\".Person").setSchema(QueryUtils.DFLT_SCHEMA)
-        ).getAll().size());
-
-        // Call from another schema.
-        assertEquals(1, cache.query(
-            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PersonCache\".Person").setSchema(CACHE_PERSON_2)
-        ).getAll().size());
-    }
-
-    /**
-     * Test simple query.
-     *
-     * @throws Exception If failed.
-     */
-    public void testSchemaChangeOnCacheWithPublicSchema() throws Exception {
-        IgniteCache<PersonKey, Person> cache = node.createCache(new CacheConfiguration<PersonKey, Person>()
-            .setName(CACHE_PERSON)
-            .setIndexedTypes(PersonKey.class, Person.class)
-            .setSqlSchema(QueryUtils.DFLT_SCHEMA));
-
-        node.createCache(new CacheConfiguration<PersonKey, Person>()
-            .setName(CACHE_PERSON_2)
-            .setIndexedTypes(PersonKey.class, Person.class));
-
-        cache.put(new PersonKey(1), new Person("Vasya", 2));
-
-        // Normal calls.
-        assertEquals(1, cache.query(
-            new SqlFieldsQuery("SELECT id, name, orgId FROM Person")
-        ).getAll().size());
-
-        assertEquals(1, cache.query(
-            new SqlFieldsQuery("SELECT id, name, orgId FROM Person").setSchema(QueryUtils.DFLT_SCHEMA)
-        ).getAll().size());
-
-        // Call from another schema.
-        assertEquals(1, cache.query(
-            new SqlFieldsQuery("SELECT id, name, orgId FROM public.Person").setSchema(CACHE_PERSON_2)
-        ).getAll().size());
-
-        assertEquals(1, cache.query(
-            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PUBLIC\".Person").setSchema(CACHE_PERSON_2)
-        ).getAll().size());
-    }
-
-    /**
-     * Test type conflict in public schema.
-     *
-     * @throws Exception If failed.
-     */
-    public void _testTypeConflictInPublicSchema() throws Exception {
-        // TODO: IGNITE-5380: uncomment work after fix.
-        fail("Hang for now, need to fix");
-
-        node.createCache(new CacheConfiguration<PersonKey, Person>()
-            .setName(CACHE_PERSON)
-            .setIndexedTypes(PersonKey.class, Person.class)
-            .setSqlSchema(QueryUtils.DFLT_SCHEMA));
-
-        node.createCache(new CacheConfiguration<PersonKey, Person>()
-            .setName(CACHE_PERSON_2)
-            .setIndexedTypes(PersonKey.class, Person.class)
-            .setSqlSchema(QueryUtils.DFLT_SCHEMA));
-    }
-
-    /**
-     * Person key.
-     */
-    public static class PersonKey {
-        @QuerySqlField
-        public long id;
-
-        /**
-         * Constructor.
-         *
-         * @param id ID.
-         */
-        PersonKey(long id) {
-            this.id = id;
-        }
-
-        /** {@inheritDoc} */
-        @Override public int hashCode() {
-            return (int)id;
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean equals(Object obj) {
-            return obj != null && obj instanceof PersonKey && (F.eq(id, ((PersonKey)obj).id));
-        }
-    }
-
-    /**
-     * Person.
-     */
-    public static class Person {
-        /** Name. */
-        @QuerySqlField
-        public String name;
-
-        /** Organization ID. */
-        @QuerySqlField(index = true)
-        public long orgId;
-
-        /**
-         * Constructor.
-         *
-         * @param name Name.
-         * @param orgId Orgainzation ID.
-         */
-        public Person(String name, long orgId) {
-            this.name = name;
-            this.orgId = orgId;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a9c942b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSchemaSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSchemaSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSchemaSelfTest.java
new file mode 100644
index 0000000..32636fa
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSchemaSelfTest.java
@@ -0,0 +1,238 @@
+/*
+ * 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.processors.query;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import java.util.List;
+
+/**
+ * Tests for schemas.
+ */
+public class SqlSchemaSelfTest extends GridCommonAbstractTest {
+    /** Person cache name. */
+    private static final String CACHE_PERSON = "PersonCache";
+
+    /** Person cache 2 name. */
+    private static final String CACHE_PERSON_2 = "PersonCache2";
+
+    /** Node. */
+    private IgniteEx node;
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        node = (IgniteEx)startGrid();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * Test query without caches.
+     *
+     * @throws Exception If failed.
+     */
+    public void testQueryWithoutCacheOnPublicSchema() throws Exception {
+        GridQueryProcessor qryProc = node.context().query();
+
+        SqlFieldsQuery qry = new SqlFieldsQuery("SELECT 1").setSchema("PUBLIC");
+
+        List<List<?>> res = qryProc.querySqlFieldsNoCache(qry, true).getAll();
+
+        assertEquals(1, res.size());
+        assertEquals(1, res.get(0).size());
+        assertEquals(1, res.get(0).get(0));
+    }
+
+    /**
+     * Test query without caches.
+     *
+     * @throws Exception If failed.
+     */
+    public void testQueryWithoutCacheOnCacheSchema() throws Exception {
+        node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON)
+            .setIndexedTypes(PersonKey.class, Person.class));
+
+        GridQueryProcessor qryProc = node.context().query();
+
+        SqlFieldsQuery qry = new SqlFieldsQuery("SELECT 1").setSchema(CACHE_PERSON);
+
+        List<List<?>> res = qryProc.querySqlFieldsNoCache(qry, true).getAll();
+
+        assertEquals(1, res.size());
+        assertEquals(1, res.get(0).size());
+        assertEquals(1, res.get(0).get(0));
+    }
+
+    /**
+     * Test simple query.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSchemaChange() throws Exception {
+        IgniteCache<PersonKey, Person> cache = node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON)
+            .setIndexedTypes(PersonKey.class, Person.class));
+
+        node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON_2)
+            .setIndexedTypes(PersonKey.class, Person.class));
+
+        cache.put(new PersonKey(1), new Person("Vasya", 2));
+
+        // Normal calls.
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM Person")
+        ).getAll().size());
+
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM Person").setSchema(CACHE_PERSON)
+        ).getAll().size());
+
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PersonCache\".Person")
+        ).getAll().size());
+
+        // Call from default schema.
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PersonCache\".Person").setSchema(QueryUtils.DFLT_SCHEMA)
+        ).getAll().size());
+
+        // Call from another schema.
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PersonCache\".Person").setSchema(CACHE_PERSON_2)
+        ).getAll().size());
+    }
+
+    /**
+     * Test simple query.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSchemaChangeOnCacheWithPublicSchema() throws Exception {
+        IgniteCache<PersonKey, Person> cache = node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON)
+            .setIndexedTypes(PersonKey.class, Person.class)
+            .setSqlSchema(QueryUtils.DFLT_SCHEMA));
+
+        node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON_2)
+            .setIndexedTypes(PersonKey.class, Person.class));
+
+        cache.put(new PersonKey(1), new Person("Vasya", 2));
+
+        // Normal calls.
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM Person")
+        ).getAll().size());
+
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM Person").setSchema(QueryUtils.DFLT_SCHEMA)
+        ).getAll().size());
+
+        // Call from another schema.
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM public.Person").setSchema(CACHE_PERSON_2)
+        ).getAll().size());
+
+        assertEquals(1, cache.query(
+            new SqlFieldsQuery("SELECT id, name, orgId FROM \"PUBLIC\".Person").setSchema(CACHE_PERSON_2)
+        ).getAll().size());
+    }
+
+    /**
+     * Test type conflict in public schema.
+     *
+     * @throws Exception If failed.
+     */
+    public void _testTypeConflictInPublicSchema() throws Exception {
+        // TODO: IGNITE-5380: uncomment work after fix.
+        fail("Hang for now, need to fix");
+
+        node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON)
+            .setIndexedTypes(PersonKey.class, Person.class)
+            .setSqlSchema(QueryUtils.DFLT_SCHEMA));
+
+        node.createCache(new CacheConfiguration<PersonKey, Person>()
+            .setName(CACHE_PERSON_2)
+            .setIndexedTypes(PersonKey.class, Person.class)
+            .setSqlSchema(QueryUtils.DFLT_SCHEMA));
+    }
+
+    /**
+     * Person key.
+     */
+    public static class PersonKey {
+        @QuerySqlField
+        public long id;
+
+        /**
+         * Constructor.
+         *
+         * @param id ID.
+         */
+        PersonKey(long id) {
+            this.id = id;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return (int)id;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object obj) {
+            return obj != null && obj instanceof PersonKey && (F.eq(id, ((PersonKey)obj).id));
+        }
+    }
+
+    /**
+     * Person.
+     */
+    public static class Person {
+        /** Name. */
+        @QuerySqlField
+        public String name;
+
+        /** Organization ID. */
+        @QuerySqlField(index = true)
+        public long orgId;
+
+        /**
+         * Constructor.
+         *
+         * @param name Name.
+         * @param orgId Orgainzation ID.
+         */
+        public Person(String name, long orgId) {
+            this.name = name;
+            this.orgId = orgId;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a9c942b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
index 848ab49..fb6a86b 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
@@ -97,7 +97,6 @@ import org.apache.ignite.internal.processors.cache.index.DynamicIndexServerNodeF
 import org.apache.ignite.internal.processors.cache.index.DynamicIndexServerNodeFilterCoordinatorBasicSelfTest;
 import org.apache.ignite.internal.processors.cache.index.DynamicIndexServerBasicSelfTest;
 import org.apache.ignite.internal.processors.cache.index.H2DynamicTableSelfTest;
-import org.apache.ignite.internal.processors.cache.index.QueryEntityValidationSelfTest;
 import org.apache.ignite.internal.processors.cache.index.SchemaExchangeSelfTest;
 import org.apache.ignite.internal.processors.cache.local.IgniteCacheLocalAtomicQuerySelfTest;
 import org.apache.ignite.internal.processors.cache.local.IgniteCacheLocalFieldsQuerySelfTest;
@@ -115,7 +114,7 @@ import org.apache.ignite.internal.processors.query.IgniteSqlSchemaIndexingTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexMultiNodeSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSplitterSelfTest;
-import org.apache.ignite.internal.processors.query.SqlPublicSchemaSelfTest;
+import org.apache.ignite.internal.processors.query.SqlSchemaSelfTest;
 import org.apache.ignite.internal.processors.query.h2.GridH2IndexingInMemSelfTest;
 import org.apache.ignite.internal.processors.query.h2.GridH2IndexingOffheapSelfTest;
 import org.apache.ignite.internal.processors.query.h2.IgniteSqlQueryMinMaxTest;
@@ -137,7 +136,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
     public static TestSuite suite() throws Exception {
         IgniteTestSuite suite = new IgniteTestSuite("Ignite Cache Queries Test Suite");
 
-        suite.addTestSuite(SqlPublicSchemaSelfTest.class);
+        suite.addTestSuite(SqlSchemaSelfTest.class);
 
         // Misc tests.
         // TODO: Enable when IGNITE-1094 is fixed.


[36/50] [abbrv] ignite git commit: IGNITE-5397: Fixed another issue causing failures on query execution without caches.

Posted by sb...@apache.org.
IGNITE-5397: Fixed another issue causing failures on query execution without caches.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/1ed088c2
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/1ed088c2
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/1ed088c2

Branch: refs/heads/ignite-5075
Commit: 1ed088c2874345b42bdd97546e94c25657cf00ee
Parents: 1d0b076
Author: devozerov <vo...@gridgain.com>
Authored: Mon Jun 5 15:29:24 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Mon Jun 5 15:29:24 2017 +0300

----------------------------------------------------------------------
 .../cache/query/GridCacheTwoStepQuery.java      |  1 +
 .../processors/query/SqlSchemaSelfTest.java     | 25 ++++++++++++++++++++
 2 files changed, 26 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1ed088c2/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
index 24958af..4a93aaf 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
@@ -240,6 +240,7 @@ public class GridCacheTwoStepQuery {
         cp.pageSize = pageSize;
         cp.distributedJoins = distributedJoins;
         cp.derivedPartitions = derivedPartitions;
+        cp.local = local;
 
         for (int i = 0; i < mapQrys.size(); i++)
             cp.mapQrys.add(mapQrys.get(i).copy());

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ed088c2/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSchemaSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSchemaSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSchemaSelfTest.java
index 32636fa..8aaccef 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSchemaSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSchemaSelfTest.java
@@ -25,6 +25,7 @@ import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -43,6 +44,8 @@ public class SqlSchemaSelfTest extends GridCommonAbstractTest {
     /** {@inheritDoc} */
     @Override protected void beforeTest() throws Exception {
         node = (IgniteEx)startGrid();
+
+        startGrid(2);
     }
 
     /** {@inheritDoc} */
@@ -65,6 +68,17 @@ public class SqlSchemaSelfTest extends GridCommonAbstractTest {
         assertEquals(1, res.size());
         assertEquals(1, res.get(0).size());
         assertEquals(1, res.get(0).get(0));
+
+        Iterator<List<?>> iter = qryProc.querySqlFieldsNoCache(qry, true).iterator();
+
+        assertTrue(iter.hasNext());
+
+        List<?> row = iter.next();
+
+        assertEquals(1, row.size());
+        assertEquals(1, row.get(0));
+
+        assertFalse(iter.hasNext());
     }
 
     /**
@@ -86,6 +100,17 @@ public class SqlSchemaSelfTest extends GridCommonAbstractTest {
         assertEquals(1, res.size());
         assertEquals(1, res.get(0).size());
         assertEquals(1, res.get(0).get(0));
+
+        Iterator<List<?>> iter = qryProc.querySqlFieldsNoCache(qry, true).iterator();
+
+        assertTrue(iter.hasNext());
+
+        List<?> row = iter.next();
+
+        assertEquals(1, row.size());
+        assertEquals(1, row.get(0));
+
+        assertFalse(iter.hasNext());
     }
 
     /**


[07/50] [abbrv] ignite git commit: IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
new file mode 100644
index 0000000..b319293
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
@@ -0,0 +1,285 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequestHandler;
+import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
+import org.apache.ignite.internal.util.GridSpinBusyLock;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.QRY_CLOSE;
+import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.QRY_EXEC;
+import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.QRY_FETCH;
+import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.QRY_META;
+
+/**
+ * SQL query handler.
+ */
+public class JdbcRequestHandler implements SqlListenerRequestHandler {
+    /** Query ID sequence. */
+    private static final AtomicLong QRY_ID_GEN = new AtomicLong();
+
+    /** Kernel context. */
+    private final GridKernalContext ctx;
+
+    /** Logger. */
+    private final IgniteLogger log;
+
+    /** Busy lock. */
+    private final GridSpinBusyLock busyLock;
+
+    /** Maximum allowed cursors. */
+    private final int maxCursors;
+
+    /** Current queries cursors. */
+    private final ConcurrentHashMap<Long, JdbcQueryCursor> qryCursors = new ConcurrentHashMap<>();
+
+    /** Distributed joins flag. */
+    private final boolean distributedJoins;
+
+    /** Enforce join order flag. */
+    private final boolean enforceJoinOrder;
+
+    /**
+     * Constructor.
+     *
+     * @param ctx Context.
+     * @param busyLock Shutdown latch.
+     * @param maxCursors Maximum allowed cursors.
+     * @param distributedJoins Distributed joins flag.
+     * @param enforceJoinOrder Enforce join order flag.
+     */
+    public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int maxCursors,
+        boolean distributedJoins, boolean enforceJoinOrder) {
+        this.ctx = ctx;
+        this.busyLock = busyLock;
+        this.maxCursors = maxCursors;
+        this.distributedJoins = distributedJoins;
+        this.enforceJoinOrder = enforceJoinOrder;
+
+        log = ctx.log(getClass());
+    }
+
+    /** {@inheritDoc} */
+    @Override public SqlListenerResponse handle(SqlListenerRequest req0) {
+        assert req0 != null;
+
+        assert req0 instanceof JdbcRequest;
+
+        JdbcRequest req = (JdbcRequest)req0;
+
+        if (!busyLock.enterBusy())
+            return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, 
+                "Failed to handle JDBC request because node is stopping.");
+
+        try {
+            switch (req.type()) {
+                case QRY_EXEC:
+                    return executeQuery((JdbcQueryExecuteRequest)req);
+
+                case QRY_FETCH:
+                    return fetchQuery((JdbcQueryFetchRequest)req);
+
+                case QRY_CLOSE:
+                    return closeQuery((JdbcQueryCloseRequest)req);
+
+                case QRY_META:
+                    return getQueryMeta((JdbcQueryMetadataRequest)req);
+            }
+
+            return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, "Unsupported JDBC request [req=" + req + ']');
+        }
+        finally {
+            busyLock.leaveBusy();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public SqlListenerResponse handleException(Exception e) {
+        return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+    }
+
+    /**
+     * {@link JdbcQueryExecuteRequest} command handler.
+     *
+     * @param req Execute query request.
+     * @return Response.
+     */
+    @SuppressWarnings("unchecked")
+    private JdbcResponse executeQuery(JdbcQueryExecuteRequest req) {
+        int cursorCnt = qryCursors.size();
+
+        if (maxCursors > 0 && cursorCnt >= maxCursors)
+            return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, "Too many opened cursors (either close other " +
+                "opened cursors or increase the limit through OdbcConfiguration.setMaxOpenCursors()) " +
+                "[maximum=" + maxCursors + ", current=" + cursorCnt + ']');
+
+        long qryId = QRY_ID_GEN.getAndIncrement();
+
+        try {
+            String sql = req.sqlQuery();
+
+            SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+            qry.setArgs(req.arguments());
+
+            qry.setDistributedJoins(distributedJoins);
+            qry.setEnforceJoinOrder(enforceJoinOrder);
+
+            if (req.pageSize() <= 0)
+                return new JdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Invalid fetch size : [fetchSize=" + req.pageSize() + ']');
+
+            qry.setPageSize(req.pageSize());
+
+            IgniteCache<Object, Object> cache0 = ctx.grid().cache(req.schemaName());
+
+            if (cache0 == null)
+                return new JdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Cache doesn't exist (did you configure it?): " + req.schemaName());
+
+            IgniteCache<Object, Object> cache = cache0.withKeepBinary();
+
+            if (cache == null)
+                return new JdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Can not get cache with keep binary: " + req.schemaName());
+
+            JdbcQueryCursor cur = new JdbcQueryCursor(
+                qryId, req.pageSize(), req.maxRows(), (QueryCursorImpl)cache.query(qry));
+
+            qryCursors.put(qryId, cur);
+
+            JdbcQueryExecuteResult res;
+
+            if (cur.isQuery())
+                res = new JdbcQueryExecuteResult(qryId, cur.fetchRows(), !cur.hasNext());
+            else {
+                List<List<Object>> items = cur.fetchRows();
+
+                assert items != null && items.size() == 1 && items.get(0).size() == 1
+                    && items.get(0).get(0) instanceof Long :
+                    "Invalid result set for not-SELECT query. [qry=" + sql +
+                        ", res=" + S.toString(List.class, items) + ']';
+
+                res = new JdbcQueryExecuteResult(qryId, (Long)items.get(0).get(0));
+            }
+
+            return new JdbcResponse(res);
+        }
+        catch (Exception e) {
+            qryCursors.remove(qryId);
+
+            U.error(log, "Failed to execute SQL query [reqId=" + req.requestId() + ", req=" + req + ']', e);
+
+            return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+        }
+    }
+
+    /**
+     * {@link JdbcQueryCloseRequest} command handler.
+     *
+     * @param req Execute query request.
+     * @return Response.
+     */
+    private JdbcResponse closeQuery(JdbcQueryCloseRequest req) {
+        try {
+            JdbcQueryCursor cur = qryCursors.remove(req.queryId());
+
+            if (cur == null)
+                return new JdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Failed to find query cursor with ID: " + req.queryId());
+
+            cur.close();
+
+            return new JdbcResponse(null);
+        }
+        catch (Exception e) {
+            qryCursors.remove(req.queryId());
+
+            U.error(log, "Failed to close SQL query [reqId=" + req.requestId() + ", req=" + req.queryId() + ']', e);
+
+            return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+        }
+    }
+
+    /**
+     * {@link JdbcQueryFetchRequest} command handler.
+     *
+     * @param req Execute query request.
+     * @return Response.
+     */
+    private JdbcResponse fetchQuery(JdbcQueryFetchRequest req) {
+        try {
+            JdbcQueryCursor cur = qryCursors.get(req.queryId());
+
+            if (cur == null)
+                return new JdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Failed to find query cursor with ID: " + req.queryId());
+
+            if (req.pageSize() <= 0)
+                return new JdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Invalid fetch size : [fetchSize=" + req.pageSize() + ']');
+
+            cur.pageSize(req.pageSize());
+
+            JdbcQueryFetchResult res = new JdbcQueryFetchResult(cur.fetchRows(), !cur.hasNext());
+
+            return new JdbcResponse(res);
+        }
+        catch (Exception e) {
+            U.error(log, "Failed to fetch SQL query result [reqId=" + req.requestId() + ", req=" + req + ']', e);
+
+            return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+        }
+    }
+
+    /**
+     * @param req Request.
+     * @return Response.
+     */
+    private JdbcResponse getQueryMeta(JdbcQueryMetadataRequest req) {
+        try {
+            JdbcQueryCursor cur = qryCursors.get(req.queryId());
+
+            if (cur == null)
+                return new JdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Failed to find query with ID: " + req.queryId());
+
+            JdbcQueryMetadataResult res = new JdbcQueryMetadataResult(req.queryId(),
+                cur.meta());
+
+            return new JdbcResponse(res);
+        }
+        catch (Exception e) {
+            U.error(log, "Failed to fetch SQL query result [reqId=" + req.requestId() + ", req=" + req + ']', e);
+
+            return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java
new file mode 100644
index 0000000..f039db7
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java
@@ -0,0 +1,104 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * SQL listener response.
+ */
+public class JdbcResponse extends SqlListenerResponse implements JdbcRawBinarylizable {
+    /** Response object. */
+    @GridToStringInclude
+    private JdbcResult res;
+
+    /**
+     * Default constructs is used for deserialization
+     */
+    public JdbcResponse() {
+        super(-1, null);
+    }
+
+    /**
+     * Constructs successful rest response.
+     *
+     * @param res Response result.
+     */
+    public JdbcResponse(JdbcResult res) {
+        super(STATUS_SUCCESS, null);
+
+        this.res = res;
+    }
+
+    /**
+     * Constructs failed rest response.
+     *
+     * @param status Response status.
+     * @param err Error, {@code null} if success is {@code true}.
+     */
+    public JdbcResponse(int status, @Nullable String err) {
+        super(status, err);
+
+        assert status != STATUS_SUCCESS;
+    }
+
+    /**
+     * @return Response object.
+     */
+    public JdbcResult response() {
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcResponse.class, this, "status", status(),"err", error());
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        writer.writeInt(status());
+
+        if (status() == STATUS_SUCCESS) {
+            writer.writeBoolean(res != null);
+
+            if (res != null)
+                res.writeBinary(writer);
+        }
+        else
+            writer.writeString(error());
+
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        status(reader.readInt());
+
+        if (status() == STATUS_SUCCESS) {
+            if (reader.readBoolean())
+                res = JdbcResult.readResult(reader);
+        }
+        else
+            error(reader.readString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java
new file mode 100644
index 0000000..2d7666e
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc.jdbc;
+
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+
+/**
+ * SQL listener response.
+ */
+public class JdbcResult implements JdbcRawBinarylizable {
+    /** Execute sql result. */
+    public static final byte QRY_EXEC = 2;
+
+    /** Fetch query results. */
+    public static final byte QRY_FETCH = 3;
+
+    /** Get columns meta query result. */
+    public static final byte QRY_META = 4;
+
+    /** Success status. */
+    private byte type;
+
+    /**
+     * Constructs result.
+     *
+     * @param type Type of results.
+     */
+    public JdbcResult(byte type) {
+        this.type = type;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        writer.writeByte(type);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        // No-op.
+    }
+
+    /**
+     * @param reader Binary reader.
+     * @return Request object.
+     * @throws BinaryObjectException On error.
+     */
+    public static JdbcResult readResult(BinaryReaderExImpl reader) throws BinaryObjectException {
+        int resId = reader.readByte();
+
+        JdbcResult res;
+
+        switch(resId) {
+            case QRY_EXEC:
+                res = new JdbcQueryExecuteResult();
+                break;
+
+            case QRY_FETCH:
+                res = new JdbcQueryFetchResult();
+                break;
+
+            case QRY_META:
+                res = new JdbcQueryMetadataResult();
+                break;
+
+            default:
+                throw new IgniteException("Unknown SQL listener request ID: [request ID=" + resId + ']');
+        }
+
+        res.readBinary(reader);
+
+        return res;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcUtils.java
new file mode 100644
index 0000000..65efbf5
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcUtils.java
@@ -0,0 +1,73 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.processors.odbc.SqlListenerUtils;
+
+/**
+ * Various JDBC utility methods.
+ */
+public class JdbcUtils {
+    /**
+     * @param writer Binari writer.
+     * @param items Query results items.
+     */
+    public static void writeItems(BinaryWriterExImpl writer, List<List<Object>> items) {
+        writer.writeInt(items.size());
+
+        for (List<Object> row : items) {
+            if (row != null) {
+                writer.writeInt(row.size());
+
+                for (Object obj : row)
+                    SqlListenerUtils.writeObject(writer, obj, false);
+            }
+        }
+    }
+
+    /**
+     * @param reader Binary reader.
+     * @return Query results items.
+     */
+    public static List<List<Object>> readItems(BinaryReaderExImpl reader) {
+        int rowsSize = reader.readInt();
+
+        if (rowsSize > 0) {
+            List<List<Object>> items = new ArrayList<>(rowsSize);
+
+            for (int i = 0; i < rowsSize; ++i) {
+                int colsSize = reader.readInt();
+
+                List<Object> col = new ArrayList<>(colsSize);
+
+                for (int colCnt = 0; colCnt < colsSize; ++colCnt)
+                    col.add(SqlListenerUtils.readObject(reader, false));
+
+                items.add(col);
+            }
+
+            return items;
+        } else
+            return Collections.emptyList();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcColumnMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcColumnMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcColumnMeta.java
new file mode 100644
index 0000000..d9d39de
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcColumnMeta.java
@@ -0,0 +1,111 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.internal.binary.BinaryUtils;
+import org.apache.ignite.internal.processors.odbc.OdbcUtils;
+import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+
+/**
+ * SQL listener column metadata.
+ */
+public class OdbcColumnMeta {
+    /** Cache name. */
+    private final String schemaName;
+
+    /** Table name. */
+    private final String tableName;
+
+    /** Column name. */
+    private final String columnName;
+
+    /** Data type. */
+    private final Class<?> dataType;
+
+    /**
+     * @param schemaName Cache name.
+     * @param tableName Table name.
+     * @param columnName Column name.
+     * @param dataType Data type.
+     */
+    public OdbcColumnMeta(String schemaName, String tableName, String columnName, Class<?> dataType) {
+        this.schemaName = OdbcUtils.addQuotationMarksIfNeeded(schemaName);
+        this.tableName = tableName;
+        this.columnName = columnName;
+        this.dataType = dataType;
+    }
+
+    /**
+     * @param info Field metadata.
+     */
+    public OdbcColumnMeta(GridQueryFieldMetadata info) {
+        this.schemaName = OdbcUtils.addQuotationMarksIfNeeded(info.schemaName());
+        this.tableName = info.typeName();
+        this.columnName = info.fieldName();
+
+        Class<?> type;
+
+        try {
+            type = Class.forName(info.fieldTypeName());
+        }
+        catch (Exception ignored) {
+            type = Object.class;
+        }
+
+        this.dataType = type;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int hash = schemaName.hashCode();
+
+        hash = 31 * hash + tableName.hashCode();
+        hash = 31 * hash + columnName.hashCode();
+        hash = 31 * hash + dataType.hashCode();
+
+        return hash;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (o instanceof OdbcColumnMeta) {
+            OdbcColumnMeta other = (OdbcColumnMeta) o;
+
+            return this == other || schemaName.equals(other.schemaName) && tableName.equals(other.tableName) &&
+                columnName.equals(other.columnName) && dataType.equals(other.dataType);
+        }
+
+        return false;
+    }
+
+    /**
+     * Write in a binary format.
+     *
+     * @param writer Binary writer.
+     */
+    public void write(BinaryRawWriter writer) {
+        writer.writeString(schemaName);
+        writer.writeString(tableName);
+        writer.writeString(columnName);
+
+        byte typeId = BinaryUtils.typeByClass(dataType);
+
+        writer.writeByte(typeId);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
index 300385f..02e8676 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
@@ -17,7 +17,9 @@
 
 package org.apache.ignite.internal.processors.odbc.odbc;
 
+import java.util.Collection;
 import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.binary.BinaryReaderExImpl;
 import org.apache.ignite.internal.binary.BinaryThreadLocalContext;
@@ -27,20 +29,34 @@ import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream;
 import org.apache.ignite.internal.binary.streams.BinaryHeapOutputStream;
 import org.apache.ignite.internal.binary.streams.BinaryInputStream;
 import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
-import org.apache.ignite.internal.processors.odbc.SqlListenerAbstractMessageParser;
+import org.apache.ignite.internal.processors.odbc.SqlListenerMessageParser;
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
+import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
+import org.apache.ignite.internal.processors.odbc.SqlListenerUtils;
 
 /**
  * JDBC message parser.
  */
-public class OdbcMessageParser extends SqlListenerAbstractMessageParser {
+public class OdbcMessageParser implements SqlListenerMessageParser {
     /** Marshaller. */
     private final GridBinaryMarshaller marsh;
 
+    /** Initial output stream capacity. */
+    protected static final int INIT_CAP = 1024;
+
+    /** Kernal context. */
+    protected GridKernalContext ctx;
+
+    /** Logger. */
+    private final IgniteLogger log;
+
     /**
      * @param ctx Context.
      */
     public OdbcMessageParser(GridKernalContext ctx) {
-        super(ctx, new OdbcObjectReader(), new OdbcObjectWriter());
+        this.ctx = ctx;
+
+        log = ctx.log(getClass());
 
         if (ctx.cacheObjects() instanceof CacheObjectBinaryProcessorImpl) {
             CacheObjectBinaryProcessorImpl cacheObjProc = (CacheObjectBinaryProcessorImpl)ctx.cacheObjects();
@@ -54,15 +70,198 @@ public class OdbcMessageParser extends SqlListenerAbstractMessageParser {
     }
 
     /** {@inheritDoc} */
-    @Override protected BinaryReaderExImpl createReader(byte[] msg) {
+    @Override public SqlListenerRequest decode(byte[] msg) {
+        assert msg != null;
+
         BinaryInputStream stream = new BinaryHeapInputStream(msg);
 
-        return new BinaryReaderExImpl(marsh.context(), stream, ctx.config().getClassLoader(), true);
+        BinaryReaderExImpl reader = new BinaryReaderExImpl(marsh.context(), stream, ctx.config().getClassLoader(), true);
+
+        byte cmd = reader.readByte();
+
+        SqlListenerRequest res;
+
+        switch (cmd) {
+            case OdbcRequest.QRY_EXEC: {
+                String cache = reader.readString();
+                String sql = reader.readString();
+                int argsNum = reader.readInt();
+
+                Object[] params = new Object[argsNum];
+
+                for (int i = 0; i < argsNum; ++i)
+                    params[i] = SqlListenerUtils.readObject(reader, true);
+
+                res = new OdbcQueryExecuteRequest(cache, sql, params);
+
+                break;
+            }
+
+            case OdbcRequest.QRY_FETCH: {
+                long queryId = reader.readLong();
+                int pageSize = reader.readInt();
+
+                res = new OdbcQueryFetchRequest(queryId, pageSize);
+
+                break;
+            }
+
+            case OdbcRequest.QRY_CLOSE: {
+                long queryId = reader.readLong();
+
+                res = new OdbcQueryCloseRequest(queryId);
+
+                break;
+            }
+
+            case OdbcRequest.META_COLS: {
+                String cache = reader.readString();
+                String table = reader.readString();
+                String column = reader.readString();
+
+                res = new OdbcQueryGetColumnsMetaRequest(cache, table, column);
+
+                break;
+            }
+
+            case OdbcRequest.META_TBLS: {
+                String catalog = reader.readString();
+                String schema = reader.readString();
+                String table = reader.readString();
+                String tableType = reader.readString();
+
+                res = new OdbcQueryGetTablesMetaRequest(catalog, schema, table, tableType);
+
+                break;
+            }
+
+            case OdbcRequest.META_PARAMS: {
+                String cacheName = reader.readString();
+                String sqlQuery = reader.readString();
+
+                res = new OdbcQueryGetParamsMetaRequest(cacheName, sqlQuery);
+
+                break;
+            }
+
+            default:
+                throw new IgniteException("Unknown ODBC command: [cmd=" + cmd + ']');
+        }
+
+        return res;
     }
 
     /** {@inheritDoc} */
-    @Override protected BinaryWriterExImpl createWriter(int cap) {
-        return new BinaryWriterExImpl(marsh.context(), new BinaryHeapOutputStream(cap),
+    @Override public byte[] encode(SqlListenerResponse msg0) {
+        assert msg0 != null;
+
+        assert msg0 instanceof OdbcResponse;
+
+        OdbcResponse msg = (OdbcResponse)msg0;
+
+        // Creating new binary writer
+        BinaryWriterExImpl writer = new BinaryWriterExImpl(marsh.context(), new BinaryHeapOutputStream(INIT_CAP),
             BinaryThreadLocalContext.get().schemaHolder(), null);
+
+        // Writing status.
+        writer.writeByte((byte) msg.status());
+
+        if (msg.status() != SqlListenerResponse.STATUS_SUCCESS) {
+            writer.writeString(msg.error());
+
+            return writer.array();
+        }
+
+        Object res0 = msg.response();
+
+        if (res0 == null)
+            return writer.array();
+        else if (res0 instanceof OdbcQueryExecuteResult) {
+            OdbcQueryExecuteResult res = (OdbcQueryExecuteResult) res0;
+
+            if (log.isDebugEnabled())
+                log.debug("Resulting query ID: " + res.getQueryId());
+
+            writer.writeLong(res.getQueryId());
+
+            Collection<OdbcColumnMeta> metas = res.getColumnsMetadata();
+
+            assert metas != null;
+
+            writer.writeInt(metas.size());
+
+            for (OdbcColumnMeta meta : metas)
+                meta.write(writer);
+        }
+        else if (res0 instanceof OdbcQueryFetchResult) {
+            OdbcQueryFetchResult res = (OdbcQueryFetchResult) res0;
+
+            if (log.isDebugEnabled())
+                log.debug("Resulting query ID: " + res.queryId());
+
+            writer.writeLong(res.queryId());
+
+            Collection<?> items0 = res.items();
+
+            assert items0 != null;
+
+            writer.writeBoolean(res.last());
+
+            writer.writeInt(items0.size());
+
+            for (Object row0 : items0) {
+                if (row0 != null) {
+                    Collection<?> row = (Collection<?>)row0;
+
+                    writer.writeInt(row.size());
+
+                    for (Object obj : row)
+                        SqlListenerUtils.writeObject(writer, obj, true);
+                }
+            }
+        }
+        else if (res0 instanceof OdbcQueryCloseResult) {
+            OdbcQueryCloseResult res = (OdbcQueryCloseResult) res0;
+
+            if (log.isDebugEnabled())
+                log.debug("Resulting query ID: " + res.getQueryId());
+
+            writer.writeLong(res.getQueryId());
+        }
+        else if (res0 instanceof OdbcQueryGetColumnsMetaResult) {
+            OdbcQueryGetColumnsMetaResult res = (OdbcQueryGetColumnsMetaResult) res0;
+
+            Collection<OdbcColumnMeta> columnsMeta = res.meta();
+
+            assert columnsMeta != null;
+
+            writer.writeInt(columnsMeta.size());
+
+            for (OdbcColumnMeta columnMeta : columnsMeta)
+                columnMeta.write(writer);
+        }
+        else if (res0 instanceof OdbcQueryGetTablesMetaResult) {
+            OdbcQueryGetTablesMetaResult res = (OdbcQueryGetTablesMetaResult) res0;
+
+            Collection<OdbcTableMeta> tablesMeta = res.meta();
+
+            assert tablesMeta != null;
+
+            writer.writeInt(tablesMeta.size());
+
+            for (OdbcTableMeta tableMeta : tablesMeta)
+                tableMeta.writeBinary(writer);
+        }
+        else if (res0 instanceof OdbcQueryGetParamsMetaResult) {
+            OdbcQueryGetParamsMetaResult res = (OdbcQueryGetParamsMetaResult) res0;
+
+            byte[] typeIds = res.typeIds();
+
+            SqlListenerUtils.writeObject(writer, typeIds, true);
+        }
+        else
+            assert false : "Should not reach here.";
+
+        return writer.array();
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcObjectReader.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcObjectReader.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcObjectReader.java
deleted file mode 100644
index 586fbc5..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcObjectReader.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc.odbc;
-
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.internal.binary.BinaryReaderExImpl;
-import org.apache.ignite.internal.processors.odbc.SqlListenerAbstractObjectReader;
-
-/**
- * Binary reader with marshaling non-primitive and non-embedded objects with JDK marshaller.
- */
-@SuppressWarnings("unchecked")
-public class OdbcObjectReader extends SqlListenerAbstractObjectReader {
-    /** {@inheritDoc} */
-    @Override protected Object readCustomObject(BinaryReaderExImpl reader) throws BinaryObjectException {
-        return reader.readObjectDetached();
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcObjectWriter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcObjectWriter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcObjectWriter.java
deleted file mode 100644
index c2f3aba..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcObjectWriter.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc.odbc;
-
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.internal.binary.BinaryWriterExImpl;
-import org.apache.ignite.internal.processors.odbc.SqlListenerAbstractObjectWriter;
-
-/**
- * Binary writer with marshaling non-primitive and non-embedded objects with JDK marshaller..
- */
-public class OdbcObjectWriter extends SqlListenerAbstractObjectWriter {
-    /** {@inheritDoc} */
-    @Override protected void writeCustomObject(BinaryWriterExImpl writer, Object obj) throws BinaryObjectException {
-        writer.writeObjectDetached(obj);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryCloseRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryCloseRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryCloseRequest.java
new file mode 100644
index 0000000..a9decb7
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryCloseRequest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * SQL listener query close request.
+ */
+public class OdbcQueryCloseRequest extends OdbcRequest {
+    /** Query ID. */
+    private final long queryId;
+
+    /**
+     * @param queryId Query ID.
+     */
+    public OdbcQueryCloseRequest(long queryId) {
+        super(QRY_CLOSE);
+
+        this.queryId = queryId;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(OdbcQueryCloseRequest.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryCloseResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryCloseResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryCloseResult.java
new file mode 100644
index 0000000..eb156fa
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryCloseResult.java
@@ -0,0 +1,40 @@
+/*
+ * 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.processors.odbc.odbc;
+
+/**
+ * SQL listener query close result.
+ */
+public class OdbcQueryCloseResult {
+    /** Query ID. */
+    private final long queryId;
+
+    /**
+     * @param queryId Query ID.
+     */
+    public OdbcQueryCloseResult(long queryId){
+        this.queryId = queryId;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long getQueryId() {
+        return queryId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
new file mode 100644
index 0000000..dd674d2
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import org.apache.ignite.internal.util.tostring.GridToStringExclude;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * SQL listener query execute request.
+ */
+public class OdbcQueryExecuteRequest extends OdbcRequest {
+    /** Cache name. */
+    private final String cacheName;
+
+    /** Sql query. */
+    @GridToStringInclude(sensitive = true)
+    private final String sqlQry;
+
+    /** Sql query arguments. */
+    @GridToStringExclude
+    private final Object[] args;
+
+    /**
+     * @param cacheName Cache name.
+     * @param sqlQry SQL query.
+     * @param args Arguments list.
+     */
+    public OdbcQueryExecuteRequest(String cacheName, String sqlQry, Object[] args) {
+        super(QRY_EXEC);
+
+        this.cacheName = cacheName.isEmpty() ? null : cacheName;
+        this.sqlQry = sqlQry;
+        this.args = args;
+    }
+
+    /**
+     * @return Sql query.
+     */
+    public String sqlQuery() {
+        return sqlQry;
+    }
+
+    /**
+     * @return Sql query arguments.
+     */
+    public Object[] arguments() {
+        return args;
+    }
+
+    /**
+     * @return Cache name.
+     */
+    @Nullable public String cacheName() {
+        return cacheName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(OdbcQueryExecuteRequest.class, this, "args", args, true);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java
new file mode 100644
index 0000000..de5a8fd
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java
@@ -0,0 +1,54 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import java.util.Collection;
+
+/**
+ * SQL listener query execute result.
+ */
+public class OdbcQueryExecuteResult {
+    /** Query ID. */
+    private final long queryId;
+
+    /** Fields metadata. */
+    private final Collection<OdbcColumnMeta> columnsMeta;
+
+    /**
+     * @param queryId Query ID.
+     * @param columnsMeta Columns metadata.
+     */
+    public OdbcQueryExecuteResult(long queryId, Collection<OdbcColumnMeta> columnsMeta) {
+        this.queryId = queryId;
+        this.columnsMeta = columnsMeta;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long getQueryId() {
+        return queryId;
+    }
+
+    /**
+     * @return Columns metadata.
+     */
+    public Collection<OdbcColumnMeta> getColumnsMetadata() {
+        return columnsMeta;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryFetchRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryFetchRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryFetchRequest.java
new file mode 100644
index 0000000..190fffd
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryFetchRequest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * SQL listener query fetch request.
+ */
+public class OdbcQueryFetchRequest extends OdbcRequest {
+    /** Query ID. */
+    private final long queryId;
+
+    /** Page size - maximum number of rows to return. */
+    private final int pageSize;
+
+    /**
+     * @param queryId Query ID.
+     * @param pageSize Page size.
+     */
+    public OdbcQueryFetchRequest(long queryId, int pageSize) {
+        super(QRY_FETCH);
+
+        this.queryId = queryId;
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * @return Page size.
+     */
+    public int pageSize() {
+        return pageSize;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(OdbcQueryFetchRequest.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryFetchResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryFetchResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryFetchResult.java
new file mode 100644
index 0000000..f8075f3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryFetchResult.java
@@ -0,0 +1,66 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import java.util.Collection;
+
+/**
+ * SQL listener query fetch result.
+ */
+public class OdbcQueryFetchResult {
+    /** Query ID. */
+    private final long queryId;
+
+    /** Query result rows. */
+    private final Collection<?> items;
+
+    /** Flag indicating the query has no unfetched results. */
+    private final boolean last;
+
+    /**
+     * @param queryId Query ID.
+     * @param items Query result rows.
+     * @param last Flag indicating the query has no unfetched results.
+     */
+    public OdbcQueryFetchResult(long queryId, Collection<?> items, boolean last){
+        this.queryId = queryId;
+        this.items = items;
+        this.last = last;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /**
+     * @return Query result rows.
+     */
+    public Collection<?> items() {
+        return items;
+    }
+
+    /**
+     * @return Flag indicating the query has no unfetched results.
+     */
+    public boolean last() {
+        return last;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaRequest.java
new file mode 100644
index 0000000..b60a9e3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaRequest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * ODBC query get columns meta request.
+ */
+public class OdbcQueryGetColumnsMetaRequest extends OdbcRequest {
+    /** Cache name. */
+    private final String cacheName;
+
+    /** Table name. */
+    private final String tableName;
+
+    /** Column name. */
+    private final String columnName;
+
+    /**
+     * @param cacheName Cache name.
+     * @param tableName Table name.
+     * @param columnName Column name.
+     */
+    public OdbcQueryGetColumnsMetaRequest(String cacheName, String tableName, String columnName) {
+        super(META_COLS);
+
+        this.cacheName = cacheName;
+        this.tableName = tableName;
+        this.columnName = columnName;
+    }
+
+    /**
+     * @return Cache name.
+     */
+    @Nullable public String cacheName() {
+        return cacheName;
+    }
+
+    /**
+     * @return Table name.
+     */
+    public String tableName() {
+        return tableName;
+    }
+
+    /**
+     * @return Column name.
+     */
+    public String columnName() {
+        return columnName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(OdbcQueryGetColumnsMetaRequest.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaResult.java
new file mode 100644
index 0000000..7dbf7d8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetColumnsMetaResult.java
@@ -0,0 +1,42 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import java.util.Collection;
+
+/**
+ * Query get columns meta result.
+ */
+public class OdbcQueryGetColumnsMetaResult {
+    /** Query result rows. */
+    private final Collection<OdbcColumnMeta> meta;
+
+    /**
+     * @param meta Column metadata.
+     */
+    public OdbcQueryGetColumnsMetaResult(Collection<OdbcColumnMeta> meta) {
+        this.meta = meta;
+    }
+
+    /**
+     * @return Query result rows.
+     */
+    public Collection<OdbcColumnMeta> meta() {
+        return meta;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaRequest.java
new file mode 100644
index 0000000..1d468b1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaRequest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * ODBC query get params meta request.
+ */
+public class OdbcQueryGetParamsMetaRequest extends OdbcRequest {
+    /** Cache. */
+    private final String cacheName;
+
+    /** Query. */
+    private final String query;
+
+    /**
+     * @param query SQL Query.
+     */
+    public OdbcQueryGetParamsMetaRequest(String cacheName, String query) {
+        super(META_PARAMS);
+
+        this.cacheName = cacheName;
+        this.query = query;
+    }
+
+    /**
+     * @return SQL Query.
+     */
+    public String query() {
+        return query;
+    }
+
+    /**
+     * @return Cache name.
+     */
+    public String cacheName() {
+        return cacheName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(OdbcQueryGetParamsMetaRequest.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaResult.java
new file mode 100644
index 0000000..d29b760
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetParamsMetaResult.java
@@ -0,0 +1,40 @@
+/*
+ * 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.processors.odbc.odbc;
+
+/**
+ * ODBC query get params meta result.
+ */
+public class OdbcQueryGetParamsMetaResult {
+    /** List of parameter type IDs. */
+    private final byte[] typeIds;
+
+    /**
+     * @param typeIds List of parameter type IDs.
+     */
+    public OdbcQueryGetParamsMetaResult(byte[] typeIds) {
+        this.typeIds = typeIds;
+    }
+
+    /**
+     * @return List of parameter type IDs.
+     */
+    public byte[] typeIds() {
+        return typeIds;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetTablesMetaRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetTablesMetaRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetTablesMetaRequest.java
new file mode 100644
index 0000000..0ebb462
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetTablesMetaRequest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * ODBC query get tables meta request.
+ */
+public class OdbcQueryGetTablesMetaRequest extends OdbcRequest {
+    /** Catalog search pattern. */
+    private final String catalog;
+
+    /** Schema search pattern. */
+    private final String schema;
+
+    /** Table search pattern. */
+    private final String table;
+
+    /** Table type search pattern. */
+    private final String tableType;
+
+    /**
+     * @param catalog Catalog search pattern.
+     * @param schema Schema search pattern.
+     * @param table Table search pattern.
+     * @param tableType Table type search pattern.
+     */
+    public OdbcQueryGetTablesMetaRequest(String catalog, String schema, String table, String tableType) {
+        super(META_TBLS);
+
+        this.catalog = catalog;
+        this.schema = schema;
+        this.table = table;
+        this.tableType = tableType;
+    }
+
+    /**
+     * @return catalog search pattern.
+     */
+    public String catalog() {
+        return catalog;
+    }
+
+    /**
+     * @return Schema search pattern.
+     */
+    public String schema() {
+        return schema;
+    }
+
+    /**
+     * @return Table search pattern.
+     */
+    public String table() {
+        return table;
+    }
+
+    /**
+     * @return Table type search pattern.
+     */
+    public String tableType() {
+        return tableType;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(OdbcQueryGetTablesMetaRequest.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetTablesMetaResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetTablesMetaResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetTablesMetaResult.java
new file mode 100644
index 0000000..6316b2d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryGetTablesMetaResult.java
@@ -0,0 +1,42 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import java.util.Collection;
+
+/**
+ * Query get columns meta result.
+ */
+public class OdbcQueryGetTablesMetaResult {
+    /** Query result rows. */
+    private final Collection<OdbcTableMeta> meta;
+
+    /**
+     * @param meta Column metadata.
+     */
+    public OdbcQueryGetTablesMetaResult(Collection<OdbcTableMeta> meta) {
+        this.meta = meta;
+    }
+
+    /**
+     * @return Query result rows.
+     */
+    public Collection<OdbcTableMeta> meta() {
+        return meta;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java
new file mode 100644
index 0000000..825e770
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
+
+/**
+ * SQL listener command request.
+ */
+public class OdbcRequest extends SqlListenerRequest {
+    /** Execute sql query. */
+    public static final int QRY_EXEC = 2;
+
+    /** Fetch query results. */
+    public static final int QRY_FETCH = 3;
+
+    /** Close query. */
+    public static final int QRY_CLOSE = 4;
+
+    /** Get columns meta query. */
+    public static final int META_COLS = 5;
+
+    /** Get columns meta query. */
+    public static final int META_TBLS = 6;
+
+    /** Get parameters meta. */
+    public static final int META_PARAMS = 7;
+
+    /** Get parameters meta. */
+    public static final int JDBC_REQ = 8;
+
+    /** Command. */
+    private final int cmd;
+
+    /**
+     * @param cmd Command type.
+     */
+    public OdbcRequest(int cmd) {
+        this.cmd = cmd;
+    }
+
+    /**
+     * @return Command.
+     */
+    public int command() {
+        return cmd;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
new file mode 100644
index 0000000..e1b421b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
@@ -0,0 +1,505 @@
+/*
+ * 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.processors.odbc.odbc;
+
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.binary.GridBinaryMarshaller;
+import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
+import org.apache.ignite.internal.processors.odbc.OdbcUtils;
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequestHandler;
+import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
+import org.apache.ignite.internal.processors.odbc.odbc.escape.OdbcEscapeUtils;
+import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
+import org.apache.ignite.internal.util.GridSpinBusyLock;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiTuple;
+
+import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_COLS;
+import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_PARAMS;
+import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_TBLS;
+import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_CLOSE;
+import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_EXEC;
+import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_FETCH;
+
+/**
+ * SQL query handler.
+ */
+public class OdbcRequestHandler implements SqlListenerRequestHandler {
+    /** Query ID sequence. */
+    private static final AtomicLong QRY_ID_GEN = new AtomicLong();
+
+    /** Kernel context. */
+    private final GridKernalContext ctx;
+
+    /** Logger. */
+    private final IgniteLogger log;
+
+    /** Busy lock. */
+    private final GridSpinBusyLock busyLock;
+
+    /** Maximum allowed cursors. */
+    private final int maxCursors;
+
+    /** Current queries cursors. */
+    private final ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCursors = new ConcurrentHashMap<>();
+
+    /** Distributed joins flag. */
+    private final boolean distributedJoins;
+
+    /** Enforce join order flag. */
+    private final boolean enforceJoinOrder;
+
+    /**
+     * Constructor.
+     *
+     * @param ctx Context.
+     * @param busyLock Shutdown latch.
+     * @param maxCursors Maximum allowed cursors.
+     * @param distributedJoins Distributed joins flag.
+     * @param enforceJoinOrder Enforce join order flag.
+     */
+    public OdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int maxCursors,
+        boolean distributedJoins, boolean enforceJoinOrder) {
+        this.ctx = ctx;
+        this.busyLock = busyLock;
+        this.maxCursors = maxCursors;
+        this.distributedJoins = distributedJoins;
+        this.enforceJoinOrder = enforceJoinOrder;
+
+        log = ctx.log(getClass());
+    }
+
+    /** {@inheritDoc} */
+    @Override public SqlListenerResponse handle(SqlListenerRequest req0) {
+        assert req0 != null;
+
+        OdbcRequest req = (OdbcRequest)req0;
+
+        if (!busyLock.enterBusy())
+            return new OdbcResponse(OdbcResponse.STATUS_FAILED,
+                    "Failed to handle ODBC request because node is stopping: " + req);
+
+        try {
+            switch (req.command()) {
+                case QRY_EXEC:
+                    return executeQuery((OdbcQueryExecuteRequest)req);
+
+                case QRY_FETCH:
+                    return fetchQuery((OdbcQueryFetchRequest)req);
+
+                case QRY_CLOSE:
+                    return closeQuery((OdbcQueryCloseRequest)req);
+
+                case META_COLS:
+                    return getColumnsMeta((OdbcQueryGetColumnsMetaRequest)req);
+
+                case META_TBLS:
+                    return getTablesMeta((OdbcQueryGetTablesMetaRequest)req);
+
+                case META_PARAMS:
+                    return getParamsMeta((OdbcQueryGetParamsMetaRequest)req);
+            }
+
+            return new OdbcResponse(OdbcResponse.STATUS_FAILED, "Unsupported ODBC request: " + req);
+        }
+        finally {
+            busyLock.leaveBusy();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public SqlListenerResponse handleException(Exception e) {
+        return new OdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+    }
+
+    /**
+     * {@link OdbcQueryExecuteRequest} command handler.
+     *
+     * @param req Execute query request.
+     * @return Response.
+     */
+    private SqlListenerResponse executeQuery(OdbcQueryExecuteRequest req) {
+        int cursorCnt = qryCursors.size();
+
+        if (maxCursors > 0 && cursorCnt >= maxCursors)
+            return new OdbcResponse(SqlListenerResponse.STATUS_FAILED, "Too many opened cursors (either close other " +
+                "opened cursors or increase the limit through OdbcConfiguration.setMaxOpenCursors()) " +
+                "[maximum=" + maxCursors + ", current=" + cursorCnt + ']');
+
+        long qryId = QRY_ID_GEN.getAndIncrement();
+
+        try {
+            String sql = OdbcEscapeUtils.parse(req.sqlQuery());
+
+            if (log.isDebugEnabled())
+                log.debug("ODBC query parsed [reqId=" + req.requestId() + ", original=" + req.sqlQuery() +
+                    ", parsed=" + sql + ']');
+
+            SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+            qry.setArgs(req.arguments());
+
+            qry.setDistributedJoins(distributedJoins);
+            qry.setEnforceJoinOrder(enforceJoinOrder);
+
+            IgniteCache<Object, Object> cache0 = ctx.grid().cache(req.cacheName());
+
+            if (cache0 == null)
+                return new OdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Cache doesn't exist (did you configure it?): " + req.cacheName());
+
+            IgniteCache<Object, Object> cache = cache0.withKeepBinary();
+
+            if (cache == null)
+                return new OdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Can not get cache with keep binary: " + req.cacheName());
+
+            QueryCursor qryCur = cache.query(qry);
+
+            qryCursors.put(qryId, new IgniteBiTuple<QueryCursor, Iterator>(qryCur, null));
+
+            List<?> fieldsMeta = ((QueryCursorImpl) qryCur).fieldsMeta();
+
+            OdbcQueryExecuteResult res = new OdbcQueryExecuteResult(qryId, convertMetadata(fieldsMeta));
+
+            return new OdbcResponse(res);
+        }
+        catch (Exception e) {
+            qryCursors.remove(qryId);
+
+            U.error(log, "Failed to execute SQL query [reqId=" + req.requestId() + ", req=" + req + ']', e);
+
+            return new OdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+        }
+    }
+
+    /**
+     * {@link OdbcQueryCloseRequest} command handler.
+     *
+     * @param req Execute query request.
+     * @return Response.
+     */
+    private SqlListenerResponse closeQuery(OdbcQueryCloseRequest req) {
+        try {
+            IgniteBiTuple<QueryCursor, Iterator> tuple = qryCursors.get(req.queryId());
+
+            if (tuple == null)
+                return new OdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Failed to find query with ID: " + req.queryId());
+
+            QueryCursor cur = tuple.get1();
+
+            assert(cur != null);
+
+            cur.close();
+
+            qryCursors.remove(req.queryId());
+
+            OdbcQueryCloseResult res = new OdbcQueryCloseResult(req.queryId());
+
+            return new OdbcResponse(res);
+        }
+        catch (Exception e) {
+            qryCursors.remove(req.queryId());
+
+            U.error(log, "Failed to close SQL query [reqId=" + req.requestId() + ", req=" + req.queryId() + ']', e);
+
+            return new OdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+        }
+    }
+
+    /**
+     * {@link OdbcQueryFetchRequest} command handler.
+     *
+     * @param req Execute query request.
+     * @return Response.
+     */
+    private SqlListenerResponse fetchQuery(OdbcQueryFetchRequest req) {
+        try {
+            IgniteBiTuple<QueryCursor, Iterator> tuple = qryCursors.get(req.queryId());
+
+            if (tuple == null)
+                return new OdbcResponse(SqlListenerResponse.STATUS_FAILED,
+                    "Failed to find query with ID: " + req.queryId());
+
+            Iterator iter = tuple.get2();
+
+            if (iter == null) {
+                QueryCursor cur = tuple.get1();
+
+                iter = cur.iterator();
+
+                tuple.put(cur, iter);
+            }
+
+            List<Object> items = new ArrayList<>();
+
+            for (int i = 0; i < req.pageSize() && iter.hasNext(); ++i)
+                items.add(iter.next());
+
+            OdbcQueryFetchResult res = new OdbcQueryFetchResult(req.queryId(), items, !iter.hasNext());
+
+            return new OdbcResponse(res);
+        }
+        catch (Exception e) {
+            U.error(log, "Failed to fetch SQL query result [reqId=" + req.requestId() + ", req=" + req + ']', e);
+
+            return new OdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+        }
+    }
+
+    /**
+     * {@link OdbcQueryGetColumnsMetaRequest} command handler.
+     *
+     * @param req Get columns metadata request.
+     * @return Response.
+     */
+    private SqlListenerResponse getColumnsMeta(OdbcQueryGetColumnsMetaRequest req) {
+        try {
+            List<OdbcColumnMeta> meta = new ArrayList<>();
+
+            String cacheName;
+            String tableName;
+
+            if (req.tableName().contains(".")) {
+                // Parsing two-part table name.
+                String[] parts = req.tableName().split("\\.");
+
+                cacheName = OdbcUtils.removeQuotationMarksIfNeeded(parts[0]);
+
+                tableName = parts[1];
+            }
+            else {
+                cacheName = OdbcUtils.removeQuotationMarksIfNeeded(req.cacheName());
+
+                tableName = req.tableName();
+            }
+
+            Collection<GridQueryTypeDescriptor> tablesMeta = ctx.query().types(cacheName);
+
+            for (GridQueryTypeDescriptor table : tablesMeta) {
+                if (!matches(table.name(), tableName))
+                    continue;
+
+                for (Map.Entry<String, Class<?>> field : table.fields().entrySet()) {
+                    if (!matches(field.getKey(), req.columnName()))
+                        continue;
+
+                    OdbcColumnMeta columnMeta = new OdbcColumnMeta(req.cacheName(), table.name(),
+                        field.getKey(), field.getValue());
+
+                    if (!meta.contains(columnMeta))
+                        meta.add(columnMeta);
+                }
+            }
+
+            OdbcQueryGetColumnsMetaResult res = new OdbcQueryGetColumnsMetaResult(meta);
+
+            return new OdbcResponse(res);
+        }
+        catch (Exception e) {
+            U.error(log, "Failed to get columns metadata [reqId=" + req.requestId() + ", req=" + req + ']', e);
+
+            return new OdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+        }
+    }
+
+    /**
+     * {@link OdbcQueryGetTablesMetaRequest} command handler.
+     *
+     * @param req Get tables metadata request.
+     * @return Response.
+     */
+    private SqlListenerResponse getTablesMeta(OdbcQueryGetTablesMetaRequest req) {
+        try {
+            List<OdbcTableMeta> meta = new ArrayList<>();
+
+            String realSchema = OdbcUtils.removeQuotationMarksIfNeeded(req.schema());
+
+            for (String cacheName : ctx.cache().cacheNames())
+            {
+                if (!matches(cacheName, realSchema))
+                    continue;
+
+                Collection<GridQueryTypeDescriptor> tablesMeta = ctx.query().types(cacheName);
+
+                for (GridQueryTypeDescriptor table : tablesMeta) {
+                    if (!matches(table.name(), req.table()))
+                        continue;
+
+                    if (!matches("TABLE", req.tableType()))
+                        continue;
+
+                    OdbcTableMeta tableMeta = new OdbcTableMeta(null, cacheName, table.name(), "TABLE");
+
+                    if (!meta.contains(tableMeta))
+                        meta.add(tableMeta);
+                }
+            }
+
+            OdbcQueryGetTablesMetaResult res = new OdbcQueryGetTablesMetaResult(meta);
+
+            return new OdbcResponse(res);
+        }
+        catch (Exception e) {
+            U.error(log, "Failed to get tables metadata [reqId=" + req.requestId() + ", req=" + req + ']', e);
+
+            return new OdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+        }
+    }
+
+    /**
+     * {@link OdbcQueryGetParamsMetaRequest} command handler.
+     *
+     * @param req Get params metadata request.
+     * @return Response.
+     */
+    private SqlListenerResponse getParamsMeta(OdbcQueryGetParamsMetaRequest req) {
+        try {
+            PreparedStatement stmt = ctx.query().prepareNativeStatement(req.cacheName(), req.query());
+
+            ParameterMetaData pmd = stmt.getParameterMetaData();
+
+            byte[] typeIds = new byte[pmd.getParameterCount()];
+
+            for (int i = 1; i <= pmd.getParameterCount(); ++i) {
+                int sqlType = pmd.getParameterType(i);
+
+                typeIds[i - 1] = sqlTypeToBinary(sqlType);
+            }
+
+            OdbcQueryGetParamsMetaResult res = new OdbcQueryGetParamsMetaResult(typeIds);
+
+            return new OdbcResponse(res);
+        }
+        catch (Exception e) {
+            U.error(log, "Failed to get params metadata [reqId=" + req.requestId() + ", req=" + req + ']', e);
+
+            return new OdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
+        }
+    }
+
+    /**
+     * Convert {@link java.sql.Types} to binary type constant (See {@link GridBinaryMarshaller} constants).
+     *
+     * @param sqlType SQL type.
+     * @return Binary type.
+     */
+    private static byte sqlTypeToBinary(int sqlType) {
+        switch (sqlType) {
+            case Types.BIGINT:
+                return GridBinaryMarshaller.LONG;
+
+            case Types.BOOLEAN:
+                return GridBinaryMarshaller.BOOLEAN;
+
+            case Types.DATE:
+                return GridBinaryMarshaller.DATE;
+
+            case Types.DOUBLE:
+                return GridBinaryMarshaller.DOUBLE;
+
+            case Types.FLOAT:
+            case Types.REAL:
+                return GridBinaryMarshaller.FLOAT;
+
+            case Types.NUMERIC:
+            case Types.DECIMAL:
+                return GridBinaryMarshaller.DECIMAL;
+
+            case Types.INTEGER:
+                return GridBinaryMarshaller.INT;
+
+            case Types.SMALLINT:
+                return GridBinaryMarshaller.SHORT;
+
+            case Types.TIME:
+                return GridBinaryMarshaller.TIME;
+
+            case Types.TIMESTAMP:
+                return GridBinaryMarshaller.TIMESTAMP;
+
+            case Types.TINYINT:
+                return GridBinaryMarshaller.BYTE;
+
+            case Types.CHAR:
+            case Types.VARCHAR:
+            case Types.LONGNVARCHAR:
+                return GridBinaryMarshaller.STRING;
+
+            case Types.NULL:
+                return GridBinaryMarshaller.NULL;
+
+            case Types.BINARY:
+            case Types.VARBINARY:
+            case Types.LONGVARBINARY:
+            default:
+                return GridBinaryMarshaller.BYTE_ARR;
+        }
+    }
+
+    /**
+     * Convert metadata in collection from {@link GridQueryFieldMetadata} to
+     * {@link OdbcColumnMeta}.
+     *
+     * @param meta Internal query field metadata.
+     * @return Odbc query field metadata.
+     */
+    private static Collection<OdbcColumnMeta> convertMetadata(Collection<?> meta) {
+        List<OdbcColumnMeta> res = new ArrayList<>();
+
+        if (meta != null) {
+            for (Object info : meta) {
+                assert info instanceof GridQueryFieldMetadata;
+
+                res.add(new OdbcColumnMeta((GridQueryFieldMetadata)info));
+            }
+        }
+
+        return res;
+    }
+
+    /**
+     * Checks whether string matches SQL pattern.
+     *
+     * @param str String.
+     * @param ptrn Pattern.
+     * @return Whether string matches pattern.
+     */
+    private static boolean matches(String str, String ptrn) {
+        return str != null && (F.isEmpty(ptrn) ||
+            str.toUpperCase().matches(ptrn.toUpperCase().replace("%", ".*").replace("_", ".")));
+    }
+}


[02/50] [abbrv] ignite git commit: IGNITE-5358 .NET: Fix nullable enum field handling in binary objects

Posted by sb...@apache.org.
IGNITE-5358 .NET: Fix nullable enum field handling in binary objects

This closes #2048


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/34409fd5
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/34409fd5
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/34409fd5

Branch: refs/heads/ignite-5075
Commit: 34409fd59374a8fad31c592a5517e8d80a032cff
Parents: c7638bc
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Jun 2 12:53:57 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Jun 2 12:53:57 2017 +0300

----------------------------------------------------------------------
 .../Apache.Ignite.Core.Tests.csproj             |   1 +
 .../Binary/BinarySelfTest.cs                    |   2 +-
 .../Binary/EnumsTest.cs                         | 299 ++++++++++++++++++-
 .../Binary/EnumsTestOnline.cs                   |  45 +++
 .../Impl/Binary/BinaryReader.cs                 |   9 +-
 .../Impl/Binary/BinaryReflectiveActions.cs      |  11 +-
 .../Impl/Binary/BinaryUtils.cs                  |   2 +
 .../Impl/Binary/BinaryWriter.cs                 |   4 +-
 8 files changed, 348 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/34409fd5/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 6d4f34b..d459d2a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -75,6 +75,7 @@
     <Compile Include="Binary\BinaryNameMapperTest.cs" />
     <Compile Include="Binary\BinaryReaderWriterTest.cs" />
     <Compile Include="Binary\BinarySelfTestSimpleName.cs" />
+    <Compile Include="Binary\EnumsTestOnline.cs" />
     <Compile Include="Deployment\GetAddressFunc.cs" />
     <Compile Include="Deployment\PeerAssemblyLoadingAllApisTest.cs" />
     <Compile Include="Deployment\PeerAssemblyLoadingVersioningTest.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/34409fd5/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
index bae126f..2b22d5a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
@@ -593,7 +593,7 @@ namespace Apache.Ignite.Core.Tests.Binary
 
             Assert.AreEqual(marsh.Unmarshal<TestEnum>(data), val);
 
-            var binEnum = marsh.Unmarshal<IBinaryObject>(data, true);
+            var binEnum = marsh.Unmarshal<IBinaryObject>(data, BinaryMode.ForceBinary);
 
             Assert.AreEqual(val, (TestEnum) binEnum.EnumValue);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/34409fd5/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/EnumsTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/EnumsTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/EnumsTest.cs
index ab54f16..18ef29a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/EnumsTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/EnumsTest.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Tests.Binary
     using System;
     using System.Runtime.Serialization;
     using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Impl;
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Common;
     using NUnit.Framework;
@@ -65,7 +66,9 @@ namespace Apache.Ignite.Core.Tests.Binary
         /// </summary>
         private static void CheckValue<T>(T val, bool isBinaryEnum = true)
         {
-            var marsh = new Marshaller(null) {CompactFooter = false};
+            var marsh = GetMarshaller();
+            var ignite = Ignition.TryGetIgnite();
+
             var bytes = marsh.Marshal(val);
             var res = marsh.Unmarshal<T>(bytes);
             var binRes = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary);
@@ -76,8 +79,17 @@ namespace Apache.Ignite.Core.Tests.Binary
             if (isBinaryEnum)
             {
                 Assert.AreEqual(TypeCaster<int>.Cast(val), binRes.EnumValue);
-                Assert.AreEqual(string.Format("BinaryEnum [typeId={0}, enumValue={1}]",
-                    BinaryUtils.GetStringHashCode(typeof(T).FullName), binRes.EnumValue), binRes.ToString());
+
+                if (ignite != null)
+                {
+                    Assert.AreEqual(string.Format("{0} [typeId={1}, enumValue={2}, enumValueName={3}]",
+                        typeof(T).FullName, binRes.GetBinaryType().TypeId, binRes.EnumValue, val), binRes.ToString());
+                }
+                else
+                {
+                    Assert.AreEqual(string.Format("BinaryEnum [typeId={0}, enumValue={1}]",
+                        BinaryUtils.GetStringHashCode(typeof(T).FullName), binRes.EnumValue), binRes.ToString());
+                }
             }
             else
             {
@@ -85,10 +97,73 @@ namespace Apache.Ignite.Core.Tests.Binary
             }
 
             // Check array.
-            var arr = new[] {val, val};
-            var arrRes = TestUtils.SerializeDeserialize(arr);
+            CheckSerializeDeserialize(new[] {val, val});
+
+            // Check caching.
+            if (ignite != null)
+            {
+                var cache = ignite.GetOrCreateCache<int, T>(typeof(T).FullName);
+                var binCache = cache.WithKeepBinary<int, IBinaryObject>();
+
+                cache[1] = val;
+                res = cache[1];
+                binRes = binCache[1];
+
+                Assert.AreEqual(val, res);
+                Assert.AreEqual(val, binRes.Deserialize<T>());
+
+                var arrCache = ignite.GetOrCreateCache<int, T[]>(typeof(T[]).FullName);
+                arrCache[1] = new[] {val, val};
+                Assert.AreEqual(new[] { val, val }, arrCache[1]);
+            }
+        }
+
+        /// <summary>
+        /// Gets the marshaller.
+        /// </summary>
+        private static Marshaller GetMarshaller()
+        {
+            var ignite = Ignition.TryGetIgnite();
+
+            return ignite != null
+                ? ((Ignite) ignite).Marshaller
+                : new Marshaller(null) {CompactFooter = false};
+        }
+
+        /// <summary>
+        /// Serializes and deserializes a value.
+        /// </summary>
+        private static void CheckSerializeDeserialize<T>(T val, bool cacheOnly = false)
+        {
+            if (!cacheOnly)
+            {
+                var marsh = GetMarshaller();
+
+                var res = marsh.Unmarshal<T>(marsh.Marshal(val));
+                Assert.AreEqual(val, res);
+            }
+
+            var ignite = Ignition.TryGetIgnite();
+
+            if (ignite != null)
+            {
+                var cache = ignite.GetOrCreateCache<int, T>(typeof(T).FullName);
+
+                cache.Put(1, val);
+                var res = cache.Get(1);
 
-            Assert.AreEqual(arr, arrRes);
+                Assert.AreEqual(val, res);
+            }
+        }
+
+        /// <summary>
+        /// Convert to IBinaryObject.
+        /// </summary>
+        private static IBinaryObject ToBinary<T>(T val)
+        {
+            var marsh = GetMarshaller();
+
+            return marsh.Unmarshal<IBinaryObject>(marsh.Marshal(val), BinaryMode.ForceBinary);
         }
 
         /// <summary>
@@ -100,8 +175,7 @@ namespace Apache.Ignite.Core.Tests.Binary
             // Min values.
             var val = new EnumsBinarizable();
             
-            var res = TestUtils.SerializeDeserialize(val);
-            Assert.AreEqual(val, res);
+            CheckSerializeDeserialize(val);
 
             // Max values.
             val = new EnumsBinarizable
@@ -116,8 +190,61 @@ namespace Apache.Ignite.Core.Tests.Binary
                 UShort = UShortEnum.Bar
             };
 
-            res = TestUtils.SerializeDeserialize(val);
-            Assert.AreEqual(val, res);
+            CheckSerializeDeserialize(val);
+        }
+
+        /// <summary>
+        /// Tests enums as a BinaryObject field in binarizable object.
+        /// </summary>
+        [Test]
+        public void TestBinarizableFieldAsBinaryObject()
+        {
+            // Null values.
+            var val = new EnumsBinaryForm();
+            
+            CheckSerializeDeserialize(val);
+
+            // Max values.
+            val = new EnumsBinaryForm
+            {
+                Byte = ToBinary(ByteEnum.Bar),
+                Int = ToBinary(IntEnum.Bar),
+                Long = ToBinary(LongEnum.Bar),
+                SByte = ToBinary(SByteEnum.Bar),
+                Short = ToBinary(ShortEnum.Bar),
+                UInt = ToBinary(UIntEnum.Bar),
+                ULong = ToBinary(ULongEnum.Bar),
+                UShort = ToBinary(UShortEnum.Bar)
+            };
+
+            CheckSerializeDeserialize(val, true);
+        }
+
+        /// <summary>
+        /// Tests enums as a nullable field in binarizable object.
+        /// </summary>
+        [Test]
+        public void TestBinarizableNullableField()
+        {
+            // Default values.
+            var val = new EnumsBinarizableNullable();
+            
+            CheckSerializeDeserialize(val);
+
+            // Max values.
+            val = new EnumsBinarizableNullable
+            {
+                Byte = ByteEnum.Bar,
+                Int = IntEnum.Bar,
+                Long = LongEnum.Bar,
+                SByte = SByteEnum.Bar,
+                Short = ShortEnum.Bar,
+                UInt = UIntEnum.Bar,
+                ULong = ULongEnum.Bar,
+                UShort = UShortEnum.Bar
+            };
+
+            CheckSerializeDeserialize(val);
         }
 
         /// <summary>
@@ -129,8 +256,7 @@ namespace Apache.Ignite.Core.Tests.Binary
             // Min values.
             var val = new EnumsSerializable();
 
-            var res = TestUtils.SerializeDeserialize(val);
-            Assert.AreEqual(val, res);
+            CheckSerializeDeserialize(val);
 
             // Max values.
             val = new EnumsSerializable
@@ -145,8 +271,34 @@ namespace Apache.Ignite.Core.Tests.Binary
                 UShort = UShortEnum.Bar
             };
 
-            res = TestUtils.SerializeDeserialize(val);
-            Assert.AreEqual(val, res);
+            CheckSerializeDeserialize(val);
+        }
+
+        /// <summary>
+        /// Tests enums as a nullable field in ISerializable object.
+        /// </summary>
+        [Test]
+        public void TestSerializableNullableField()
+        {
+            // Default values.
+            var val = new EnumsSerializableNullable();
+
+            CheckSerializeDeserialize(val);
+
+            // Max values.
+            val = new EnumsSerializableNullable
+            {
+                Byte = ByteEnum.Bar,
+                Int = IntEnum.Bar,
+                Long = LongEnum.Bar,
+                SByte = SByteEnum.Bar,
+                Short = ShortEnum.Bar,
+                UInt = UIntEnum.Bar,
+                ULong = ULongEnum.Bar,
+                UShort = UShortEnum.Bar
+            };
+
+            CheckSerializeDeserialize(val);
         }
 
         private enum ByteEnum : byte
@@ -240,6 +392,92 @@ namespace Apache.Ignite.Core.Tests.Binary
             }
         }
 
+        private class EnumsBinaryForm
+        {
+            public IBinaryObject Byte { get; set; }
+            public IBinaryObject SByte { get; set; }
+            public IBinaryObject Short { get; set; }
+            public IBinaryObject UShort { get; set; }
+            public IBinaryObject Int { get; set; }
+            public IBinaryObject UInt { get; set; }
+            public IBinaryObject Long { get; set; }
+            public IBinaryObject ULong { get; set; }
+
+            private bool Equals(EnumsBinaryForm other)
+            {
+                return Equals(Byte, other.Byte) && Equals(SByte, other.SByte) && Equals(Short, other.Short) &&
+                       Equals(UShort, other.UShort) && Equals(Int, other.Int) && Equals(UInt, other.UInt) &&
+                       Equals(Long, other.Long) && Equals(ULong, other.ULong);
+            }
+
+            public override bool Equals(object obj)
+            {
+                if (ReferenceEquals(null, obj)) return false;
+                if (ReferenceEquals(this, obj)) return true;
+                if (obj.GetType() != GetType()) return false;
+                return Equals((EnumsBinaryForm) obj);
+            }
+
+            public override int GetHashCode()
+            {
+                unchecked
+                {
+                    var hashCode = (Byte != null ? Byte.GetHashCode() : 0);
+                    hashCode = (hashCode*397) ^ (SByte != null ? SByte.GetHashCode() : 0);
+                    hashCode = (hashCode*397) ^ (Short != null ? Short.GetHashCode() : 0);
+                    hashCode = (hashCode*397) ^ (UShort != null ? UShort.GetHashCode() : 0);
+                    hashCode = (hashCode*397) ^ (Int != null ? Int.GetHashCode() : 0);
+                    hashCode = (hashCode*397) ^ (UInt != null ? UInt.GetHashCode() : 0);
+                    hashCode = (hashCode*397) ^ (Long != null ? Long.GetHashCode() : 0);
+                    hashCode = (hashCode*397) ^ (ULong != null ? ULong.GetHashCode() : 0);
+                    return hashCode;
+                }
+            }
+        }
+
+        private class EnumsBinarizableNullable
+        {
+            public ByteEnum? Byte { get; set; }
+            public SByteEnum? SByte { get; set; }
+            public ShortEnum? Short { get; set; }
+            public UShortEnum? UShort { get; set; }
+            public IntEnum? Int { get; set; }
+            public UIntEnum? UInt { get; set; }
+            public LongEnum? Long { get; set; }
+            public ULongEnum? ULong { get; set; }
+
+            private bool Equals(EnumsBinarizableNullable other)
+            {
+                return Byte == other.Byte && SByte == other.SByte && Short == other.Short 
+                    && UShort == other.UShort && Int == other.Int && UInt == other.UInt 
+                    && Long == other.Long && ULong == other.ULong;
+            }
+
+            public override bool Equals(object obj)
+            {
+                if (ReferenceEquals(null, obj)) return false;
+                if (ReferenceEquals(this, obj)) return true;
+                if (obj.GetType() != GetType()) return false;
+                return Equals((EnumsBinarizableNullable) obj);
+            }
+
+            public override int GetHashCode()
+            {
+                unchecked
+                {
+                    var hashCode = Byte.GetHashCode();
+                    hashCode = (hashCode*397) ^ SByte.GetHashCode();
+                    hashCode = (hashCode*397) ^ Short.GetHashCode();
+                    hashCode = (hashCode*397) ^ UShort.GetHashCode();
+                    hashCode = (hashCode*397) ^ Int.GetHashCode();
+                    hashCode = (hashCode*397) ^ UInt.GetHashCode();
+                    hashCode = (hashCode*397) ^ Long.GetHashCode();
+                    hashCode = (hashCode*397) ^ ULong.GetHashCode();
+                    return hashCode;
+                }
+            }
+        }
+
         [Serializable]
         private class EnumsSerializable : EnumsBinarizable, ISerializable
         {
@@ -272,5 +510,38 @@ namespace Apache.Ignite.Core.Tests.Binary
                 info.AddValue("ulong", ULong);
             }
         }
+
+        [Serializable]
+        private class EnumsSerializableNullable : EnumsBinarizableNullable, ISerializable
+        {
+            public EnumsSerializableNullable()
+            {
+                // No-op.
+            }
+
+            protected EnumsSerializableNullable(SerializationInfo info, StreamingContext context)
+            {
+                Byte = (ByteEnum?) info.GetValue("byte", typeof(ByteEnum));
+                SByte = (SByteEnum?) info.GetValue("sbyte", typeof(SByteEnum));
+                Short = (ShortEnum?) info.GetValue("short", typeof(ShortEnum));
+                UShort = (UShortEnum?) info.GetValue("ushort", typeof(UShortEnum));
+                Int = (IntEnum?) info.GetValue("int", typeof(IntEnum));
+                UInt = (UIntEnum?) info.GetValue("uint", typeof(UIntEnum));
+                Long = (LongEnum?) info.GetValue("long", typeof(LongEnum));
+                ULong = (ULongEnum?) info.GetValue("ulong", typeof(ULongEnum));
+            }
+
+            public void GetObjectData(SerializationInfo info, StreamingContext context)
+            {
+                info.AddValue("byte", Byte);
+                info.AddValue("sbyte", SByte);
+                info.AddValue("short", Short);
+                info.AddValue("ushort", UShort);
+                info.AddValue("int", Int);
+                info.AddValue("uint", UInt);
+                info.AddValue("long", Long);
+                info.AddValue("ulong", ULong);
+            }
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/34409fd5/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/EnumsTestOnline.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/EnumsTestOnline.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/EnumsTestOnline.cs
new file mode 100644
index 0000000..0c82696
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/EnumsTestOnline.cs
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Tests.Binary
+{
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Enums test with Ignite running.
+    /// </summary>
+    public class EnumsTestOnline : EnumsTest
+    {
+        /// <summary>
+        /// Sets up the fixture.
+        /// </summary>
+        [TestFixtureSetUp]
+        public void FixtureSetUp()
+        {
+            Ignition.Start(TestUtils.GetTestConfiguration());
+        }
+
+        /// <summary>
+        /// Tears down the fixture.
+        /// </summary>
+        [TestFixtureTearDown]
+        public void FixtureTearDown()
+        {
+            Ignition.StopAll(true);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/34409fd5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
index e38085c..4b4b471 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
@@ -401,9 +401,10 @@ namespace Apache.Ignite.Core.Impl.Binary
                     return default(T);
 
                 case BinaryUtils.TypeEnum:
+                    return ReadEnum0<T>(this, _mode == BinaryMode.ForceBinary);
+
                 case BinaryUtils.TypeBinaryEnum:
-                    // Never read enums in binary mode when reading a field (we do not support half-binary objects)
-                    return ReadEnum0<T>(this, false);  
+                    return ReadEnum0<T>(this, _mode != BinaryMode.Deserialize);
 
                 case BinaryUtils.HdrFull:
                     // Unregistered enum written as serializable
@@ -583,6 +584,10 @@ namespace Apache.Ignite.Core.Impl.Binary
                     return true;
 
                 case BinaryUtils.TypeEnum:
+                    res = ReadEnum0<T>(this, _mode == BinaryMode.ForceBinary);
+
+                    return true;
+
                 case BinaryUtils.TypeBinaryEnum:
                     res = ReadEnum0<T>(this, _mode != BinaryMode.Deserialize);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/34409fd5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
index b061be2..97964cf 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
@@ -422,11 +422,7 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             var type = field.FieldType;
 
-            var genericDef = type.IsGenericType ? type.GetGenericTypeDefinition() : null;
-
-            bool nullable = genericDef == typeof (Nullable<>);
-
-            var nullableType = nullable ? type.GetGenericArguments()[0] : null;
+            var nullableType = Nullable.GetUnderlyingType(type);
 
             if (type == typeof (decimal))
             {
@@ -455,14 +451,15 @@ namespace Apache.Ignite.Core.Impl.Binary
                     ? GetRawReader(field, r => r.ReadObject<Guid>())
                     : GetReader(field, (f, r) => r.ReadObject<Guid>(f));
             }
-            else if (nullable && nullableType == typeof (Guid))
+            else if (nullableType == typeof (Guid))
             {
                 writeAction = raw
                     ? GetRawWriter<Guid?>(field, (w, o) => w.WriteGuid(o))
                     : GetWriter<Guid?>(field, (f, w, o) => w.WriteGuid(f, o));
                 readAction = raw ? GetRawReader(field, r => r.ReadGuid()) : GetReader(field, (f, r) => r.ReadGuid(f));
             }
-            else if (type.IsEnum && !new[] {typeof(long), typeof(ulong)}.Contains(Enum.GetUnderlyingType(type)))
+            else if ((nullableType ?? type).IsEnum && 
+                !new[] {typeof(long), typeof(ulong)}.Contains(Enum.GetUnderlyingType(nullableType ?? type)))
             {
                 writeAction = raw
                     ? GetRawWriter<object>(field, (w, o) => w.WriteEnum(o), true)

http://git-wip-us.apache.org/repos/asf/ignite/blob/34409fd5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
index 2ac617e..91a536e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
@@ -1787,6 +1787,8 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             Debug.Assert(type != null);
 
+            type = Nullable.GetUnderlyingType(type) ?? type;
+
             if (!type.IsEnum)
                 return false;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/34409fd5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
index da2b371..43a73912 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
@@ -861,7 +861,9 @@ namespace Apache.Ignite.Core.Impl.Binary
                 WriteNullField();
             else
             {
-                var type = val.GetType();
+                // Unwrap nullable.
+                var valType = val.GetType();
+                var type = Nullable.GetUnderlyingType(valType) ?? valType;
 
                 if (!type.IsEnum)
                 {


[21/50] [abbrv] ignite git commit: IGNITE-5327: Introduced PARTITIONED and REPLICATED cache templates for CREATE TABLE command. This closes #2056.

Posted by sb...@apache.org.
IGNITE-5327: Introduced PARTITIONED and REPLICATED cache templates for CREATE TABLE command. This closes #2056.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/3d7b15b1
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/3d7b15b1
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/3d7b15b1

Branch: refs/heads/ignite-5075
Commit: 3d7b15b1a3e025fafd44035ff33d714e3d2d87eb
Parents: e4580b8
Author: Alexander Paschenko <al...@gmail.com>
Authored: Fri Jun 2 17:40:12 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 17:40:12 2017 +0300

----------------------------------------------------------------------
 .../processors/query/GridQueryProcessor.java    | 35 ++++++-----
 .../internal/processors/query/QueryUtils.java   |  6 ++
 .../query/h2/sql/GridSqlQueryParser.java        | 25 ++------
 .../cache/index/H2DynamicTableSelfTest.java     | 65 +++++++++++++++++++-
 .../query/h2/sql/GridQueryParsingTest.java      |  5 +-
 5 files changed, 95 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/3d7b15b1/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index 1c1fa34..62d826d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -1290,30 +1290,33 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         assert !F.isEmpty(templateName);
         assert backups >= 0;
 
-        CacheConfiguration<?, ?> templateCfg = ctx.cache().getConfigFromTemplate(templateName);
+        CacheConfiguration<?, ?> ccfg = ctx.cache().getConfigFromTemplate(templateName);
 
-        if (templateCfg == null)
-            throw new SchemaOperationException(SchemaOperationException.CODE_CACHE_NOT_FOUND, templateName);
+        if (ccfg == null) {
+            if (QueryUtils.TEMPLATE_PARTITIONED.equalsIgnoreCase(templateName))
+                ccfg = new CacheConfiguration<>().setCacheMode(CacheMode.PARTITIONED);
+            else if (QueryUtils.TEMPLATE_REPLICÄTED.equalsIgnoreCase(templateName))
+                ccfg = new CacheConfiguration<>().setCacheMode(CacheMode.REPLICATED);
+            else
+                throw new SchemaOperationException(SchemaOperationException.CODE_CACHE_NOT_FOUND, templateName);
+        }
 
-        if (!F.isEmpty(templateCfg.getQueryEntities()))
-            throw new SchemaOperationException("Template cannot contain query entities [template=" +
-                templateName + ']');
+        if (!F.isEmpty(ccfg.getQueryEntities()))
+            throw new SchemaOperationException("Template cache already contains query entities which it should not: " +
+                templateName);
 
-        CacheConfiguration<?, ?> newCfg = new CacheConfiguration<>(templateCfg);
+        ccfg.setName(entity.getTableName());
 
         if (atomicityMode != null)
-            newCfg.setAtomicityMode(atomicityMode);
-
-        newCfg.setBackups(backups);
+            ccfg.setAtomicityMode(atomicityMode);
 
-        newCfg.setName(entity.getTableName());
-        newCfg.setQueryEntities(Collections.singleton(entity));
-        newCfg.setSqlSchema(schemaName);
+        ccfg.setBackups(backups);
 
-        // Preserve user specified names as they are.
-        newCfg.setSqlEscapeAll(true);
+        ccfg.setSqlSchema(schemaName);
+        ccfg.setSqlEscapeAll(true);
+        ccfg.setQueryEntities(Collections.singleton(entity));
 
-        boolean res = ctx.grid().getOrCreateCache0(newCfg, true).get2();
+        boolean res = ctx.grid().getOrCreateCache0(ccfg, true).get2();
 
         if (!res && !ifNotExists)
             throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_EXISTS,  entity.getTableName());

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d7b15b1/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
index 51648e5..748768e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
@@ -75,6 +75,12 @@ public class QueryUtils {
     /** Version field name. */
     public static final String VER_FIELD_NAME = "_VER";
 
+    /** Well-known template name for PARTITIONED cache. */
+    public static final String TEMPLATE_PARTITIONED = "PARTITIONED";
+
+    /** Well-known template name for REPLICATED cache. */
+    public static final String TEMPLATE_REPLICÄTED = "REPLICATED";
+
     /** Discovery history size. */
     private static final int DISCO_HIST_SIZE = getInteger(IGNITE_INDEXING_DISCOVERY_HISTORY_SIZE, 1000);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d7b15b1/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
index 573384a..fdb908e 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -30,7 +30,6 @@ import java.util.Map;
 import javax.cache.CacheException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.cache.CacheAtomicityMode;
-import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.cache.QueryIndexType;
 import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
@@ -405,11 +404,6 @@ public class GridSqlQueryParser {
     /** */
     private static final String PARAM_ATOMICITY = "ATOMICITY";
 
-    /** Names of the params that need to be present in WITH clause of CREATE TABLE. */
-    private static final String[] MANDATORY_CREATE_TABLE_PARAMS = {
-        PARAM_TEMPLATE
-    };
-
     /** */
     private final IdentityHashMap<Object, Object> h2ObjToGridObj = new IdentityHashMap<>();
 
@@ -847,6 +841,8 @@ public class GridSqlQueryParser {
     private GridSqlCreateTable parseCreateTable(CreateTable createTbl) {
         GridSqlCreateTable res = new GridSqlCreateTable();
 
+        res.templateName(QueryUtils.TEMPLATE_PARTITIONED);
+
         Query qry = CREATE_TABLE_QUERY.get(createTbl);
 
         if (qry != null)
@@ -945,11 +941,8 @@ public class GridSqlQueryParser {
             throw new IgniteSQLException("No cache value related columns found");
 
         res.columns(cols);
-
         res.primaryKeyColumns(pkCols);
-
         res.tableName(data.tableName);
-
         res.ifNotExists(CREATE_TABLE_IF_NOT_EXISTS.get(createTbl));
 
         List<String> extraParams = data.tableEngineParams != null ? new ArrayList<String>() : null;
@@ -960,9 +953,9 @@ public class GridSqlQueryParser {
 
         res.params(extraParams);
 
-        Map<String, String> params = new HashMap<>();
-
         if (!F.isEmpty(extraParams)) {
+            Map<String, String> params = new HashMap<>();
+
             for (String p : extraParams) {
                 String[] parts = p.split(PARAM_NAME_VALUE_SEPARATOR);
 
@@ -981,17 +974,11 @@ public class GridSqlQueryParser {
                 if (params.put(name, val) != null)
                     throw new IgniteSQLException("Duplicate parameter: " + p, IgniteQueryErrorCode.PARSING);
             }
-        }
 
-        for (String paramName : MANDATORY_CREATE_TABLE_PARAMS) {
-            if (!params.containsKey(paramName))
-                throw new IgniteSQLException("Mandatory parameter is missing: " + paramName,
-                    IgniteQueryErrorCode.PARSING);
+            for (Map.Entry<String, String> e : params.entrySet())
+                processExtraParam(e.getKey(), e.getValue(), res);
         }
 
-        for (Map.Entry<String, String> e : params.entrySet())
-            processExtraParam(e.getKey(), e.getValue(), res);
-
         return res;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d7b15b1/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
index b43d3f2..d97d1eb 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
@@ -97,9 +97,64 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testCreateTable() throws Exception {
+        doTestCreateTable(CACHE_NAME, null);
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} with reserved template cache name actually creates new {@code REPLICATED} cache,
+     * H2 table and type descriptor on all nodes.
+     * @throws Exception if failed.
+     */
+    public void testCreateTableReplicated() throws Exception {
+        doTestCreateTable("REPLICATED", CacheMode.REPLICATED);
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} with reserved template cache name actually creates new {@code PARTITIONED} cache,
+     * H2 table and type descriptor on all nodes.
+     * @throws Exception if failed.
+     */
+    public void testCreateTablePartitioned() throws Exception {
+        doTestCreateTable("PARTITIONED", CacheMode.PARTITIONED);
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} with reserved template cache name actually creates new {@code REPLICATED} cache,
+     * H2 table and type descriptor on all nodes.
+     * @throws Exception if failed.
+     */
+    public void testCreateTableReplicatedCaseInsensitive() throws Exception {
+        doTestCreateTable("replicated", CacheMode.REPLICATED);
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} with reserved template cache name actually creates new {@code PARTITIONED} cache,
+     * H2 table and type descriptor on all nodes.
+     * @throws Exception if failed.
+     */
+    public void testCreateTablePartitionedCaseInsensitive() throws Exception {
+        doTestCreateTable("partitioned", CacheMode.PARTITIONED);
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} with reserved template cache name actually creates new {@code PARTITIONED} cache,
+     * H2 table and type descriptor on all nodes, when no cache template name is given.
+     * @throws Exception if failed.
+     */
+    public void testCreateTableNoTemplate() throws Exception {
+        doTestCreateTable(null, CacheMode.PARTITIONED);
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} with given template cache name actually creates new cache,
+     * H2 table and type descriptor on all nodes, optionally with cache type check.
+     * @param tplCacheName Template cache name.
+     * @param mode Expected cache mode, or {@code null} if no check is needed.
+     */
+    private void doTestCreateTable(String tplCacheName, CacheMode mode) {
         executeDdl("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "\"template=cache,backups=10\",\"atomicity=atomic\"");
+            (F.isEmpty(tplCacheName) ? "" : "\"template=" + tplCacheName + "\",") + "\"backups=10,atomicity=atomic\"");
 
         for (int i = 0; i < 4; i++) {
             IgniteEx node = grid(i);
@@ -110,12 +165,18 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
 
             assertNotNull(cacheDesc);
 
-            assertEquals(10, cacheDesc.cacheConfiguration().getBackups());
+            if (mode == CacheMode.REPLICATED)
+                assertEquals(Integer.MAX_VALUE, cacheDesc.cacheConfiguration().getBackups());
+            else
+                assertEquals(10, cacheDesc.cacheConfiguration().getBackups());
 
             assertEquals(CacheAtomicityMode.ATOMIC, cacheDesc.cacheConfiguration().getAtomicityMode());
 
             assertTrue(cacheDesc.sql());
 
+            if (mode != null)
+                assertEquals(mode, cacheDesc.cacheConfiguration().getCacheMode());
+
             QueryTypeDescriptorImpl desc = typeExisting(node, "Person", "Person");
 
             assertEquals(Object.class, desc.keyClass());

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d7b15b1/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
index 8f9db2e..329e580 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
@@ -598,10 +598,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
         assertParseThrows("create table Person (id int primary key)",
             IgniteSQLException.class, "No cache value related columns found");
 
-        assertParseThrows("create table Person (id int primary key, age int null)",
-            IgniteSQLException.class, "Mandatory parameter is missing: TEMPLATE");
-
-        assertParseThrows("create table Person (id int primary key, age int not null) WITH \"template=cache\"",
+        assertParseThrows("create table Person (id int primary key, age int not null) WITH \"cacheTemplate=cache\"",
             IgniteSQLException.class, "Non nullable columns are forbidden");
 
         assertParseThrows("create table Person (id int primary key, age int unique) WITH \"template=cache\"",


[24/50] [abbrv] ignite git commit: IGNITE-4477: Added IgniteFuture.listenAsync() and IgniteFuture.chainAsync() methods. This closes #1844.

Posted by sb...@apache.org.
IGNITE-4477: Added IgniteFuture.listenAsync() and IgniteFuture.chainAsync() methods. This closes #1844.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/b375c1ef
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/b375c1ef
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/b375c1ef

Branch: refs/heads/ignite-5075
Commit: b375c1ef504c72b9ffd653933da4bacea5aad5b5
Parents: 9d2ec1c
Author: dkarachentsev <dk...@gridgain.com>
Authored: Sat Jun 3 16:43:35 2017 +0300
Committer: devozerov <pp...@gmail.com>
Committed: Sat Jun 3 16:43:35 2017 +0300

----------------------------------------------------------------------
 .../processors/cache/IgniteCacheFutureImpl.java |   8 +-
 .../util/future/AsyncFutureListener.java        |  57 +++
 .../internal/util/future/IgniteFutureImpl.java  |  33 +-
 .../org/apache/ignite/lang/IgniteFuture.java    |  24 +-
 .../util/future/IgniteCacheFutureImplTest.java  |  46 ++
 .../util/future/IgniteFutureImplTest.java       | 466 +++++++++++++++++--
 .../testsuites/IgniteLangSelfTestSuite.java     |   3 +
 .../processors/schedule/ScheduleFutureImpl.java |  51 +-
 .../schedule/GridScheduleSelfTest.java          |  84 +++-
 9 files changed, 724 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b375c1ef/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheFutureImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheFutureImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheFutureImpl.java
index 74cccc1..c861be8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheFutureImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheFutureImpl.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.processors.cache;
 
+import java.util.concurrent.Executor;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.IgniteFutureCancelledCheckedException;
 import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException;
@@ -43,7 +44,12 @@ public class IgniteCacheFutureImpl<V> extends IgniteFutureImpl<V> {
 
     /** {@inheritDoc} */
     @Override public <T> IgniteFuture<T> chain(IgniteClosure<? super IgniteFuture<V>, T> doneCb) {
-        return new IgniteCacheFutureImpl<>(chainInternal(doneCb));
+        return new IgniteCacheFutureImpl<>(chainInternal(doneCb, null));
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> IgniteFuture<T> chainAsync(IgniteClosure<? super IgniteFuture<V>, T> doneCb, Executor exec) {
+        return new IgniteCacheFutureImpl<>(chainInternal(doneCb, exec));
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b375c1ef/modules/core/src/main/java/org/apache/ignite/internal/util/future/AsyncFutureListener.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/future/AsyncFutureListener.java b/modules/core/src/main/java/org/apache/ignite/internal/util/future/AsyncFutureListener.java
new file mode 100644
index 0000000..460ce8b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/future/AsyncFutureListener.java
@@ -0,0 +1,57 @@
+/*
+ * 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.util.future;
+
+import java.util.concurrent.Executor;
+import org.apache.ignite.lang.IgniteFuture;
+import org.apache.ignite.lang.IgniteInClosure;
+
+/**
+ * Wraps listener and executes it in specified executor.
+ */
+public class AsyncFutureListener<V> implements IgniteInClosure<IgniteFuture<V>> {
+    /** Serial version uid. */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    private final IgniteInClosure<? super IgniteFuture<V>> lsnr;
+
+    /** */
+    private final Executor exec;
+
+    /**
+     * @param lsnr Listener to be called asynchronously.
+     * @param exec Executor to process listener.
+     */
+    public AsyncFutureListener(IgniteInClosure<? super IgniteFuture<V>> lsnr, Executor exec) {
+        assert lsnr != null;
+        assert exec != null;
+
+        this.lsnr = lsnr;
+        this.exec = exec;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void apply(final IgniteFuture<V> fut) {
+        exec.execute(new Runnable() {
+            @Override public void run() {
+                lsnr.apply(fut);
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b375c1ef/modules/core/src/main/java/org/apache/ignite/internal/util/future/IgniteFutureImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/future/IgniteFutureImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/util/future/IgniteFutureImpl.java
index 08fae96..a018628 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/future/IgniteFutureImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/future/IgniteFutureImpl.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.util.future;
 
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
@@ -28,6 +29,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteClosure;
 import org.apache.ignite.lang.IgniteFuture;
 import org.apache.ignite.lang.IgniteInClosure;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Implementation of public API future.
@@ -70,16 +72,34 @@ public class IgniteFutureImpl<V> implements IgniteFuture<V> {
     }
 
     /** {@inheritDoc} */
+    @Override public void listenAsync(IgniteInClosure<? super IgniteFuture<V>> lsnr, Executor exec) {
+        A.notNull(lsnr, "lsnr");
+        A.notNull(exec, "exec");
+
+        fut.listen(new InternalFutureListener(new AsyncFutureListener<>(lsnr, exec)));
+    }
+
+    /** {@inheritDoc} */
     @Override public <T> IgniteFuture<T> chain(final IgniteClosure<? super IgniteFuture<V>, T> doneCb) {
-        return new IgniteFutureImpl<>(chainInternal(doneCb));
+        return new IgniteFutureImpl<>(chainInternal(doneCb, null));
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> IgniteFuture<T> chainAsync(final IgniteClosure<? super IgniteFuture<V>, T> doneCb,
+        Executor exec) {
+        A.notNull(doneCb, "doneCb");
+        A.notNull(exec, "exec");
+
+        return new IgniteFutureImpl<>(chainInternal(doneCb, exec));
     }
 
     /**
      * @param doneCb Done callback.
      * @return Internal future
      */
-    protected  <T> IgniteInternalFuture<T> chainInternal(final IgniteClosure<? super IgniteFuture<V>, T> doneCb) {
-        return fut.chain(new C1<IgniteInternalFuture<V>, T>() {
+    protected  <T> IgniteInternalFuture<T> chainInternal(final IgniteClosure<? super IgniteFuture<V>, T> doneCb,
+        @Nullable Executor exec) {
+        C1<IgniteInternalFuture<V>, T> clos = new C1<IgniteInternalFuture<V>, T>() {
             @Override public T apply(IgniteInternalFuture<V> fut) {
                 assert IgniteFutureImpl.this.fut == fut;
 
@@ -90,7 +110,12 @@ public class IgniteFutureImpl<V> implements IgniteFuture<V> {
                     throw new GridClosureException(e);
                 }
             }
-        });
+        };
+
+        if (exec != null)
+            return fut.chain(clos, exec);
+
+        return fut.chain(clos);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b375c1ef/modules/core/src/main/java/org/apache/ignite/lang/IgniteFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/IgniteFuture.java b/modules/core/src/main/java/org/apache/ignite/lang/IgniteFuture.java
index 6519ec8..ee297cd 100644
--- a/modules/core/src/main/java/org/apache/ignite/lang/IgniteFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/lang/IgniteFuture.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.lang;
 
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteInterruptedException;
@@ -96,12 +97,23 @@ public interface IgniteFuture<V> {
 
     /**
      * Registers listener closure to be asynchronously notified whenever future completes.
+     * Closure will be processed in thread that completes this future or (if future already
+     * completed) immediately in current thread.
      *
-     * @param lsnr Listener closure to register. If not provided - this method is no-op.
+     * @param lsnr Listener closure to register. Cannot be {@code null}.
      */
     public void listen(IgniteInClosure<? super IgniteFuture<V>> lsnr);
 
     /**
+     * Registers listener closure to be asynchronously notified whenever future completes.
+     * Closure will be processed in specified executor.
+     *
+     * @param lsnr Listener closure to register. Cannot be {@code null}.
+     * @param exec Executor to run listener. Cannot be {@code null}.
+     */
+    public void listenAsync(IgniteInClosure<? super IgniteFuture<V>> lsnr, Executor exec);
+
+    /**
      * Make a chained future to convert result of this future (when complete) into a new format.
      * It is guaranteed that done callback will be called only ONCE.
      *
@@ -109,4 +121,14 @@ public interface IgniteFuture<V> {
      * @return Chained future that finishes after this future completes and done callback is called.
      */
     public <T> IgniteFuture<T> chain(IgniteClosure<? super IgniteFuture<V>, T> doneCb);
+
+    /**
+     * Make a chained future to convert result of this future (when complete) into a new format.
+     * It is guaranteed that done callback will be called only ONCE.
+     *
+     * @param doneCb Done callback that is applied to this future when it finishes to produce chained future result.
+     * @param exec Executor to run done callback. Cannot be {@code null}.
+     * @return Chained future that finishes after this future completes and done callback is called.
+     */
+    public <T> IgniteFuture<T> chainAsync(IgniteClosure<? super IgniteFuture<V>, T> doneCb, Executor exec);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/b375c1ef/modules/core/src/test/java/org/apache/ignite/internal/util/future/IgniteCacheFutureImplTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/future/IgniteCacheFutureImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/future/IgniteCacheFutureImplTest.java
new file mode 100644
index 0000000..46f1706
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/future/IgniteCacheFutureImplTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.util.future;
+
+import javax.cache.CacheException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.cache.IgniteCacheFutureImpl;
+
+/**
+ * Tests IgniteCacheFutureImpl.
+ */
+public class IgniteCacheFutureImplTest extends IgniteFutureImplTest {
+    /** {@inheritDoc} */
+    @Override protected <V> IgniteFutureImpl<V> createFuture(IgniteInternalFuture<V> fut) {
+        return new IgniteCacheFutureImpl<>(fut);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Class<? extends Exception> expectedException() {
+        return CacheException.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void assertExpectedException(Exception e, Exception exp) {
+        if (exp instanceof IgniteException)
+            assertEquals(exp, e.getCause().getCause());
+        else
+            assertEquals(exp, e.getCause());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b375c1ef/modules/core/src/test/java/org/apache/ignite/internal/util/future/IgniteFutureImplTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/future/IgniteFutureImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/future/IgniteFutureImplTest.java
index 1e5b9a8..3a06cf4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/util/future/IgniteFutureImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/future/IgniteFutureImplTest.java
@@ -18,10 +18,17 @@
 package org.apache.ignite.internal.util.future;
 
 import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import javax.cache.CacheException;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.util.typedef.C1;
 import org.apache.ignite.internal.util.typedef.CI1;
 import org.apache.ignite.internal.util.typedef.internal.U;
@@ -29,18 +36,47 @@ import org.apache.ignite.lang.IgniteFuture;
 import org.apache.ignite.lang.IgniteInClosure;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.NotNull;
 
 /**
  *
  */
 public class IgniteFutureImplTest extends GridCommonAbstractTest {
+    /** Context thread name. */
+    private static final String CTX_THREAD_NAME = "test-async";
+
+    /** Custom thread name. */
+    private static final String CUSTOM_THREAD_NAME = "test-custom-async";
+
+    /** Test executor. */
+    private ExecutorService ctxExec;
+
+    /** Custom executor. */
+    private ExecutorService customExec;
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("ExternalizableWithoutPublicNoArgConstructor")
+    @Override protected void beforeTest() throws Exception {
+        ctxExec = createExecutor(CTX_THREAD_NAME);
+        customExec = createExecutor(CUSTOM_THREAD_NAME);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        U.shutdownNow(getClass(), ctxExec, log);
+        U.shutdownNow(getClass(), customExec, log);
+
+        ctxExec = null;
+        customExec = null;
+    }
+
     /**
      * @throws Exception If failed.
      */
     public void testFutureGet() throws Exception {
         GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
 
-        IgniteFutureImpl<String> fut = new IgniteFutureImpl<>(fut0);
+        IgniteFutureImpl<String> fut = createFuture(fut0);
 
         assertFalse(fut.isDone());
 
@@ -59,7 +95,7 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
     public void testFutureException() throws Exception {
         GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
 
-        final IgniteFutureImpl<String> fut = new IgniteFutureImpl<>(fut0);
+        final IgniteFutureImpl<String> fut = createFuture(fut0);
 
         assertFalse(fut.isDone());
 
@@ -69,27 +105,27 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
         fut0.onDone(err0);
 
-        IgniteException err = (IgniteException)GridTestUtils.assertThrows(log, new Callable<Void>() {
+        Exception err = (Exception)GridTestUtils.assertThrows(log, new Callable<Void>() {
             @Override public Void call() throws Exception {
                 fut.get();
 
                 return null;
             }
-        }, IgniteException.class, "test error");
+        }, expectedException(), "test error");
 
-        assertEquals(err0, err.getCause());
+        assertExpectedException(err, err0);
 
         assertTrue(fut.isDone());
 
-        err = (IgniteException)GridTestUtils.assertThrows(log, new Callable<Void>() {
+        err = (Exception)GridTestUtils.assertThrows(log, new Callable<Void>() {
             @Override public Void call() throws Exception {
                 fut.get();
 
                 return null;
             }
-        }, IgniteException.class, null);
+        }, expectedException(), null);
 
-        assertEquals(err0, err.getCause());
+        assertExpectedException(err, err0);
     }
 
     /**
@@ -98,21 +134,21 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
     public void testFutureIgniteException() throws Exception {
         GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
 
-        final IgniteFutureImpl<String> fut = new IgniteFutureImpl<>(fut0);
+        final IgniteFutureImpl<String> fut = createFuture(fut0);
 
         IgniteException err0 = new IgniteException("test error");
 
         fut0.onDone(err0);
 
-        IgniteException err = (IgniteException)GridTestUtils.assertThrows(log, new Callable<Void>() {
+        Exception err = (Exception)GridTestUtils.assertThrows(log, new Callable<Void>() {
             @Override public Void call() throws Exception {
                 fut.get();
 
                 return null;
             }
-        }, IgniteException.class, "test error");
+        }, expectedException(), "test error");
 
-        assertEquals(err0, err);
+        assertExpectedException(err, err0);
     }
 
     /**
@@ -121,7 +157,7 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
     public void testListeners() throws Exception {
         GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
 
-        IgniteFutureImpl<String> fut = new IgniteFutureImpl<>(fut0);
+        IgniteFutureImpl<String> fut = createFuture(fut0);
 
         final AtomicInteger lsnr1Cnt = new AtomicInteger();
 
@@ -166,7 +202,7 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
         {
             GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
 
-            IgniteFutureImpl<String> fut = new IgniteFutureImpl<>(fut0);
+            IgniteFutureImpl<String> fut = createFuture(fut0);
 
             final IgniteException err0 = new IgniteException("test error");
 
@@ -179,8 +215,8 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
                         fail();
                     }
-                    catch (IgniteException err) {
-                        assertEquals(err0, err);
+                    catch (IgniteException | CacheException err) {
+                        assertExpectedException(err, err0);
 
                         passed.set(true);
                     }
@@ -197,7 +233,7 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
         {
             GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
 
-            IgniteFutureImpl<String> fut = new IgniteFutureImpl<>(fut0);
+            IgniteFutureImpl<String> fut = createFuture(fut0);
 
             final IgniteCheckedException err0 = new IgniteCheckedException("test error");
 
@@ -210,8 +246,8 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
                         fail();
                     }
-                    catch (IgniteException err) {
-                        assertEquals(err0, err.getCause());
+                    catch (IgniteException | CacheException err) {
+                        assertExpectedException(err, err0);
 
                         passed.set(true);
                     }
@@ -229,10 +265,130 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    public void testAsyncListeners() throws Exception {
+        GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
+
+        IgniteFutureImpl<String> fut = createFuture(fut0);
+
+        final CountDownLatch latch1 = new CountDownLatch(1);
+
+        IgniteInClosure<? super IgniteFuture<String>> lsnr1 = createAsyncListener(latch1, CUSTOM_THREAD_NAME, null);
+
+        assertFalse(fut.isDone());
+
+        fut.listenAsync(lsnr1, customExec);
+
+        U.sleep(100);
+
+        assertEquals(1, latch1.getCount());
+
+        fut0.onDone("test");
+
+        assert latch1.await(1, TimeUnit.SECONDS) : latch1.getCount();
+
+        checkAsyncListener(fut);
+        checkAsyncListener(createFuture(new GridFinishedFuture<>("test")));
+    }
+
+    /**
+     * @param fut Future.
+     */
+    private void checkAsyncListener(IgniteFutureImpl<String> fut) throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        IgniteInClosure<? super IgniteFuture<String>> lsnr = createAsyncListener(latch, CUSTOM_THREAD_NAME, null);
+
+        fut.listenAsync(lsnr, customExec);
+
+        assert latch.await(1, TimeUnit.SECONDS) : latch.getCount();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testAsyncListenersOnError() throws Exception {
+        checkAsyncListenerOnError(new IgniteException("Test exception"));
+        checkAsyncListenerOnError(new IgniteCheckedException("Test checked exception"));
+    }
+
+    /**
+     * @param err0 Test exception.
+     */
+    private void checkAsyncListenerOnError(Exception err0) throws InterruptedException {
+        GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
+
+        IgniteFutureImpl<String> fut = createFuture(fut0);
+
+        final CountDownLatch latch1 = new CountDownLatch(1);
+
+        IgniteInClosure<? super IgniteFuture<String>> lsnr1 = createAsyncListener(latch1, CUSTOM_THREAD_NAME, err0);
+
+        fut.listenAsync(lsnr1, customExec);
+
+        assertEquals(1, latch1.getCount());
+
+        fut0.onDone(err0);
+
+        assert latch1.await(1, TimeUnit.SECONDS);
+
+        checkAsyncListenerOnError(err0, fut);
+        checkAsyncListenerOnError(err0, createFuture(new GridFinishedFuture<String>(err0)));
+    }
+
+    /**
+     * @param err0 Err 0.
+     * @param fut Future.
+     */
+    private void checkAsyncListenerOnError(Exception err0, IgniteFutureImpl<String> fut) throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        IgniteInClosure<? super IgniteFuture<String>> lsnr = createAsyncListener(latch, CUSTOM_THREAD_NAME, err0);
+
+        fut.listenAsync(lsnr, customExec);
+
+        assert latch.await(1, TimeUnit.SECONDS);
+    }
+
+    /**
+     * @param latch Latch.
+     */
+    @NotNull private CI1<IgniteFuture<String>> createAsyncListener(
+        final CountDownLatch latch,
+        final String threadName,
+        final Exception err
+    ) {
+        return new CI1<IgniteFuture<String>>() {
+            @Override public void apply(IgniteFuture<String> fut) {
+                try {
+                    String tname = Thread.currentThread().getName();
+
+                    assert tname.contains(threadName) : tname;
+
+                    assertEquals("test", fut.get());
+
+                    if (err != null)
+                        fail();
+                }
+                catch (IgniteException | CacheException e) {
+                    if (err != null)
+                        assertExpectedException(e, err);
+                    else
+                        throw e;
+                }
+                finally {
+                    latch.countDown();
+                }
+            }
+        };
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     public void testChain() throws Exception {
         GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
 
-        IgniteFutureImpl<String> fut = new IgniteFutureImpl<>(fut0);
+        IgniteFutureImpl<String> fut = createFuture(fut0);
 
         IgniteFuture<Integer> chained = fut.chain(new C1<IgniteFuture<String>, Integer>() {
             @Override public Integer apply(IgniteFuture<String> fut) {
@@ -274,7 +430,7 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
         {
             GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
 
-            IgniteFutureImpl<String> fut = new IgniteFutureImpl<>(fut0);
+            IgniteFutureImpl<String> fut = createFuture(fut0);
 
             final IgniteException err0 = new IgniteException("test error");
 
@@ -289,8 +445,8 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
                         return -1;
                     }
-                    catch (IgniteException err) {
-                        assertEquals(err0, err);
+                    catch (IgniteException | CacheException err) {
+                        assertExpectedException(err, err0);
 
                         chainedPassed.set(true);
 
@@ -308,8 +464,8 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
                         fail();
                     }
-                    catch (IgniteException err) {
-                        assertEquals(err0, err);
+                    catch (IgniteException | CacheException err) {
+                        assertExpectedException(err, err0);
 
                         lsnrPassed.set(true);
                     }
@@ -329,8 +485,8 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
                 fail();
             }
-            catch (IgniteException err) {
-                assertEquals(err0, err);
+            catch (IgniteException | CacheException err) {
+                assertExpectedException(err, err0);
             }
 
             try {
@@ -338,15 +494,15 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
                 fail();
             }
-            catch (IgniteException err) {
-                assertEquals(err0, err);
+            catch (IgniteException | CacheException err) {
+                assertExpectedException(err, err0);
             }
         }
 
         {
             GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
 
-            IgniteFutureImpl<String> fut = new IgniteFutureImpl<>(fut0);
+            IgniteFutureImpl<String> fut = createFuture(fut0);
 
             final IgniteCheckedException err0 = new IgniteCheckedException("test error");
 
@@ -361,8 +517,8 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
                         return -1;
                     }
-                    catch (IgniteException err) {
-                        assertEquals(err0, err.getCause());
+                    catch (IgniteException | CacheException err) {
+                        assertExpectedException(err, err0);
 
                         chainedPassed.set(true);
 
@@ -380,8 +536,8 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
                         fail();
                     }
-                    catch (IgniteException err) {
-                        assertEquals(err0, err.getCause());
+                    catch (IgniteException | CacheException err) {
+                        assertExpectedException(err, err0);
 
                         lsnrPassed.set(true);
                     }
@@ -401,8 +557,8 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
                 fail();
             }
-            catch (IgniteException err) {
-                assertEquals(err0, err.getCause());
+            catch (IgniteException | CacheException err) {
+                assertExpectedException(err, err0);
             }
 
             try {
@@ -410,9 +566,243 @@ public class IgniteFutureImplTest extends GridCommonAbstractTest {
 
                 fail();
             }
-            catch (IgniteException err) {
-                assertEquals(err0, err.getCause());
+            catch (IgniteException | CacheException err) {
+                assertExpectedException(err, err0);
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testChainAsync() throws Exception {
+        GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
+
+        IgniteFuture<String> fut = createFuture(fut0);
+
+        C1<IgniteFuture<String>, Integer> chainClos = new C1<IgniteFuture<String>, Integer>() {
+            @Override public Integer apply(IgniteFuture<String> fut) {
+                assertEquals(CUSTOM_THREAD_NAME, Thread.currentThread().getName());
+
+                return Integer.valueOf(fut.get());
+            }
+        };
+
+        IgniteFuture<Integer> chained1 = fut.chainAsync(chainClos, customExec);
+
+        assertFalse(chained1.isDone());
+
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        class TestClosure implements CI1<IgniteFuture<Integer>> {
+            private final CountDownLatch latch;
+
+            private TestClosure(CountDownLatch latch) {
+                this.latch = latch;
+            }
+
+            @Override public void apply(IgniteFuture<Integer> fut) {
+                assertEquals(CUSTOM_THREAD_NAME, Thread.currentThread().getName());
+                assertEquals(10, (int)fut.get());
+
+                latch.countDown();
             }
         }
+
+        chained1.listen(new TestClosure(latch));
+
+        fut0.onDone("10");
+
+        // Chained future will be completed asynchronously.
+        chained1.get(100, TimeUnit.MILLISECONDS);
+
+        assertTrue(chained1.isDone());
+
+        assertEquals(10, (int)chained1.get());
+
+        assert latch.await(100, TimeUnit.MILLISECONDS);
+
+        assertTrue(fut.isDone());
+
+        assertEquals("10", fut.get());
+
+        // Test finished future
+        GridFinishedFuture<String> ffut0 = new GridFinishedFuture<>("10");
+
+        CountDownLatch latch1 = new CountDownLatch(1);
+
+        IgniteFuture<Integer> chained2 = createFuture(ffut0).chainAsync(chainClos, customExec);
+
+        chained2.listen(new TestClosure(latch1));
+
+        chained2.get(100, TimeUnit.MILLISECONDS);
+
+        assertTrue(chained2.isDone());
+
+        assertEquals(10, (int)chained2.get());
+
+        assert latch1.await(100, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testChainAsyncOnError() throws Exception {
+        checkChainedOnError(new IgniteException("Test exception"));
+        checkChainedOnError(new IgniteCheckedException("Test checked exception"));
+        checkChainedOnErrorFinishedFuture(new IgniteException("Test exception"));
+        checkChainedOnErrorFinishedFuture(new IgniteCheckedException("Test checked exception"));
+    }
+
+    /**
+     * @param err Exception.
+     * @throws Exception If failed.
+     */
+    private void checkChainedOnError(final Exception err) throws Exception {
+        GridFutureAdapter<String> fut0 = new GridFutureAdapter<>();
+
+        IgniteFutureImpl<String> fut = createFuture(fut0);
+
+        // Chain callback will be invoked in specific executor.
+        IgniteFuture<Integer> chained1 = fut.chainAsync(new C1<IgniteFuture<String>, Integer>() {
+            @Override public Integer apply(IgniteFuture<String> fut) {
+                assertEquals(CUSTOM_THREAD_NAME, Thread.currentThread().getName());
+
+                try {
+                    fut.get();
+
+                    fail();
+                }
+                catch (IgniteException | CacheException e) {
+                    assertExpectedException(e, err);
+
+                    throw e;
+                }
+
+                return -1;
+            }
+        }, customExec);
+
+        assertFalse(chained1.isDone());
+        assertFalse(fut.isDone());
+
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        chained1.listen(new CI1<IgniteFuture<Integer>>() {
+            @Override public void apply(IgniteFuture<Integer> fut) {
+                try {
+                    assertEquals(CUSTOM_THREAD_NAME, Thread.currentThread().getName());
+
+                    fut.get();
+
+                    fail();
+                }
+                catch (IgniteException | CacheException e) {
+                    assertExpectedException(e, err);
+                }
+                finally {
+                    latch.countDown();
+                }
+            }
+        });
+
+        fut0.onDone(err);
+
+        assertExceptionThrown(err, chained1);
+        assertExceptionThrown(err, fut);
+
+        assertTrue(chained1.isDone());
+        assertTrue(fut.isDone());
+
+        assert latch.await(100, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * @param err Err.
+     */
+    private void checkChainedOnErrorFinishedFuture(final Exception err) throws Exception {
+        IgniteFutureImpl<String> fut = createFuture(new GridFinishedFuture<String>(err));
+
+        // Chain callback will be invoked in specific executor.
+        IgniteFuture<Integer> chained1 = fut.chainAsync(new C1<IgniteFuture<String>, Integer>() {
+            @Override public Integer apply(IgniteFuture<String> fut) {
+                assertEquals(CUSTOM_THREAD_NAME, Thread.currentThread().getName());
+
+                try {
+                    fut.get();
+
+                    fail();
+                }
+                catch (IgniteException e) {
+                    assertExpectedException(e, err);
+
+                    throw e;
+                }
+
+                return -1;
+            }
+        }, customExec);
+
+
+        assertExceptionThrown(err, chained1);
+        assertExceptionThrown(err, fut);
+
+        assertTrue(chained1.isDone());
+        assertTrue(fut.isDone());
+    }
+
+    /**
+     * @param err Expected exception.
+     * @param fut Future.
+     */
+    private void assertExceptionThrown(Exception err, IgniteFuture<?> fut) {
+        try {
+            fut.get();
+
+            fail();
+        }
+        catch (IgniteException | CacheException e) {
+            assertExpectedException(e, err);
+        }
+    }
+
+    /**
+     * @param e Actual exception.
+     * @param exp Expected exception.
+     */
+    protected void assertExpectedException(Exception e, Exception exp) {
+        if (exp instanceof IgniteException)
+            assertEquals(exp, e);
+        else
+            assertEquals(exp, e.getCause());
+    }
+
+    /**
+     * @param name Name.
+     */
+    @NotNull private ExecutorService createExecutor(final String name) {
+        return Executors.newSingleThreadExecutor(new ThreadFactory() {
+            @Override public Thread newThread(@NotNull Runnable r) {
+                Thread t = new Thread(r);
+
+                t.setName(name);
+
+                return t;
+            }
+        });
+    }
+
+    /**
+     * @param fut Future.
+     */
+    protected <V> IgniteFutureImpl<V> createFuture(IgniteInternalFuture<V> fut) {
+        return new IgniteFutureImpl<>(fut);
+    }
+
+    /**
+     *
+     */
+    protected Class<? extends Exception> expectedException() {
+        return IgniteException.class;
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/b375c1ef/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteLangSelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteLangSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteLangSelfTestSuite.java
index cfec1ec..70aec72 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteLangSelfTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteLangSelfTestSuite.java
@@ -21,6 +21,7 @@ import junit.framework.TestSuite;
 import org.apache.ignite.internal.util.future.GridCompoundFutureSelfTest;
 import org.apache.ignite.internal.util.future.GridEmbeddedFutureSelfTest;
 import org.apache.ignite.internal.util.future.GridFutureAdapterSelfTest;
+import org.apache.ignite.internal.util.future.IgniteCacheFutureImplTest;
 import org.apache.ignite.internal.util.future.IgniteFutureImplTest;
 import org.apache.ignite.internal.util.future.nio.GridNioEmbeddedFutureSelfTest;
 import org.apache.ignite.internal.util.future.nio.GridNioFutureSelfTest;
@@ -80,7 +81,9 @@ public class IgniteLangSelfTestSuite extends TestSuite {
         suite.addTest(new TestSuite(GridEmbeddedFutureSelfTest.class));
         suite.addTest(new TestSuite(GridNioFutureSelfTest.class));
         suite.addTest(new TestSuite(GridNioEmbeddedFutureSelfTest.class));
+
         suite.addTest(new TestSuite(IgniteFutureImplTest.class));
+        suite.addTest(new TestSuite(IgniteCacheFutureImplTest.class));
 
         // Consistent hash tests.
         suite.addTest(new TestSuite(GridConsistentHashSelfTest.class));

http://git-wip-us.apache.org/repos/asf/ignite/blob/b375c1ef/modules/schedule/src/main/java/org/apache/ignite/internal/processors/schedule/ScheduleFutureImpl.java
----------------------------------------------------------------------
diff --git a/modules/schedule/src/main/java/org/apache/ignite/internal/processors/schedule/ScheduleFutureImpl.java b/modules/schedule/src/main/java/org/apache/ignite/internal/processors/schedule/ScheduleFutureImpl.java
index 63a6164..e3c743c 100644
--- a/modules/schedule/src/main/java/org/apache/ignite/internal/processors/schedule/ScheduleFutureImpl.java
+++ b/modules/schedule/src/main/java/org/apache/ignite/internal/processors/schedule/ScheduleFutureImpl.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.regex.Matcher;
@@ -35,6 +36,7 @@ import org.apache.ignite.IgniteInterruptedException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.timeout.GridTimeoutObjectAdapter;
+import org.apache.ignite.internal.util.future.AsyncFutureListener;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.future.IgniteFutureImpl;
 import org.apache.ignite.internal.util.lang.GridClosureException;
@@ -579,15 +581,42 @@ class ScheduleFutureImpl<R> implements SchedulerFuture<R> {
     }
 
     /** {@inheritDoc} */
+    @Override public void listenAsync(IgniteInClosure<? super IgniteFuture<R>> lsnr, Executor exec) {
+        A.notNull(lsnr, "lsnr");
+        A.notNull(exec, "exec");
+
+        listen(new AsyncFutureListener<>(lsnr, exec));
+    }
+
+    /** {@inheritDoc} */
     @SuppressWarnings("ExternalizableWithoutPublicNoArgConstructor")
     @Override public <T> IgniteFuture<T> chain(final IgniteClosure<? super IgniteFuture<R>, T> doneCb) {
-        final GridFutureAdapter<T> fut = new GridFutureAdapter() {
+        A.notNull(doneCb, "doneCb");
+
+        return chain(doneCb, null);
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> IgniteFuture<T> chainAsync(IgniteClosure<? super IgniteFuture<R>, T> doneCb, Executor exec) {
+        A.notNull(doneCb, "");
+        A.notNull(exec, "exec");
+
+        return chain(doneCb, exec);
+    }
+
+    /**
+     * @param doneCb Done callback.
+     * @param exec Executor.
+     * @return Chained future.
+     */
+    private <T> IgniteFuture<T> chain(final IgniteClosure<? super IgniteFuture<R>, T> doneCb, @Nullable Executor exec) {
+        final GridFutureAdapter<T> fut = new GridFutureAdapter<T>() {
             @Override public String toString() {
                 return "ChainFuture[orig=" + ScheduleFutureImpl.this + ", doneCb=" + doneCb + ']';
             }
         };
 
-        listen(new CI1<IgniteFuture<R>>() {
+        IgniteInClosure<? super IgniteFuture<R>> lsnr = new CI1<IgniteFuture<R>>() {
             @Override public void apply(IgniteFuture<R> fut0) {
                 try {
                     fut.onDone(doneCb.apply(fut0));
@@ -607,7 +636,12 @@ class ScheduleFutureImpl<R> implements SchedulerFuture<R> {
                     throw e;
                 }
             }
-        });
+        };
+
+        if (exec != null)
+            lsnr = new AsyncFutureListener<>(lsnr, exec);
+
+        listen(lsnr);
 
         return new IgniteFutureImpl<>(fut);
     }
@@ -861,9 +895,20 @@ class ScheduleFutureImpl<R> implements SchedulerFuture<R> {
         }
 
         /** {@inheritDoc} */
+        @Override public void listenAsync(IgniteInClosure<? super IgniteFuture<R>> lsnr, Executor exec) {
+            ref.listenAsync(lsnr, exec);
+        }
+
+        /** {@inheritDoc} */
         @Override public <T> IgniteFuture<T> chain(IgniteClosure<? super IgniteFuture<R>, T> doneCb) {
             return ref.chain(doneCb);
         }
+
+        /** {@inheritDoc} */
+        @Override public <T> IgniteFuture<T> chainAsync(IgniteClosure<? super IgniteFuture<R>, T> doneCb,
+            Executor exec) {
+            return ref.chainAsync(doneCb, exec);
+        }
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b375c1ef/modules/schedule/src/test/java/org/apache/ignite/internal/processors/schedule/GridScheduleSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/schedule/src/test/java/org/apache/ignite/internal/processors/schedule/GridScheduleSelfTest.java b/modules/schedule/src/test/java/org/apache/ignite/internal/processors/schedule/GridScheduleSelfTest.java
index f0860f2..122d98d 100644
--- a/modules/schedule/src/test/java/org/apache/ignite/internal/processors/schedule/GridScheduleSelfTest.java
+++ b/modules/schedule/src/test/java/org/apache/ignite/internal/processors/schedule/GridScheduleSelfTest.java
@@ -19,21 +19,29 @@ package org.apache.ignite.internal.processors.schedule;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.internal.util.lang.GridTuple;
 import org.apache.ignite.internal.util.typedef.CI1;
+import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteCallable;
+import org.apache.ignite.lang.IgniteClosure;
 import org.apache.ignite.lang.IgniteFuture;
+import org.apache.ignite.lang.IgniteInClosure;
 import org.apache.ignite.lang.IgniteRunnable;
 import org.apache.ignite.resources.IgniteInstanceResource;
 import org.apache.ignite.resources.LoggerResource;
 import org.apache.ignite.scheduler.SchedulerFuture;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.NotNull;
 
 import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.ignite.testframework.GridTestUtils.assertThrows;
 
 /**
  * Test for task scheduler.
@@ -43,9 +51,15 @@ public class GridScheduleSelfTest extends GridCommonAbstractTest {
     /** */
     private static final int NODES_CNT = 2;
 
+    /** Custom thread name. */
+    private static final String CUSTOM_THREAD_NAME = "custom-async-test";
+
     /** */
     private static AtomicInteger execCntr = new AtomicInteger(0);
 
+    /** Custom executor. */
+    private ExecutorService exec;
+
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         startGrids(NODES_CNT);
@@ -61,6 +75,22 @@ public class GridScheduleSelfTest extends GridCommonAbstractTest {
     /** {@inheritDoc} */
     @Override protected void beforeTest() throws Exception {
         execCntr.set(0);
+        exec = Executors.newSingleThreadExecutor(new ThreadFactory() {
+            @Override public Thread newThread(@NotNull Runnable r) {
+                Thread t = new Thread(r);
+
+                t.setName(CUSTOM_THREAD_NAME);
+
+                return t;
+            }
+        });
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        U.shutdownNow(getClass(), exec, log);
+
+        exec = null;
     }
 
     /**
@@ -124,6 +154,54 @@ public class GridScheduleSelfTest extends GridCommonAbstractTest {
                 }
             });
 
+            final SchedulerFuture<?> fut0 = fut;
+
+            //noinspection ThrowableNotThrown
+            assertThrows(log, new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    fut0.listenAsync(new IgniteInClosure<IgniteFuture<?>>() {
+                        @Override public void apply(IgniteFuture<?> fut) {
+                            // No-op
+                        }
+                    }, null);
+
+                    return null;
+                }
+            }, NullPointerException.class, null);
+
+            fut.listenAsync(new IgniteInClosure<IgniteFuture<?>>() {
+                @Override public void apply(IgniteFuture<?> fut) {
+                    assertEquals(Thread.currentThread().getName(), CUSTOM_THREAD_NAME);
+
+                    notifyCnt.incrementAndGet();
+                }
+            }, exec);
+
+            //noinspection ThrowableNotThrown
+            assertThrows(log, new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    fut0.chainAsync(new IgniteClosure<IgniteFuture<?>, String>() {
+                        @Override public String apply(IgniteFuture<?> fut) {
+                            // No-op
+
+                            return null;
+                        }
+                    }, null);
+
+                    return null;
+                }
+            }, NullPointerException.class, null);
+
+            IgniteFuture<String> chained1 = fut.chainAsync(new IgniteClosure<IgniteFuture<?>, String>() {
+                @Override public String apply(IgniteFuture<?> fut) {
+                    assertEquals(Thread.currentThread().getName(), CUSTOM_THREAD_NAME);
+
+                    fut.get();
+
+                    return "done-custom";
+                }
+            }, exec);
+
             long timeTillRun = freq + delay;
 
             info("Going to wait for the first run: " + timeTillRun);
@@ -135,6 +213,7 @@ public class GridScheduleSelfTest extends GridCommonAbstractTest {
             assert !fut.isDone();
             assert !fut.isCancelled();
             assert fut.last() == null;
+            assertFalse(chained1.isDone());
 
             info("Going to wait for 2nd run: " + timeTillRun);
 
@@ -142,10 +221,13 @@ public class GridScheduleSelfTest extends GridCommonAbstractTest {
             Thread.sleep(timeTillRun * 1000);
 
             assert fut.isDone();
-            assert notifyCnt.get() == 2;
+            assert notifyCnt.get() == 2 * 2;
             assert !fut.isCancelled();
             assert fut.last() == null;
 
+            assertEquals("done-custom", chained1.get());
+
+            assertTrue(chained1.isDone());
         }
         finally {
             assert fut != null;


[09/50] [abbrv] ignite git commit: IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
new file mode 100644
index 0000000..136fcf9
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
@@ -0,0 +1,309 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.Logger;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream;
+import org.apache.ignite.internal.binary.streams.BinaryHeapOutputStream;
+import org.apache.ignite.internal.processors.odbc.SqlListenerNioListener;
+import org.apache.ignite.internal.processors.odbc.SqlListenerProtocolVersion;
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
+import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteRequest;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataRequest;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcUtils;
+import org.apache.ignite.internal.util.ipc.IpcEndpoint;
+import org.apache.ignite.internal.util.ipc.IpcEndpointFactory;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ * JDBC IO layer implementation based on blocking IPC streams.
+ */
+public class JdbcThinTcpIo {
+    /** Current version. */
+    private static final SqlListenerProtocolVersion CURRENT_VER = SqlListenerProtocolVersion.create(2, 1, 0);
+
+    /** Initial output stream capacity for handshake. */
+    private static final int HANDSHAKE_MSG_SIZE = 10;
+
+    /** Initial output for query message. */
+    private static final int QUERY_EXEC_MSG_INIT_CAP = 1024;
+
+    /** Initial output for query fetch message. */
+    private static final int QUERY_FETCH_MSG_SIZE = 13;
+
+    /** Initial output for query fetch message. */
+    private static final int QUERY_META_MSG_SIZE = 9;
+
+    /** Initial output for query close message. */
+    private static final int QUERY_CLOSE_MSG_SIZE = 9;
+
+    /** Logger. */
+    private static final Logger log = Logger.getLogger(JdbcThinTcpIo.class.getName());
+
+    /** Server endpoint address. */
+    private final String endpointAddr;
+
+    /** Endpoint. */
+    private IpcEndpoint endpoint;
+
+    /** Output stream. */
+    private BufferedOutputStream out;
+
+    /** Input stream. */
+    private BufferedInputStream in;
+
+    /** Distributed joins. */
+    private boolean distributedJoins;
+
+    /** Enforce join order. */
+    private boolean enforceJoinOrder;
+
+    /** Closed flag. */
+    private boolean closed;
+
+    /**
+     * @param endpointAddr Endpoint.
+     * @param distributedJoins Distributed joins flag.
+     * @param enforceJoinOrder Enforce join order flag.
+     */
+    JdbcThinTcpIo(String endpointAddr, boolean distributedJoins, boolean enforceJoinOrder) {
+        assert endpointAddr != null;
+
+        this.endpointAddr = endpointAddr;
+        this.distributedJoins = distributedJoins;
+        this.enforceJoinOrder= enforceJoinOrder;
+    }
+
+    /**
+     * @throws IgniteCheckedException On error.
+     * @throws IOException On IO error in handshake.
+     */
+    public void start() throws IgniteCheckedException, IOException {
+        endpoint = IpcEndpointFactory.connectEndpoint(endpointAddr, null);
+
+        out = new BufferedOutputStream(endpoint.outputStream());
+        in = new BufferedInputStream(endpoint.inputStream());
+
+        handshake();
+    }
+
+    /**
+     * @throws IOException On error.
+     * @throws IgniteCheckedException On error.
+     */
+    public void handshake() throws IOException, IgniteCheckedException {
+        BinaryWriterExImpl writer = new BinaryWriterExImpl(null, new BinaryHeapOutputStream(HANDSHAKE_MSG_SIZE),
+            null, null);
+
+        writer.writeByte((byte)SqlListenerRequest.HANDSHAKE);
+
+        writer.writeShort(CURRENT_VER.major());
+        writer.writeShort(CURRENT_VER.minor());
+        writer.writeShort(CURRENT_VER.maintenance());
+
+        writer.writeByte(SqlListenerNioListener.JDBC_CLIENT);
+
+        writer.writeBoolean(distributedJoins);
+        writer.writeBoolean(enforceJoinOrder);
+
+        send(writer.array());
+
+        BinaryReaderExImpl reader = new BinaryReaderExImpl(null, new BinaryHeapInputStream(read()),
+            null, null, false);
+
+        boolean accepted = reader.readBoolean();
+
+        if (accepted)
+            return;
+
+        short maj = reader.readShort();
+        short min = reader.readShort();
+        short maintenance = reader.readShort();
+
+        String err = reader.readString();
+
+        SqlListenerProtocolVersion ver = SqlListenerProtocolVersion.create(maj, min, maintenance);
+
+        throw new IgniteCheckedException("Handshake failed [driverProtocolVer=" + CURRENT_VER +
+            ", remoteNodeProtocolVer=" + ver + ", err=" + err + ']');
+    }
+
+    /**
+     * @param cache Cache name.
+     * @param fetchSize Fetch size.
+     * @param maxRows Max rows.
+     * @param sql SQL statement.
+     * @param args Query parameters.
+     * @return Execute query results.
+     * @throws IOException On error.
+     * @throws IgniteCheckedException On error.
+     */
+    public JdbcQueryExecuteResult queryExecute(String cache, int fetchSize, int maxRows,
+        String sql, List<Object> args)
+        throws IOException, IgniteCheckedException {
+        return sendRequest(new JdbcQueryExecuteRequest(cache, fetchSize, maxRows, sql,
+            args == null ? null : args.toArray(new Object[args.size()])), QUERY_EXEC_MSG_INIT_CAP);
+    }
+
+    /**
+     * @param req Request.
+     * @param cap Initial ouput stream capacity.
+     * @return Server response.
+     * @throws IOException On IO error.
+     * @throws IgniteCheckedException On error.
+     */
+    @SuppressWarnings("unchecked")
+    public <R extends JdbcResult> R sendRequest(JdbcRequest req, int cap) throws IOException, IgniteCheckedException {
+        BinaryWriterExImpl writer = new BinaryWriterExImpl(null, new BinaryHeapOutputStream(cap), null, null);
+
+        req.writeBinary(writer);
+
+        send(writer.array());
+
+        BinaryReaderExImpl reader = new BinaryReaderExImpl(null, new BinaryHeapInputStream(read()), null, null, false);
+
+        JdbcResponse res = new JdbcResponse();
+
+        res.readBinary(reader);
+
+        if (res.status() != SqlListenerResponse.STATUS_SUCCESS)
+            throw new IgniteCheckedException("Error server response: [req=" + req + ", resp=" + res + ']');
+
+        return (R)res.response();
+    }
+
+    /**
+     * @param qryId Query ID.
+     * @param pageSize pageSize.
+     * @return Fetch results.
+     * @throws IOException On error.
+     * @throws IgniteCheckedException On error.
+     */
+    public JdbcQueryFetchResult queryFetch(Long qryId, int pageSize)
+        throws IOException, IgniteCheckedException {
+        return sendRequest(new JdbcQueryFetchRequest(qryId, pageSize), QUERY_FETCH_MSG_SIZE);
+    }
+
+
+    /**
+     * @param qryId Query ID.
+     * @return Fetch results.
+     * @throws IOException On error.
+     * @throws IgniteCheckedException On error.
+     */
+    public JdbcQueryMetadataResult queryMeta(Long qryId)
+        throws IOException, IgniteCheckedException {
+        return sendRequest(new JdbcQueryMetadataRequest(qryId), QUERY_META_MSG_SIZE);
+    }
+
+    /**
+     * @param qryId Query ID.
+     * @throws IOException On error.
+     * @throws IgniteCheckedException On error.
+     */
+    public void queryClose(long qryId) throws IOException, IgniteCheckedException {
+        sendRequest(new JdbcQueryCloseRequest(qryId), QUERY_CLOSE_MSG_SIZE);
+    }
+
+    /**
+     * @param req ODBC request.
+     * @throws IOException On error.
+     */
+    private void send(byte[] req) throws IOException {
+        int size = req.length;
+
+        out.write(size & 0xFF);
+        out.write((size >> 8) & 0xFF);
+        out.write((size >> 16) & 0xFF);
+        out.write((size >> 24) & 0xFF);
+
+        out.write(req);
+
+        out.flush();
+    }
+
+    /**
+     * @return Bytes of a response from server.
+     * @throws IOException On error.
+     * @throws IgniteCheckedException On error.
+     */
+    private byte[] read() throws IOException, IgniteCheckedException {
+        byte[] sizeBytes = read(4);
+
+        int msgSize  = (((0xFF & sizeBytes[3]) << 24) | ((0xFF & sizeBytes[2]) << 16)
+            | ((0xFF & sizeBytes[1]) << 8) + (0xFF & sizeBytes[0]));
+
+        return read(msgSize);
+    }
+
+    /**
+     * @param size Count of bytes to read from stream.
+     * @return Read bytes.
+     * @throws IOException On error.
+     * @throws IgniteCheckedException On error.
+     */
+    private byte [] read(int size) throws IOException, IgniteCheckedException {
+        int off = 0;
+
+        byte[] data = new byte[size];
+
+        while (off != size) {
+            int res = in.read(data, off, size - off);
+
+            if (res == -1)
+                throw new IgniteCheckedException("Failed to read incoming message (not enough data).");
+
+            off += res;
+        }
+
+        return data;
+    }
+
+    /**
+     * Close the client IO.
+     */
+    public void close() {
+        if (closed)
+            return;
+
+        // Clean up resources.
+        U.closeQuiet(out);
+        U.closeQuiet(in);
+
+        if (endpoint != null)
+            endpoint.close();
+
+        closed = true;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
new file mode 100644
index 0000000..7f4c111
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
@@ -0,0 +1,152 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.Date;
+
+import static java.sql.Types.BIGINT;
+import static java.sql.Types.BINARY;
+import static java.sql.Types.BOOLEAN;
+import static java.sql.Types.DATE;
+import static java.sql.Types.DOUBLE;
+import static java.sql.Types.FLOAT;
+import static java.sql.Types.INTEGER;
+import static java.sql.Types.OTHER;
+import static java.sql.Types.SMALLINT;
+import static java.sql.Types.TIME;
+import static java.sql.Types.TIMESTAMP;
+import static java.sql.Types.TINYINT;
+import static java.sql.Types.VARCHAR;
+
+/**
+ * Utility methods for thin JDBC driver.
+ */
+public class JdbcThinUtils {
+    /**
+     * Converts Java class name to type from {@link Types}.
+     *
+     * @param cls Java class name.
+     * @return Type from {@link Types}.
+     */
+    @SuppressWarnings("IfMayBeConditional")
+    public static int type(String cls) {
+        if (Boolean.class.getName().equals(cls) || boolean.class.getName().equals(cls))
+            return BOOLEAN;
+        else if (Byte.class.getName().equals(cls) || byte.class.getName().equals(cls))
+            return TINYINT;
+        else if (Short.class.getName().equals(cls) || short.class.getName().equals(cls))
+            return SMALLINT;
+        else if (Integer.class.getName().equals(cls) || int.class.getName().equals(cls))
+            return INTEGER;
+        else if (Long.class.getName().equals(cls) || long.class.getName().equals(cls))
+            return BIGINT;
+        else if (Float.class.getName().equals(cls) || float.class.getName().equals(cls))
+            return FLOAT;
+        else if (Double.class.getName().equals(cls) || double.class.getName().equals(cls))
+            return DOUBLE;
+        else if (String.class.getName().equals(cls))
+            return VARCHAR;
+        else if (byte[].class.getName().equals(cls))
+            return BINARY;
+        else if (Time.class.getName().equals(cls))
+            return TIME;
+        else if (Timestamp.class.getName().equals(cls))
+            return TIMESTAMP;
+        else if (Date.class.getName().equals(cls))
+            return DATE;
+        else
+            return OTHER;
+    }
+
+    /**
+     * Converts Java class name to SQL type name.
+     *
+     * @param cls Java class name.
+     * @return SQL type name.
+     */
+    @SuppressWarnings("IfMayBeConditional")
+    public static String typeName(String cls) {
+        if (Boolean.class.getName().equals(cls) || boolean.class.getName().equals(cls))
+            return "BOOLEAN";
+        else if (Byte.class.getName().equals(cls) || byte.class.getName().equals(cls))
+            return "TINYINT";
+        else if (Short.class.getName().equals(cls) || short.class.getName().equals(cls))
+            return "SMALLINT";
+        else if (Integer.class.getName().equals(cls) || int.class.getName().equals(cls))
+            return "INTEGER";
+        else if (Long.class.getName().equals(cls) || long.class.getName().equals(cls))
+            return "BIGINT";
+        else if (Float.class.getName().equals(cls) || float.class.getName().equals(cls))
+            return "FLOAT";
+        else if (Double.class.getName().equals(cls) || double.class.getName().equals(cls))
+            return "DOUBLE";
+        else if (String.class.getName().equals(cls))
+            return "VARCHAR";
+        else if (byte[].class.getName().equals(cls))
+            return "BINARY";
+        else if (Time.class.getName().equals(cls))
+            return "TIME";
+        else if (Timestamp.class.getName().equals(cls))
+            return "TIMESTAMP";
+        else if (Date.class.getName().equals(cls))
+            return "DATE";
+        else
+            return "OTHER";
+    }
+
+    /**
+     * @param type a value from <code>java.sql.Types</code>.
+     * @return {@code true} if type is plain and supported by thin JDBC driver.
+     */
+    public static boolean isPlainJdbcType(int type) {
+        return type != Types.ARRAY
+            && type != Types.BLOB
+            && type != Types.CLOB
+            && type != Types.DATALINK
+            && type != Types.JAVA_OBJECT
+            && type != Types.NCHAR
+            && type != Types.NVARCHAR
+            && type != Types.LONGNVARCHAR
+            && type != Types.REF
+            && type != Types.NCHAR
+            && type != Types.ROWID
+            && type != Types.SQLXML;
+    }
+
+    /**
+     * Determines whether type is nullable.
+     *
+     * @param name Column name.
+     * @param cls Java class name.
+     * @return {@code True} if nullable.
+     */
+    public static boolean nullable(String name, String cls) {
+        return !"_KEY".equalsIgnoreCase(name) &&
+            !"_VAL".equalsIgnoreCase(name) &&
+            !(boolean.class.getName().equals(cls) ||
+            byte.class.getName().equals(cls) ||
+            short.class.getName().equals(cls) ||
+            int.class.getName().equals(cls) ||
+            long.class.getName().equals(cls) ||
+            float.class.getName().equals(cls) ||
+            double.class.getName().equals(cls));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaRequest.java
deleted file mode 100644
index bdfaa1d..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaRequest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import org.apache.ignite.internal.util.typedef.internal.S;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * ODBC query get columns meta request.
- */
-public class OdbcQueryGetColumnsMetaRequest extends SqlListenerRequest {
-    /** Cache name. */
-    private final String cacheName;
-
-    /** Table name. */
-    private final String tableName;
-
-    /** Column name. */
-    private final String columnName;
-
-    /**
-     * @param cacheName Cache name.
-     * @param tableName Table name.
-     * @param columnName Column name.
-     */
-    public OdbcQueryGetColumnsMetaRequest(String cacheName, String tableName, String columnName) {
-        super(META_COLS);
-
-        this.cacheName = cacheName;
-        this.tableName = tableName;
-        this.columnName = columnName;
-    }
-
-    /**
-     * @return Cache name.
-     */
-    @Nullable public String cacheName() {
-        return cacheName;
-    }
-
-    /**
-     * @return Table name.
-     */
-    public String tableName() {
-        return tableName;
-    }
-
-    /**
-     * @return Column name.
-     */
-    public String columnName() {
-        return columnName;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(OdbcQueryGetColumnsMetaRequest.class, this);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaResult.java
deleted file mode 100644
index 28daa56..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaResult.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import java.util.Collection;
-
-/**
- * Query get columns meta result.
- */
-public class OdbcQueryGetColumnsMetaResult {
-    /** Query result rows. */
-    private final Collection<SqlListenerColumnMeta> meta;
-
-    /**
-     * @param meta Column metadata.
-     */
-    public OdbcQueryGetColumnsMetaResult(Collection<SqlListenerColumnMeta> meta) {
-        this.meta = meta;
-    }
-
-    /**
-     * @return Query result rows.
-     */
-    public Collection<SqlListenerColumnMeta> meta() {
-        return meta;
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetParamsMetaRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetParamsMetaRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetParamsMetaRequest.java
deleted file mode 100644
index e6a97e3..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetParamsMetaRequest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import org.apache.ignite.internal.util.typedef.internal.S;
-
-/**
- * ODBC query get params meta request.
- */
-public class OdbcQueryGetParamsMetaRequest extends SqlListenerRequest {
-    /** Cache. */
-    private final String cacheName;
-
-    /** Query. */
-    private final String query;
-
-    /**
-     * @param query SQL Query.
-     */
-    public OdbcQueryGetParamsMetaRequest(String cacheName, String query) {
-        super(META_PARAMS);
-
-        this.cacheName = cacheName;
-        this.query = query;
-    }
-
-    /**
-     * @return SQL Query.
-     */
-    public String query() {
-        return query;
-    }
-
-    /**
-     * @return Cache name.
-     */
-    public String cacheName() {
-        return cacheName;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(OdbcQueryGetParamsMetaRequest.class, this);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetParamsMetaResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetParamsMetaResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetParamsMetaResult.java
deleted file mode 100644
index 616c82d..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetParamsMetaResult.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-/**
- * ODBC query get params meta result.
- */
-public class OdbcQueryGetParamsMetaResult {
-    /** List of parameter type IDs. */
-    private final byte[] typeIds;
-
-    /**
-     * @param typeIds List of parameter type IDs.
-     */
-    public OdbcQueryGetParamsMetaResult(byte[] typeIds) {
-        this.typeIds = typeIds;
-    }
-
-    /**
-     * @return List of parameter type IDs.
-     */
-    public byte[] typeIds() {
-        return typeIds;
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaRequest.java
deleted file mode 100644
index 772c487..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaRequest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import org.apache.ignite.internal.util.typedef.internal.S;
-
-/**
- * ODBC query get tables meta request.
- */
-public class OdbcQueryGetTablesMetaRequest extends SqlListenerRequest {
-    /** Catalog search pattern. */
-    private final String catalog;
-
-    /** Schema search pattern. */
-    private final String schema;
-
-    /** Table search pattern. */
-    private final String table;
-
-    /** Table type search pattern. */
-    private final String tableType;
-
-    /**
-     * @param catalog Catalog search pattern.
-     * @param schema Schema search pattern.
-     * @param table Table search pattern.
-     * @param tableType Table type search pattern.
-     */
-    public OdbcQueryGetTablesMetaRequest(String catalog, String schema, String table, String tableType) {
-        super(META_TBLS);
-
-        this.catalog = catalog;
-        this.schema = schema;
-        this.table = table;
-        this.tableType = tableType;
-    }
-
-    /**
-     * @return catalog search pattern.
-     */
-    public String catalog() {
-        return catalog;
-    }
-
-    /**
-     * @return Schema search pattern.
-     */
-    public String schema() {
-        return schema;
-    }
-
-    /**
-     * @return Table search pattern.
-     */
-    public String table() {
-        return table;
-    }
-
-    /**
-     * @return Table type search pattern.
-     */
-    public String tableType() {
-        return tableType;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(OdbcQueryGetTablesMetaRequest.class, this);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaResult.java
deleted file mode 100644
index 27bebd6..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaResult.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import java.util.Collection;
-
-/**
- * Query get columns meta result.
- */
-public class OdbcQueryGetTablesMetaResult {
-    /** Query result rows. */
-    private final Collection<OdbcTableMeta> meta;
-
-    /**
-     * @param meta Column metadata.
-     */
-    public OdbcQueryGetTablesMetaResult(Collection<OdbcTableMeta> meta) {
-        this.meta = meta;
-    }
-
-    /**
-     * @return Query result rows.
-     */
-    public Collection<OdbcTableMeta> meta() {
-        return meta;
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTableMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTableMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTableMeta.java
deleted file mode 100644
index ca630dd..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTableMeta.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import org.apache.ignite.internal.binary.BinaryRawWriterEx;
-
-import java.util.Objects;
-
-/**
- * ODBC table-related metadata.
- */
-public class OdbcTableMeta {
-    /** Catalog name. */
-    private final String catalog;
-
-    /** Schema name. */
-    private final String schema;
-
-    /** Table name. */
-    private final String table;
-
-    /** Table type. */
-    private final String tableType;
-
-    /**
-     * @param catalog Catalog name.
-     * @param schema Schema name.
-     * @param table Table name.
-     * @param tableType Table type.
-     */
-    public OdbcTableMeta(String catalog, String schema, String table, String tableType) {
-        this.catalog = catalog;
-        this.schema = OdbcUtils.addQuotationMarksIfNeeded(schema);
-        this.table = table;
-        this.tableType = tableType;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int hashCode() {
-        int hash = Objects.hashCode(catalog);
-
-        hash = 31 * hash + Objects.hashCode(schema);
-        hash = 31 * hash + Objects.hashCode(table);
-        hash = 31 * hash + Objects.hashCode(tableType);
-
-        return hash;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean equals(Object o) {
-        if (o instanceof OdbcTableMeta) {
-            OdbcTableMeta other = (OdbcTableMeta) o;
-
-            return this == other ||
-                    Objects.equals(catalog, other.catalog) && Objects.equals(schema, other.schema) &&
-                    Objects.equals(table, other.table) && Objects.equals(tableType, other.tableType);
-        }
-
-        return false;
-    }
-
-    /**
-     * Write in a binary format.
-     *
-     * @param writer Binary writer.
-     */
-    public void writeBinary(BinaryRawWriterEx writer) {
-        writer.writeString(catalog);
-        writer.writeString(schema);
-        writer.writeString(table);
-        writer.writeString(tableType);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractMessageParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractMessageParser.java
deleted file mode 100644
index 9d731ab..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractMessageParser.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import java.util.Collection;
-import org.apache.ignite.IgniteException;
-import org.apache.ignite.IgniteLogger;
-import org.apache.ignite.internal.GridKernalContext;
-import org.apache.ignite.internal.binary.BinaryReaderExImpl;
-import org.apache.ignite.internal.binary.BinaryWriterExImpl;
-
-/**
- * ODBC message parser.
- */
-public abstract class SqlListenerAbstractMessageParser implements SqlListenerMessageParser {
-    /** Initial output stream capacity. */
-    protected static final int INIT_CAP = 1024;
-
-    /** Kernal context. */
-    protected GridKernalContext ctx;
-
-    /** Logger. */
-    private final IgniteLogger log;
-
-    /** Object reader. */
-    private SqlListenerAbstractObjectReader objReader;
-
-    /** Object writer. */
-    private SqlListenerAbstractObjectWriter objWriter;
-
-    /**
-     * @param ctx Context.
-     * @param objReader Object reader.
-     * @param objWriter Object writer.
-     */
-    protected SqlListenerAbstractMessageParser(final GridKernalContext ctx, SqlListenerAbstractObjectReader objReader,
-        SqlListenerAbstractObjectWriter objWriter) {
-        this.ctx = ctx;
-
-        log = ctx.log(getClass());
-
-        this.objReader = objReader;
-        this.objWriter = objWriter;
-    }
-
-    /** {@inheritDoc} */
-    @Override public SqlListenerRequest decode(byte[] msg) {
-        assert msg != null;
-
-        BinaryReaderExImpl reader = createReader(msg);
-
-        byte cmd = reader.readByte();
-
-        SqlListenerRequest res;
-
-        switch (cmd) {
-            case SqlListenerRequest.QRY_EXEC: {
-                String cache = reader.readString();
-                String sql = reader.readString();
-                int argsNum = reader.readInt();
-
-                Object[] params = new Object[argsNum];
-
-                for (int i = 0; i < argsNum; ++i)
-                    params[i] = objReader.readObject(reader);
-
-                res = new SqlListenerQueryExecuteRequest(cache, sql, params);
-
-                break;
-            }
-
-            case SqlListenerRequest.QRY_FETCH: {
-                long queryId = reader.readLong();
-                int pageSize = reader.readInt();
-
-                res = new SqlListenerQueryFetchRequest(queryId, pageSize);
-
-                break;
-            }
-
-            case SqlListenerRequest.QRY_CLOSE: {
-                long queryId = reader.readLong();
-
-                res = new SqlListenerQueryCloseRequest(queryId);
-
-                break;
-            }
-
-            case SqlListenerRequest.META_COLS: {
-                String cache = reader.readString();
-                String table = reader.readString();
-                String column = reader.readString();
-
-                res = new OdbcQueryGetColumnsMetaRequest(cache, table, column);
-
-                break;
-            }
-
-            case SqlListenerRequest.META_TBLS: {
-                String catalog = reader.readString();
-                String schema = reader.readString();
-                String table = reader.readString();
-                String tableType = reader.readString();
-
-                res = new OdbcQueryGetTablesMetaRequest(catalog, schema, table, tableType);
-
-                break;
-            }
-
-            case SqlListenerRequest.META_PARAMS: {
-                String cacheName = reader.readString();
-                String sqlQuery = reader.readString();
-
-                res = new OdbcQueryGetParamsMetaRequest(cacheName, sqlQuery);
-
-                break;
-            }
-
-            default:
-                throw new IgniteException("Unknown ODBC command: [cmd=" + cmd + ']');
-        }
-
-        return res;
-    }
-
-    /** {@inheritDoc} */
-    @Override public byte[] encode(SqlListenerResponse msg) {
-        assert msg != null;
-
-        // Creating new binary writer
-        BinaryWriterExImpl writer = createWriter(INIT_CAP);
-
-        // Writing status.
-        writer.writeByte((byte) msg.status());
-
-        if (msg.status() != SqlListenerResponse.STATUS_SUCCESS) {
-            writer.writeString(msg.error());
-
-            return writer.array();
-        }
-
-        Object res0 = msg.response();
-
-        if (res0 == null)
-            return writer.array();
-        else if (res0 instanceof SqlListenerQueryExecuteResult) {
-            SqlListenerQueryExecuteResult res = (SqlListenerQueryExecuteResult) res0;
-
-            if (log.isDebugEnabled())
-                log.debug("Resulting query ID: " + res.getQueryId());
-
-            writer.writeLong(res.getQueryId());
-
-            Collection<SqlListenerColumnMeta> metas = res.getColumnsMetadata();
-
-            assert metas != null;
-
-            writer.writeInt(metas.size());
-
-            for (SqlListenerColumnMeta meta : metas)
-                meta.write(writer);
-        }
-        else if (res0 instanceof SqlListenerQueryFetchResult) {
-            SqlListenerQueryFetchResult res = (SqlListenerQueryFetchResult) res0;
-
-            if (log.isDebugEnabled())
-                log.debug("Resulting query ID: " + res.queryId());
-
-            writer.writeLong(res.queryId());
-
-            Collection<?> items0 = res.items();
-
-            assert items0 != null;
-
-            writer.writeBoolean(res.last());
-
-            writer.writeInt(items0.size());
-
-            for (Object row0 : items0) {
-                if (row0 != null) {
-                    Collection<?> row = (Collection<?>)row0;
-
-                    writer.writeInt(row.size());
-
-                    for (Object obj : row)
-                        objWriter.writeObject(writer, obj);
-                }
-            }
-        }
-        else if (res0 instanceof SqlListenerQueryCloseResult) {
-            SqlListenerQueryCloseResult res = (SqlListenerQueryCloseResult) res0;
-
-            if (log.isDebugEnabled())
-                log.debug("Resulting query ID: " + res.getQueryId());
-
-            writer.writeLong(res.getQueryId());
-        }
-        else if (res0 instanceof OdbcQueryGetColumnsMetaResult) {
-            OdbcQueryGetColumnsMetaResult res = (OdbcQueryGetColumnsMetaResult) res0;
-
-            Collection<SqlListenerColumnMeta> columnsMeta = res.meta();
-
-            assert columnsMeta != null;
-
-            writer.writeInt(columnsMeta.size());
-
-            for (SqlListenerColumnMeta columnMeta : columnsMeta)
-                columnMeta.write(writer);
-        }
-        else if (res0 instanceof OdbcQueryGetTablesMetaResult) {
-            OdbcQueryGetTablesMetaResult res = (OdbcQueryGetTablesMetaResult) res0;
-
-            Collection<OdbcTableMeta> tablesMeta = res.meta();
-
-            assert tablesMeta != null;
-
-            writer.writeInt(tablesMeta.size());
-
-            for (OdbcTableMeta tableMeta : tablesMeta)
-                tableMeta.writeBinary(writer);
-        }
-        else if (res0 instanceof OdbcQueryGetParamsMetaResult) {
-            OdbcQueryGetParamsMetaResult res = (OdbcQueryGetParamsMetaResult) res0;
-
-            byte[] typeIds = res.typeIds();
-
-            objWriter.writeObject(writer, typeIds);
-        }
-        else
-            assert false : "Should not reach here.";
-
-        return writer.array();
-    }
-
-    /**
-     * Create reader.
-     *
-     * @param msg Input message.
-     * @return Reader.
-     */
-    protected abstract BinaryReaderExImpl createReader(byte[] msg);
-
-    /**
-     * Create writer.
-     *
-     * @param cap Initial capacity.
-     * @return Binary writer instance.
-     */
-    protected abstract BinaryWriterExImpl createWriter(int cap);
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractObjectReader.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractObjectReader.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractObjectReader.java
deleted file mode 100644
index 18162e6..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractObjectReader.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.internal.binary.BinaryReaderExImpl;
-import org.apache.ignite.internal.binary.BinaryUtils;
-import org.apache.ignite.internal.binary.GridBinaryMarshaller;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Binary reader with marshaling non-primitive and non-embedded objects with JDK marshaller.
- */
-@SuppressWarnings("unchecked")
-public abstract class SqlListenerAbstractObjectReader {
-    /**
-     * @param reader Reader.
-     * @return Read object.
-     * @throws BinaryObjectException On error.
-     */
-    @Nullable public Object readObject(BinaryReaderExImpl reader) throws BinaryObjectException {
-        byte type = reader.readByte();
-
-        switch (type) {
-            case GridBinaryMarshaller.NULL:
-                return null;
-
-            case GridBinaryMarshaller.BOOLEAN:
-                return reader.readBoolean();
-
-            case GridBinaryMarshaller.BYTE:
-                return reader.readByte();
-
-            case GridBinaryMarshaller.CHAR:
-                return reader.readChar();
-
-            case GridBinaryMarshaller.SHORT:
-                return reader.readShort();
-
-            case GridBinaryMarshaller.INT:
-                return reader.readInt();
-
-            case GridBinaryMarshaller.LONG:
-                return reader.readLong();
-
-            case GridBinaryMarshaller.FLOAT:
-                return reader.readFloat();
-
-            case GridBinaryMarshaller.DOUBLE:
-                return reader.readDouble();
-
-            case GridBinaryMarshaller.STRING:
-                return BinaryUtils.doReadString(reader.in());
-
-            case GridBinaryMarshaller.DECIMAL:
-                return BinaryUtils.doReadDecimal(reader.in());
-
-            case GridBinaryMarshaller.UUID:
-                return BinaryUtils.doReadUuid(reader.in());
-
-            case GridBinaryMarshaller.TIME:
-                return BinaryUtils.doReadTime(reader.in());
-
-            case GridBinaryMarshaller.TIMESTAMP:
-                return BinaryUtils.doReadTimestamp(reader.in());
-
-            case GridBinaryMarshaller.DATE:
-                return BinaryUtils.doReadDate(reader.in());
-
-            case GridBinaryMarshaller.BOOLEAN_ARR:
-                return BinaryUtils.doReadBooleanArray(reader.in());
-
-            case GridBinaryMarshaller.BYTE_ARR:
-                return BinaryUtils.doReadByteArray(reader.in());
-
-            case GridBinaryMarshaller.CHAR_ARR:
-                return BinaryUtils.doReadCharArray(reader.in());
-
-            case GridBinaryMarshaller.SHORT_ARR:
-                return BinaryUtils.doReadShortArray(reader.in());
-
-            case GridBinaryMarshaller.INT_ARR:
-                return BinaryUtils.doReadIntArray(reader.in());
-
-            case GridBinaryMarshaller.FLOAT_ARR:
-                return BinaryUtils.doReadFloatArray(reader.in());
-
-            case GridBinaryMarshaller.DOUBLE_ARR:
-                return BinaryUtils.doReadDoubleArray(reader.in());
-
-            case GridBinaryMarshaller.STRING_ARR:
-                return BinaryUtils.doReadStringArray(reader.in());
-
-            case GridBinaryMarshaller.DECIMAL_ARR:
-                return BinaryUtils.doReadDecimalArray(reader.in());
-
-            case GridBinaryMarshaller.UUID_ARR:
-                return BinaryUtils.doReadUuidArray(reader.in());
-
-            case GridBinaryMarshaller.TIME_ARR:
-                return BinaryUtils.doReadTimeArray(reader.in());
-
-            case GridBinaryMarshaller.TIMESTAMP_ARR:
-                return BinaryUtils.doReadTimestampArray(reader.in());
-
-            case GridBinaryMarshaller.DATE_ARR:
-                return BinaryUtils.doReadDateArray(reader.in());
-
-            default:
-                reader.in().position(reader.in().position() - 1);
-
-                return readCustomObject(reader);
-        }
-    }
-
-    /**
-     * @param reader Reader.
-     * @return An object is unmarshaled by marshaller.
-     * @throws BinaryObjectException On error.
-     */
-    protected abstract Object readCustomObject(BinaryReaderExImpl reader) throws BinaryObjectException;
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractObjectWriter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractObjectWriter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractObjectWriter.java
deleted file mode 100644
index f5e9924..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerAbstractObjectWriter.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import java.math.BigDecimal;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.UUID;
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.internal.binary.BinaryWriterExImpl;
-import org.apache.ignite.internal.binary.GridBinaryMarshaller;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Binary writer with marshaling non-primitive and non-embedded objects with JDK marshaller..
- */
-public abstract class SqlListenerAbstractObjectWriter {
-    /**
-     * @param writer Writer.
-     * @param obj Object to write.
-     * @throws BinaryObjectException On error.
-     */
-    public void writeObject(BinaryWriterExImpl writer, @Nullable Object obj) throws BinaryObjectException {
-        if (obj == null) {
-            writer.writeByte(GridBinaryMarshaller.NULL);
-
-            return;
-        }
-
-        Class<?> cls = obj.getClass();
-
-        if (cls == Boolean.class)
-            writer.writeBooleanFieldPrimitive((Boolean)obj);
-        else if (cls == Byte.class)
-            writer.writeByteFieldPrimitive((Byte)obj);
-        else if (cls == Character.class)
-            writer.writeCharFieldPrimitive((Character)obj);
-        else if (cls == Short.class)
-            writer.writeShortFieldPrimitive((Short)obj);
-        else if (cls == Integer.class)
-            writer.writeIntFieldPrimitive((Integer)obj);
-        else if (cls == Long.class)
-            writer.writeLongFieldPrimitive((Long)obj);
-        else if (cls == Float.class)
-            writer.writeFloatFieldPrimitive((Float)obj);
-        else if (cls == Double.class)
-            writer.writeDoubleFieldPrimitive((Double)obj);
-        else if (cls == String.class)
-            writer.doWriteString((String)obj);
-        else if (cls == BigDecimal.class)
-            writer.doWriteDecimal((BigDecimal)obj);
-        else if (cls == UUID.class)
-            writer.writeUuid((UUID)obj);
-        else if (cls == Time.class)
-            writer.writeTime((Time)obj);
-        else if (cls == Timestamp.class)
-            writer.writeTimestamp((Timestamp)obj);
-        else if (cls == java.sql.Date.class || cls == java.util.Date.class)
-            writer.writeDate((java.util.Date)obj);
-        else if (cls == boolean[].class)
-            writer.writeBooleanArray((boolean[])obj);
-        else if (cls == byte[].class)
-            writer.writeByteArray((byte[])obj);
-        else if (cls == char[].class)
-            writer.writeCharArray((char[])obj);
-        else if (cls == short[].class)
-            writer.writeShortArray((short[])obj);
-        else if (cls == int[].class)
-            writer.writeIntArray((int[])obj);
-        else if (cls == float[].class)
-            writer.writeFloatArray((float[])obj);
-        else if (cls == double[].class)
-            writer.writeDoubleArray((double[])obj);
-        else if (cls == String[].class)
-            writer.writeStringArray((String[])obj);
-        else if (cls == BigDecimal[].class)
-            writer.writeDecimalArray((BigDecimal[])obj);
-        else if (cls == UUID[].class)
-            writer.writeUuidArray((UUID[])obj);
-        else if (cls == Time[].class)
-            writer.writeTimeArray((Time[])obj);
-        else if (cls == Timestamp[].class)
-            writer.writeTimestampArray((Timestamp[])obj);
-        else if (cls == java.util.Date[].class || cls == java.sql.Date[].class)
-            writer.writeDateArray((java.util.Date[])obj);
-        else
-            writeCustomObject(writer, obj);
-    }
-
-    /**
-     * @param writer Writer.
-     * @param obj Object to marshal with marshaller and write to binary stream.
-     * @throws BinaryObjectException On error.
-     */
-    protected abstract void writeCustomObject(BinaryWriterExImpl writer, Object obj) throws BinaryObjectException;
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerColumnMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerColumnMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerColumnMeta.java
deleted file mode 100644
index 73133a1..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerColumnMeta.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import org.apache.ignite.binary.BinaryRawWriter;
-import org.apache.ignite.internal.binary.BinaryUtils;
-import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
-
-/**
- * SQL listener column metadata.
- */
-public class SqlListenerColumnMeta {
-    /** Cache name. */
-    private final String schemaName;
-
-    /** Table name. */
-    private final String tableName;
-
-    /** Column name. */
-    private final String columnName;
-
-    /** Data type. */
-    private final Class<?> dataType;
-
-    /**
-     * @param schemaName Cache name.
-     * @param tableName Table name.
-     * @param columnName Column name.
-     * @param dataType Data type.
-     */
-    public SqlListenerColumnMeta(String schemaName, String tableName, String columnName, Class<?> dataType) {
-        this.schemaName = OdbcUtils.addQuotationMarksIfNeeded(schemaName);
-        this.tableName = tableName;
-        this.columnName = columnName;
-        this.dataType = dataType;
-    }
-
-    /**
-     * @param info Field metadata.
-     */
-    public SqlListenerColumnMeta(GridQueryFieldMetadata info) {
-        this.schemaName = OdbcUtils.addQuotationMarksIfNeeded(info.schemaName());
-        this.tableName = info.typeName();
-        this.columnName = info.fieldName();
-
-        Class<?> type;
-
-        try {
-            type = Class.forName(info.fieldTypeName());
-        }
-        catch (Exception ignored) {
-            type = Object.class;
-        }
-
-        this.dataType = type;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int hashCode() {
-        int hash = schemaName.hashCode();
-
-        hash = 31 * hash + tableName.hashCode();
-        hash = 31 * hash + columnName.hashCode();
-        hash = 31 * hash + dataType.hashCode();
-
-        return hash;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean equals(Object o) {
-        if (o instanceof SqlListenerColumnMeta) {
-            SqlListenerColumnMeta other = (SqlListenerColumnMeta) o;
-
-            return this == other || schemaName.equals(other.schemaName) && tableName.equals(other.tableName) &&
-                columnName.equals(other.columnName) && dataType.equals(other.dataType);
-        }
-
-        return false;
-    }
-
-    /**
-     * Write in a binary format.
-     *
-     * @param writer Binary writer.
-     */
-    public void write(BinaryRawWriter writer) {
-        writer.writeString(schemaName);
-        writer.writeString(tableName);
-        writer.writeString(columnName);
-
-        byte typeId = BinaryUtils.typeByClass(dataType);
-
-        writer.writeByte(typeId);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
index 9eaec04..e46ee50 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java
@@ -29,7 +29,9 @@ import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream;
 import org.apache.ignite.internal.binary.streams.BinaryHeapOutputStream;
 import org.apache.ignite.internal.binary.streams.BinaryInputStream;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMessageParser;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequestHandler;
 import org.apache.ignite.internal.processors.odbc.odbc.OdbcMessageParser;
+import org.apache.ignite.internal.processors.odbc.odbc.OdbcRequestHandler;
 import org.apache.ignite.internal.util.GridSpinBusyLock;
 import org.apache.ignite.internal.util.nio.GridNioServerListenerAdapter;
 import org.apache.ignite.internal.util.nio.GridNioSession;
@@ -118,6 +120,7 @@ public class SqlListenerNioListener extends GridNioServerListenerAdapter<byte[]>
         }
 
         SqlListenerMessageParser parser = connCtx.parser();
+        SqlListenerRequestHandler handler = connCtx.handler();
 
         SqlListenerRequest req;
 
@@ -125,7 +128,7 @@ public class SqlListenerNioListener extends GridNioServerListenerAdapter<byte[]>
             req = parser.decode(msg);
         }
         catch (Exception e) {
-            log.error("Failed to parse SQL client request [err=" + e + ']');
+            log.error("Failed to parse SQL client request.", e);
 
             ses.close();
 
@@ -146,8 +149,6 @@ public class SqlListenerNioListener extends GridNioServerListenerAdapter<byte[]>
                     ", req=" + req + ']');
             }
 
-            SqlListenerRequestHandler handler = connCtx.handler();
-
             SqlListenerResponse resp = handler.handle(req);
 
             if (log.isDebugEnabled()) {
@@ -162,9 +163,9 @@ public class SqlListenerNioListener extends GridNioServerListenerAdapter<byte[]>
             ses.send(outMsg);
         }
         catch (Exception e) {
-            log.error("Failed to process SQL client request [reqId=" + req.requestId() + ", err=" + e + ']');
+            log.error("Failed to process SQL client request [req=" + req + ']', e);
 
-            ses.send(parser.encode(new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString())));
+            ses.send(parser.encode(handler.handleException(e)));
         }
     }
 
@@ -238,25 +239,27 @@ public class SqlListenerNioListener extends GridNioServerListenerAdapter<byte[]>
         boolean distributedJoins = reader.readBoolean();
         boolean enforceJoinOrder = reader.readBoolean();
 
-        SqlListenerRequestHandlerImpl handler = new SqlListenerRequestHandlerImpl(ctx, busyLock, maxCursors,
-            distributedJoins, enforceJoinOrder);
-
-        SqlListenerMessageParser parser = null;
+        SqlListenerRequestHandler handler;
+        SqlListenerMessageParser parser;
 
         switch (clientType) {
             case ODBC_CLIENT:
                 parser = new OdbcMessageParser(ctx);
 
+                handler = new OdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins, enforceJoinOrder);
+
                 break;
 
             case JDBC_CLIENT:
                 parser = new JdbcMessageParser(ctx);
 
+                handler = new JdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins, enforceJoinOrder);
+
                 break;
-        }
 
-        if (parser == null)
-            throw new IgniteException("Unknown client type: " + clientType);
+            default:
+                throw new IgniteException("Unknown client type: " + clientType);
+        }
 
         return new SqlListenerConnectionContext(handler, parser);
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryCloseRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryCloseRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryCloseRequest.java
deleted file mode 100644
index 74361c6..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryCloseRequest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import org.apache.ignite.internal.util.typedef.internal.S;
-
-/**
- * SQL listener query close request.
- */
-public class SqlListenerQueryCloseRequest extends SqlListenerRequest {
-    /** Query ID. */
-    private final long queryId;
-
-    /**
-     * @param queryId Query ID.
-     */
-    public SqlListenerQueryCloseRequest(long queryId) {
-        super(QRY_CLOSE);
-
-        this.queryId = queryId;
-    }
-
-    /**
-     * @return Query ID.
-     */
-    public long queryId() {
-        return queryId;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(SqlListenerQueryCloseRequest.class, this);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryCloseResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryCloseResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryCloseResult.java
deleted file mode 100644
index 2558a85..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryCloseResult.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-/**
- * SQL listener query close result.
- */
-public class SqlListenerQueryCloseResult {
-    /** Query ID. */
-    private final long queryId;
-
-    /**
-     * @param queryId Query ID.
-     */
-    public SqlListenerQueryCloseResult(long queryId){
-        this.queryId = queryId;
-    }
-
-    /**
-     * @return Query ID.
-     */
-    public long getQueryId() {
-        return queryId;
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryExecuteRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryExecuteRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryExecuteRequest.java
deleted file mode 100644
index 3c77e06..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryExecuteRequest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import org.apache.ignite.internal.util.tostring.GridToStringExclude;
-import org.apache.ignite.internal.util.tostring.GridToStringInclude;
-import org.apache.ignite.internal.util.typedef.internal.S;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * SQL listener query execute request.
- */
-public class SqlListenerQueryExecuteRequest extends SqlListenerRequest {
-    /** Cache name. */
-    private final String cacheName;
-
-    /** Sql query. */
-    @GridToStringInclude(sensitive = true)
-    private final String sqlQry;
-
-    /** Sql query arguments. */
-    @GridToStringExclude
-    private final Object[] args;
-
-    /**
-     * @param cacheName Cache name.
-     * @param sqlQry SQL query.
-     * @param args Arguments list.
-     */
-    public SqlListenerQueryExecuteRequest(String cacheName, String sqlQry, Object[] args) {
-        super(QRY_EXEC);
-
-        this.cacheName = cacheName.isEmpty() ? null : cacheName;
-        this.sqlQry = sqlQry;
-        this.args = args;
-    }
-
-    /**
-     * @return Sql query.
-     */
-    public String sqlQuery() {
-        return sqlQry;
-    }
-
-    /**
-     * @return Sql query arguments.
-     */
-    public Object[] arguments() {
-        return args;
-    }
-
-    /**
-     * @return Cache name.
-     */
-    @Nullable public String cacheName() {
-        return cacheName;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(SqlListenerQueryExecuteRequest.class, this, "args", args, true);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryExecuteResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryExecuteResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryExecuteResult.java
deleted file mode 100644
index e4c0cb9..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryExecuteResult.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import java.util.Collection;
-
-/**
- * SQL listener query execute result.
- */
-public class SqlListenerQueryExecuteResult {
-    /** Query ID. */
-    private final long queryId;
-
-    /** Fields metadata. */
-    private final Collection<SqlListenerColumnMeta> columnsMeta;
-
-    /**
-     * @param queryId Query ID.
-     * @param columnsMeta Columns metadata.
-     */
-    public SqlListenerQueryExecuteResult(long queryId, Collection<SqlListenerColumnMeta> columnsMeta) {
-        this.queryId = queryId;
-        this.columnsMeta = columnsMeta;
-    }
-
-    /**
-     * @return Query ID.
-     */
-    public long getQueryId() {
-        return queryId;
-    }
-
-    /**
-     * @return Columns metadata.
-     */
-    public Collection<SqlListenerColumnMeta> getColumnsMetadata() {
-        return columnsMeta;
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryFetchRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryFetchRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryFetchRequest.java
deleted file mode 100644
index 41c3be0..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryFetchRequest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import org.apache.ignite.internal.util.typedef.internal.S;
-
-/**
- * SQL listener query fetch request.
- */
-public class SqlListenerQueryFetchRequest extends SqlListenerRequest {
-    /** Query ID. */
-    private final long queryId;
-
-    /** Page size - maximum number of rows to return. */
-    private final int pageSize;
-
-    /**
-     * @param queryId Query ID.
-     * @param pageSize Page size.
-     */
-    public SqlListenerQueryFetchRequest(long queryId, int pageSize) {
-        super(QRY_FETCH);
-
-        this.queryId = queryId;
-        this.pageSize = pageSize;
-    }
-
-    /**
-     * @return Page size.
-     */
-    public int pageSize() {
-        return pageSize;
-    }
-
-    /**
-     * @return Query ID.
-     */
-    public long queryId() {
-        return queryId;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(SqlListenerQueryFetchRequest.class, this);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryFetchResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryFetchResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryFetchResult.java
deleted file mode 100644
index 6763f8b..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerQueryFetchResult.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import java.util.Collection;
-
-/**
- * SQL listener query fetch result.
- */
-public class SqlListenerQueryFetchResult {
-    /** Query ID. */
-    private final long queryId;
-
-    /** Query result rows. */
-    private final Collection<?> items;
-
-    /** Flag indicating the query has no unfetched results. */
-    private final boolean last;
-
-    /**
-     * @param queryId Query ID.
-     * @param items Query result rows.
-     * @param last Flag indicating the query has no unfetched results.
-     */
-    public SqlListenerQueryFetchResult(long queryId, Collection<?> items, boolean last){
-        this.queryId = queryId;
-        this.items = items;
-        this.last = last;
-    }
-
-    /**
-     * @return Query ID.
-     */
-    public long queryId() {
-        return queryId;
-    }
-
-    /**
-     * @return Query result rows.
-     */
-    public Collection<?> items() {
-        return items;
-    }
-
-    /**
-     * @return Flag indicating the query has no unfetched results.
-     */
-    public boolean last() {
-        return last;
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequest.java
index 2714237..3c74752 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequest.java
@@ -20,49 +20,14 @@ package org.apache.ignite.internal.processors.odbc;
 /**
  * SQL listener command request.
  */
-public class SqlListenerRequest {
+public abstract class SqlListenerRequest {
     /** Handshake request. */
     public static final int HANDSHAKE = 1;
 
-    /** Execute sql query. */
-    public static final int QRY_EXEC = 2;
-
-    /** Fetch query results. */
-    public static final int QRY_FETCH = 3;
-
-    /** Close query. */
-    public static final int QRY_CLOSE = 4;
-
-    /** Get columns meta query. */
-    public static final int META_COLS = 5;
-
-    /** Get columns meta query. */
-    public static final int META_TBLS = 6;
-
-    /** Get parameters meta. */
-    public static final int META_PARAMS = 7;
-
-    /** Command. */
-    private final int cmd;
-
     /** Request ID. */
     private long reqId;
 
     /**
-     * @param cmd Command type.
-     */
-    public SqlListenerRequest(int cmd) {
-        this.cmd = cmd;
-    }
-
-    /**
-     * @return Command.
-     */
-    public int command() {
-        return cmd;
-    }
-
-    /**
      * @return Request ID.
      */
     public long requestId() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandler.java
index 0ebb084..98dc039 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandler.java
@@ -28,4 +28,12 @@ public interface SqlListenerRequestHandler {
      * @return Response.
      */
     public SqlListenerResponse handle(SqlListenerRequest req);
+
+    /**
+     * Handle exception.
+     *
+     * @param e Exception.
+     * @return Error response.
+     */
+    public SqlListenerResponse handleException(Exception e);
 }


[08/50] [abbrv] ignite git commit: IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandlerImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandlerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandlerImpl.java
deleted file mode 100644
index 1230bb4..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandlerImpl.java
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc;
-
-import java.sql.ParameterMetaData;
-import java.sql.PreparedStatement;
-import java.sql.Types;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicLong;
-import org.apache.ignite.IgniteCache;
-import org.apache.ignite.IgniteLogger;
-import org.apache.ignite.cache.query.QueryCursor;
-import org.apache.ignite.cache.query.SqlFieldsQuery;
-import org.apache.ignite.internal.GridKernalContext;
-import org.apache.ignite.internal.binary.GridBinaryMarshaller;
-import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
-import org.apache.ignite.internal.processors.odbc.odbc.escape.OdbcEscapeUtils;
-import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
-import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
-import org.apache.ignite.internal.util.GridSpinBusyLock;
-import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteBiTuple;
-
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.META_COLS;
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.META_PARAMS;
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.META_TBLS;
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.QRY_CLOSE;
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.QRY_EXEC;
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.QRY_FETCH;
-
-/**
- * SQL query handler.
- */
-public class SqlListenerRequestHandlerImpl implements SqlListenerRequestHandler {
-    /** Query ID sequence. */
-    private static final AtomicLong QRY_ID_GEN = new AtomicLong();
-
-    /** Kernel context. */
-    private final GridKernalContext ctx;
-
-    /** Logger. */
-    private final IgniteLogger log;
-
-    /** Busy lock. */
-    private final GridSpinBusyLock busyLock;
-
-    /** Maximum allowed cursors. */
-    private final int maxCursors;
-
-    /** Current queries cursors. */
-    private final ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCursors = new ConcurrentHashMap<>();
-
-    /** Distributed joins flag. */
-    private final boolean distributedJoins;
-
-    /** Enforce join order flag. */
-    private final boolean enforceJoinOrder;
-
-    /**
-     * Constructor.
-     *
-     * @param ctx Context.
-     * @param busyLock Shutdown latch.
-     * @param maxCursors Maximum allowed cursors.
-     * @param distributedJoins Distributed joins flag.
-     * @param enforceJoinOrder Enforce join order flag.
-     */
-    public SqlListenerRequestHandlerImpl(GridKernalContext ctx, GridSpinBusyLock busyLock, int maxCursors,
-        boolean distributedJoins, boolean enforceJoinOrder) {
-        this.ctx = ctx;
-        this.busyLock = busyLock;
-        this.maxCursors = maxCursors;
-        this.distributedJoins = distributedJoins;
-        this.enforceJoinOrder = enforceJoinOrder;
-
-        log = ctx.log(getClass());
-    }
-
-    /** {@inheritDoc} */
-    @Override public SqlListenerResponse handle(SqlListenerRequest req) {
-        assert req != null;
-
-        if (!busyLock.enterBusy())
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Failed to handle ODBC request because node is stopping: " + req);
-
-        try {
-            switch (req.command()) {
-                case QRY_EXEC:
-                    return executeQuery((SqlListenerQueryExecuteRequest)req);
-
-                case QRY_FETCH:
-                    return fetchQuery((SqlListenerQueryFetchRequest)req);
-
-                case QRY_CLOSE:
-                    return closeQuery((SqlListenerQueryCloseRequest)req);
-
-                case META_COLS:
-                    return getColumnsMeta((OdbcQueryGetColumnsMetaRequest)req);
-
-                case META_TBLS:
-                    return getTablesMeta((OdbcQueryGetTablesMetaRequest)req);
-
-                case META_PARAMS:
-                    return getParamsMeta((OdbcQueryGetParamsMetaRequest)req);
-            }
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, "Unsupported ODBC request: " + req);
-        }
-        finally {
-            busyLock.leaveBusy();
-        }
-    }
-
-    /**
-     * {@link SqlListenerQueryExecuteRequest} command handler.
-     *
-     * @param req Execute query request.
-     * @return Response.
-     */
-    private SqlListenerResponse executeQuery(SqlListenerQueryExecuteRequest req) {
-        int cursorCnt = qryCursors.size();
-
-        if (maxCursors > 0 && cursorCnt >= maxCursors)
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, "Too many opened cursors (either close other " +
-                "opened cursors or increase the limit through OdbcConfiguration.setMaxOpenCursors()) " +
-                "[maximum=" + maxCursors + ", current=" + cursorCnt + ']');
-
-        long qryId = QRY_ID_GEN.getAndIncrement();
-
-        try {
-            String sql = OdbcEscapeUtils.parse(req.sqlQuery());
-
-            if (log.isDebugEnabled())
-                log.debug("ODBC query parsed [reqId=" + req.requestId() + ", original=" + req.sqlQuery() +
-                    ", parsed=" + sql + ']');
-
-            SqlFieldsQuery qry = new SqlFieldsQuery(sql);
-
-            qry.setArgs(req.arguments());
-
-            qry.setDistributedJoins(distributedJoins);
-            qry.setEnforceJoinOrder(enforceJoinOrder);
-
-            IgniteCache<Object, Object> cache0 = ctx.grid().cache(req.cacheName());
-
-            if (cache0 == null)
-                return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Cache doesn't exist (did you configure it?): " + req.cacheName());
-
-            IgniteCache<Object, Object> cache = cache0.withKeepBinary();
-
-            if (cache == null)
-                return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Can not get cache with keep binary: " + req.cacheName());
-
-            QueryCursor qryCur = cache.query(qry);
-
-            qryCursors.put(qryId, new IgniteBiTuple<QueryCursor, Iterator>(qryCur, null));
-
-            List<?> fieldsMeta = ((QueryCursorImpl) qryCur).fieldsMeta();
-
-            SqlListenerQueryExecuteResult res = new SqlListenerQueryExecuteResult(qryId, convertMetadata(fieldsMeta));
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            qryCursors.remove(qryId);
-
-            U.error(log, "Failed to execute SQL query [reqId=" + req.requestId() + ", req=" + req + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * {@link SqlListenerQueryCloseRequest} command handler.
-     *
-     * @param req Execute query request.
-     * @return Response.
-     */
-    private SqlListenerResponse closeQuery(SqlListenerQueryCloseRequest req) {
-        try {
-            IgniteBiTuple<QueryCursor, Iterator> tuple = qryCursors.get(req.queryId());
-
-            if (tuple == null)
-                return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Failed to find query with ID: " + req.queryId());
-
-            QueryCursor cur = tuple.get1();
-
-            assert(cur != null);
-
-            cur.close();
-
-            qryCursors.remove(req.queryId());
-
-            SqlListenerQueryCloseResult res = new SqlListenerQueryCloseResult(req.queryId());
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            qryCursors.remove(req.queryId());
-
-            U.error(log, "Failed to close SQL query [reqId=" + req.requestId() + ", req=" + req.queryId() + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * {@link SqlListenerQueryFetchRequest} command handler.
-     *
-     * @param req Execute query request.
-     * @return Response.
-     */
-    private SqlListenerResponse fetchQuery(SqlListenerQueryFetchRequest req) {
-        try {
-            IgniteBiTuple<QueryCursor, Iterator> tuple = qryCursors.get(req.queryId());
-
-            if (tuple == null)
-                return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Failed to find query with ID: " + req.queryId());
-
-            Iterator iter = tuple.get2();
-
-            if (iter == null) {
-                QueryCursor cur = tuple.get1();
-
-                iter = cur.iterator();
-
-                tuple.put(cur, iter);
-            }
-
-            List<Object> items = new ArrayList<>();
-
-            for (int i = 0; i < req.pageSize() && iter.hasNext(); ++i)
-                items.add(iter.next());
-
-            SqlListenerQueryFetchResult res = new SqlListenerQueryFetchResult(req.queryId(), items, !iter.hasNext());
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            U.error(log, "Failed to fetch SQL query result [reqId=" + req.requestId() + ", req=" + req + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * {@link OdbcQueryGetColumnsMetaRequest} command handler.
-     *
-     * @param req Get columns metadata request.
-     * @return Response.
-     */
-    private SqlListenerResponse getColumnsMeta(OdbcQueryGetColumnsMetaRequest req) {
-        try {
-            List<SqlListenerColumnMeta> meta = new ArrayList<>();
-
-            String cacheName;
-            String tableName;
-
-            if (req.tableName().contains(".")) {
-                // Parsing two-part table name.
-                String[] parts = req.tableName().split("\\.");
-
-                cacheName = OdbcUtils.removeQuotationMarksIfNeeded(parts[0]);
-
-                tableName = parts[1];
-            }
-            else {
-                cacheName = OdbcUtils.removeQuotationMarksIfNeeded(req.cacheName());
-
-                tableName = req.tableName();
-            }
-
-            Collection<GridQueryTypeDescriptor> tablesMeta = ctx.query().types(cacheName);
-
-            for (GridQueryTypeDescriptor table : tablesMeta) {
-                if (!matches(table.name(), tableName))
-                    continue;
-
-                for (Map.Entry<String, Class<?>> field : table.fields().entrySet()) {
-                    if (!matches(field.getKey(), req.columnName()))
-                        continue;
-
-                    SqlListenerColumnMeta columnMeta = new SqlListenerColumnMeta(req.cacheName(), table.name(),
-                        field.getKey(), field.getValue());
-
-                    if (!meta.contains(columnMeta))
-                        meta.add(columnMeta);
-                }
-            }
-
-            OdbcQueryGetColumnsMetaResult res = new OdbcQueryGetColumnsMetaResult(meta);
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            U.error(log, "Failed to get columns metadata [reqId=" + req.requestId() + ", req=" + req + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * {@link OdbcQueryGetTablesMetaRequest} command handler.
-     *
-     * @param req Get tables metadata request.
-     * @return Response.
-     */
-    private SqlListenerResponse getTablesMeta(OdbcQueryGetTablesMetaRequest req) {
-        try {
-            List<OdbcTableMeta> meta = new ArrayList<>();
-
-            String realSchema = OdbcUtils.removeQuotationMarksIfNeeded(req.schema());
-
-            for (String cacheName : ctx.cache().cacheNames())
-            {
-                if (!matches(cacheName, realSchema))
-                    continue;
-
-                Collection<GridQueryTypeDescriptor> tablesMeta = ctx.query().types(cacheName);
-
-                for (GridQueryTypeDescriptor table : tablesMeta) {
-                    if (!matches(table.name(), req.table()))
-                        continue;
-
-                    if (!matches("TABLE", req.tableType()))
-                        continue;
-
-                    OdbcTableMeta tableMeta = new OdbcTableMeta(null, cacheName, table.name(), "TABLE");
-
-                    if (!meta.contains(tableMeta))
-                        meta.add(tableMeta);
-                }
-            }
-
-            OdbcQueryGetTablesMetaResult res = new OdbcQueryGetTablesMetaResult(meta);
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            U.error(log, "Failed to get tables metadata [reqId=" + req.requestId() + ", req=" + req + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * {@link OdbcQueryGetParamsMetaRequest} command handler.
-     *
-     * @param req Get params metadata request.
-     * @return Response.
-     */
-    private SqlListenerResponse getParamsMeta(OdbcQueryGetParamsMetaRequest req) {
-        try {
-            PreparedStatement stmt = ctx.query().prepareNativeStatement(req.cacheName(), req.query());
-
-            ParameterMetaData pmd = stmt.getParameterMetaData();
-
-            byte[] typeIds = new byte[pmd.getParameterCount()];
-
-            for (int i = 1; i <= pmd.getParameterCount(); ++i) {
-                int sqlType = pmd.getParameterType(i);
-
-                typeIds[i - 1] = sqlTypeToBinary(sqlType);
-            }
-
-            OdbcQueryGetParamsMetaResult res = new OdbcQueryGetParamsMetaResult(typeIds);
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            U.error(log, "Failed to get params metadata [reqId=" + req.requestId() + ", req=" + req + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * Convert {@link java.sql.Types} to binary type constant (See {@link GridBinaryMarshaller} constants).
-     *
-     * @param sqlType SQL type.
-     * @return Binary type.
-     */
-    private static byte sqlTypeToBinary(int sqlType) {
-        switch (sqlType) {
-            case Types.BIGINT:
-                return GridBinaryMarshaller.LONG;
-
-            case Types.BOOLEAN:
-                return GridBinaryMarshaller.BOOLEAN;
-
-            case Types.DATE:
-                return GridBinaryMarshaller.DATE;
-
-            case Types.DOUBLE:
-                return GridBinaryMarshaller.DOUBLE;
-
-            case Types.FLOAT:
-            case Types.REAL:
-                return GridBinaryMarshaller.FLOAT;
-
-            case Types.NUMERIC:
-            case Types.DECIMAL:
-                return GridBinaryMarshaller.DECIMAL;
-
-            case Types.INTEGER:
-                return GridBinaryMarshaller.INT;
-
-            case Types.SMALLINT:
-                return GridBinaryMarshaller.SHORT;
-
-            case Types.TIME:
-                return GridBinaryMarshaller.TIME;
-
-            case Types.TIMESTAMP:
-                return GridBinaryMarshaller.TIMESTAMP;
-
-            case Types.TINYINT:
-                return GridBinaryMarshaller.BYTE;
-
-            case Types.CHAR:
-            case Types.VARCHAR:
-            case Types.LONGNVARCHAR:
-                return GridBinaryMarshaller.STRING;
-
-            case Types.NULL:
-                return GridBinaryMarshaller.NULL;
-
-            case Types.BINARY:
-            case Types.VARBINARY:
-            case Types.LONGVARBINARY:
-            default:
-                return GridBinaryMarshaller.BYTE_ARR;
-        }
-    }
-
-    /**
-     * Convert metadata in collection from {@link GridQueryFieldMetadata} to
-     * {@link SqlListenerColumnMeta}.
-     *
-     * @param meta Internal query field metadata.
-     * @return Odbc query field metadata.
-     */
-    private static Collection<SqlListenerColumnMeta> convertMetadata(Collection<?> meta) {
-        List<SqlListenerColumnMeta> res = new ArrayList<>();
-
-        if (meta != null) {
-            for (Object info : meta) {
-                assert info instanceof GridQueryFieldMetadata;
-
-                res.add(new SqlListenerColumnMeta((GridQueryFieldMetadata)info));
-            }
-        }
-
-        return res;
-    }
-
-    /**
-     * Checks whether string matches SQL pattern.
-     *
-     * @param str String.
-     * @param ptrn Pattern.
-     * @return Whether string matches pattern.
-     */
-    private static boolean matches(String str, String ptrn) {
-        return str != null && (F.isEmpty(ptrn) ||
-            str.toUpperCase().matches(ptrn.toUpperCase().replace("%", ".*").replace("_", ".")));
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerResponse.java
index 84c1e26..e35d8f2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerResponse.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerResponse.java
@@ -17,14 +17,12 @@
 
 package org.apache.ignite.internal.processors.odbc;
 
-import org.apache.ignite.internal.util.tostring.GridToStringInclude;
-import org.apache.ignite.internal.util.typedef.internal.S;
 import org.jetbrains.annotations.Nullable;
 
 /**
  * SQL listener response.
  */
-public class SqlListenerResponse {
+public abstract class SqlListenerResponse {
     /** Command succeeded. */
     public static final int STATUS_SUCCESS = 0;
 
@@ -32,26 +30,10 @@ public class SqlListenerResponse {
     public static final int STATUS_FAILED = 1;
 
     /** Success status. */
-    private final int status;
+    private int status;
 
     /** Error. */
-    private final String err;
-
-    /** Response object. */
-    @GridToStringInclude
-    private final Object obj;
-
-    /**
-     * Constructs successful rest response.
-     *
-     * @param obj Response object.
-     */
-    public SqlListenerResponse(Object obj) {
-        this.status = STATUS_SUCCESS;
-
-        this.obj = obj;
-        this.err = null;
-    }
+    private String err;
 
     /**
      * Constructs failed rest response.
@@ -60,11 +42,7 @@ public class SqlListenerResponse {
      * @param err Error, {@code null} if success is {@code true}.
      */
     public SqlListenerResponse(int status, @Nullable String err) {
-        assert status != STATUS_SUCCESS;
-
         this.status = status;
-
-        this.obj = null;
         this.err = err;
     }
 
@@ -76,10 +54,10 @@ public class SqlListenerResponse {
     }
 
     /**
-     * @return Response object.
+     * @param status Status.
      */
-    public Object response() {
-        return obj;
+    public void status(int status) {
+        this.status = status;
     }
 
     /**
@@ -89,8 +67,10 @@ public class SqlListenerResponse {
         return err;
     }
 
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(SqlListenerResponse.class, this);
+    /**
+     * @param err Error message.
+     */
+    public void error(String err) {
+        this.err = err;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerUtils.java
new file mode 100644
index 0000000..196eafa
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerUtils.java
@@ -0,0 +1,250 @@
+/*
+ * 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.processors.odbc;
+
+import java.math.BigDecimal;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.UUID;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryUtils;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.binary.GridBinaryMarshaller;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Binary reader with marshaling non-primitive and non-embedded objects with JDK marshaller.
+ */
+@SuppressWarnings("unchecked")
+public abstract class SqlListenerUtils {
+    /**
+     * @param reader Reader.
+     * @param binObjAllow Allow to read non plaint objects.
+     * @return Read object.
+     * @throws BinaryObjectException On error.
+     */
+    @Nullable public static Object readObject(BinaryReaderExImpl reader, boolean binObjAllow)
+        throws BinaryObjectException {
+        byte type = reader.readByte();
+
+        switch (type) {
+            case GridBinaryMarshaller.NULL:
+                return null;
+
+            case GridBinaryMarshaller.BOOLEAN:
+                return reader.readBoolean();
+
+            case GridBinaryMarshaller.BYTE:
+                return reader.readByte();
+
+            case GridBinaryMarshaller.CHAR:
+                return reader.readChar();
+
+            case GridBinaryMarshaller.SHORT:
+                return reader.readShort();
+
+            case GridBinaryMarshaller.INT:
+                return reader.readInt();
+
+            case GridBinaryMarshaller.LONG:
+                return reader.readLong();
+
+            case GridBinaryMarshaller.FLOAT:
+                return reader.readFloat();
+
+            case GridBinaryMarshaller.DOUBLE:
+                return reader.readDouble();
+
+            case GridBinaryMarshaller.STRING:
+                return BinaryUtils.doReadString(reader.in());
+
+            case GridBinaryMarshaller.DECIMAL:
+                return BinaryUtils.doReadDecimal(reader.in());
+
+            case GridBinaryMarshaller.UUID:
+                return BinaryUtils.doReadUuid(reader.in());
+
+            case GridBinaryMarshaller.TIME:
+                return BinaryUtils.doReadTime(reader.in());
+
+            case GridBinaryMarshaller.TIMESTAMP:
+                return BinaryUtils.doReadTimestamp(reader.in());
+
+            case GridBinaryMarshaller.DATE:
+                return BinaryUtils.doReadDate(reader.in());
+
+            case GridBinaryMarshaller.BOOLEAN_ARR:
+                return BinaryUtils.doReadBooleanArray(reader.in());
+
+            case GridBinaryMarshaller.BYTE_ARR:
+                return BinaryUtils.doReadByteArray(reader.in());
+
+            case GridBinaryMarshaller.CHAR_ARR:
+                return BinaryUtils.doReadCharArray(reader.in());
+
+            case GridBinaryMarshaller.SHORT_ARR:
+                return BinaryUtils.doReadShortArray(reader.in());
+
+            case GridBinaryMarshaller.INT_ARR:
+                return BinaryUtils.doReadIntArray(reader.in());
+
+            case GridBinaryMarshaller.FLOAT_ARR:
+                return BinaryUtils.doReadFloatArray(reader.in());
+
+            case GridBinaryMarshaller.DOUBLE_ARR:
+                return BinaryUtils.doReadDoubleArray(reader.in());
+
+            case GridBinaryMarshaller.STRING_ARR:
+                return BinaryUtils.doReadStringArray(reader.in());
+
+            case GridBinaryMarshaller.DECIMAL_ARR:
+                return BinaryUtils.doReadDecimalArray(reader.in());
+
+            case GridBinaryMarshaller.UUID_ARR:
+                return BinaryUtils.doReadUuidArray(reader.in());
+
+            case GridBinaryMarshaller.TIME_ARR:
+                return BinaryUtils.doReadTimeArray(reader.in());
+
+            case GridBinaryMarshaller.TIMESTAMP_ARR:
+                return BinaryUtils.doReadTimestampArray(reader.in());
+
+            case GridBinaryMarshaller.DATE_ARR:
+                return BinaryUtils.doReadDateArray(reader.in());
+
+            default:
+                reader.in().position(reader.in().position() - 1);
+
+                if (binObjAllow)
+                    return reader.readObjectDetached();
+                else
+                    throw new BinaryObjectException("Custom objects are not supported");
+        }
+    }
+
+    /**
+     * @param writer Writer.
+     * @param obj Object to write.
+     * @param binObjAllow Allow to write non plain objects.
+     * @throws BinaryObjectException On error.
+     */
+    public static void writeObject(BinaryWriterExImpl writer, @Nullable Object obj, boolean binObjAllow)
+        throws BinaryObjectException {
+        if (obj == null) {
+            writer.writeByte(GridBinaryMarshaller.NULL);
+
+            return;
+        }
+
+        Class<?> cls = obj.getClass();
+
+        if (cls == Boolean.class)
+            writer.writeBooleanFieldPrimitive((Boolean)obj);
+        else if (cls == Byte.class)
+            writer.writeByteFieldPrimitive((Byte)obj);
+        else if (cls == Character.class)
+            writer.writeCharFieldPrimitive((Character)obj);
+        else if (cls == Short.class)
+            writer.writeShortFieldPrimitive((Short)obj);
+        else if (cls == Integer.class)
+            writer.writeIntFieldPrimitive((Integer)obj);
+        else if (cls == Long.class)
+            writer.writeLongFieldPrimitive((Long)obj);
+        else if (cls == Float.class)
+            writer.writeFloatFieldPrimitive((Float)obj);
+        else if (cls == Double.class)
+            writer.writeDoubleFieldPrimitive((Double)obj);
+        else if (cls == String.class)
+            writer.doWriteString((String)obj);
+        else if (cls == BigDecimal.class)
+            writer.doWriteDecimal((BigDecimal)obj);
+        else if (cls == UUID.class)
+            writer.writeUuid((UUID)obj);
+        else if (cls == Time.class)
+            writer.writeTime((Time)obj);
+        else if (cls == Timestamp.class)
+            writer.writeTimestamp((Timestamp)obj);
+        else if (cls == java.sql.Date.class || cls == java.util.Date.class)
+            writer.writeDate((java.util.Date)obj);
+        else if (cls == boolean[].class)
+            writer.writeBooleanArray((boolean[])obj);
+        else if (cls == byte[].class)
+            writer.writeByteArray((byte[])obj);
+        else if (cls == char[].class)
+            writer.writeCharArray((char[])obj);
+        else if (cls == short[].class)
+            writer.writeShortArray((short[])obj);
+        else if (cls == int[].class)
+            writer.writeIntArray((int[])obj);
+        else if (cls == float[].class)
+            writer.writeFloatArray((float[])obj);
+        else if (cls == double[].class)
+            writer.writeDoubleArray((double[])obj);
+        else if (cls == String[].class)
+            writer.writeStringArray((String[])obj);
+        else if (cls == BigDecimal[].class)
+            writer.writeDecimalArray((BigDecimal[])obj);
+        else if (cls == UUID[].class)
+            writer.writeUuidArray((UUID[])obj);
+        else if (cls == Time[].class)
+            writer.writeTimeArray((Time[])obj);
+        else if (cls == Timestamp[].class)
+            writer.writeTimestampArray((Timestamp[])obj);
+        else if (cls == java.util.Date[].class || cls == java.sql.Date[].class)
+            writer.writeDateArray((java.util.Date[])obj);
+        else if (binObjAllow)
+            writer.writeObjectDetached(obj);
+        else
+            throw new BinaryObjectException("Custom objects are not supported");
+    }
+
+    /**
+     * @param cls Class.
+     * @return {@code true} is the type is plain (not user's custom class).
+     */
+    public static boolean isPlainType(Class<?> cls) {
+        return cls == Boolean.class
+            || cls == Byte.class
+            || cls == Character.class
+            || cls == Short.class
+            || cls == Integer.class
+            || cls == Long.class
+            || cls == Float.class
+            || cls == Double.class
+            || cls == String.class
+            || cls == BigDecimal.class
+            || cls == UUID.class
+            || cls == Time.class
+            || cls == Timestamp.class
+            || cls == java.sql.Date.class || cls == java.util.Date.class
+            || cls == boolean[].class
+            || cls == byte[].class
+            || cls == char[].class
+            || cls == short[].class
+            || cls == int[].class
+            || cls == float[].class
+            || cls == double[].class
+            || cls == String[].class
+            || cls == BigDecimal[].class
+            || cls == UUID[].class
+            || cls == Time[].class
+            || cls == Timestamp[].class
+            || cls == java.util.Date[].class || cls == java.sql.Date[].class;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java
new file mode 100644
index 0000000..07cbabe
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java
@@ -0,0 +1,129 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.jdbc.thin.JdbcThinUtils;
+import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+
+/**
+ * SQL listener column metadata.
+ */
+public class JdbcColumnMeta implements JdbcRawBinarylizable {
+    /** Cache name. */
+    private String schemaName;
+
+    /** Table name. */
+    private String tableName;
+
+    /** Column name. */
+    private String columnName;
+
+    /** Data type. */
+    private int dataType;
+
+    /** Data type. */
+    private String dataTypeName;
+
+    /** Data type. */
+    private String dataTypeClass;
+
+    /**
+     * Default constructor is used for serialization.
+     */
+    public JdbcColumnMeta() {
+    }
+
+    /**
+     * @param info Field metadata.
+     */
+    public JdbcColumnMeta(GridQueryFieldMetadata info) {
+        this.schemaName = info.schemaName();
+        this.tableName = info.typeName();
+        this.columnName = info.fieldName();
+
+        dataType = JdbcThinUtils.type(info.fieldTypeName());
+        dataTypeName = JdbcThinUtils.typeName(info.fieldTypeName());
+        dataTypeClass = info.fieldTypeName();
+    }
+
+    /**
+     * @return Schema name.
+     */
+    public String schemaName() {
+        return schemaName;
+    }
+
+    /**
+     * @return Table name.
+     */
+    public String tableName() {
+        return tableName;
+    }
+
+    /**
+     * @return Column name.
+     */
+    public String columnName() {
+        return columnName;
+    }
+
+    /**
+     * @return Column's data type.
+     */
+    public int dataType() {
+        return dataType;
+    }
+
+    /**
+     * @return Column's data type name.
+     */
+    public String dataTypeName() {
+        return dataTypeName;
+    }
+
+    /**
+     * @return Column's data type class.
+     */
+    public String dataTypeClass() {
+        return dataTypeClass;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) {
+        writer.writeString(schemaName);
+        writer.writeString(tableName);
+        writer.writeString(columnName);
+
+        writer.writeInt(dataType);
+        writer.writeString(dataTypeName);
+        writer.writeString(dataTypeClass);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) {
+        schemaName = reader.readString();
+        tableName = reader.readString();
+        columnName = reader.readString();
+
+        dataType = reader.readInt();
+        dataTypeName = reader.readString();
+        dataTypeClass = reader.readString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMessageParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMessageParser.java
index cf87712..0f8a3ef 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMessageParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMessageParser.java
@@ -23,28 +23,65 @@ import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream;
 import org.apache.ignite.internal.binary.streams.BinaryHeapOutputStream;
 import org.apache.ignite.internal.binary.streams.BinaryInputStream;
-import org.apache.ignite.internal.processors.odbc.SqlListenerAbstractMessageParser;
+import org.apache.ignite.internal.processors.odbc.SqlListenerMessageParser;
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
+import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
 
 /**
  * JDBC message parser.
  */
-public class JdbcMessageParser extends SqlListenerAbstractMessageParser {
+public class JdbcMessageParser implements SqlListenerMessageParser {
+    /** Kernal context. */
+    private final GridKernalContext ctx;
+
+    /** Initial output stream capacity. */
+    protected static final int INIT_CAP = 1024;
+
     /**
      * @param ctx Context.
      */
     public JdbcMessageParser(GridKernalContext ctx) {
-        super(ctx, new JdbcObjectReader(), new JdbcObjectWriter());
+        this.ctx = ctx;
     }
 
-    /** {@inheritDoc} */
-    @Override protected BinaryReaderExImpl createReader(byte[] msg) {
+    /**
+     * @param msg Message.
+     * @return Reader.
+     */
+    protected BinaryReaderExImpl createReader(byte[] msg) {
         BinaryInputStream stream = new BinaryHeapInputStream(msg);
 
         return new BinaryReaderExImpl(null, stream, ctx.config().getClassLoader(), true);
     }
 
-    /** {@inheritDoc} */
-    @Override protected BinaryWriterExImpl createWriter(int cap) {
+    /**
+     * @param cap Capacisty
+     * @return Writer.
+     */
+    protected BinaryWriterExImpl createWriter(int cap) {
         return new BinaryWriterExImpl(null, new BinaryHeapOutputStream(cap), null, null);
     }
-}
+
+    /** {@inheritDoc} */
+    @Override public SqlListenerRequest decode(byte[] msg) {
+        assert msg != null;
+
+        BinaryReaderExImpl reader = createReader(msg);
+
+        return JdbcRequest.readRequest(reader);
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte[] encode(SqlListenerResponse msg) {
+        assert msg != null;
+
+        assert msg instanceof JdbcResponse;
+
+        JdbcResponse res = (JdbcResponse)msg;
+
+        BinaryWriterExImpl writer = createWriter(INIT_CAP);
+
+        res.writeBinary(writer);
+
+        return writer.array();
+    }}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectReader.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectReader.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectReader.java
deleted file mode 100644
index 81c8c10..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectReader.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc.jdbc;
-
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.internal.binary.BinaryReaderExImpl;
-import org.apache.ignite.internal.processors.odbc.SqlListenerAbstractObjectReader;
-
-/**
- * Binary reader with marshaling non-primitive and non-embedded objects with JDK marshaller.
- */
-@SuppressWarnings("unchecked")
-public class JdbcObjectReader extends SqlListenerAbstractObjectReader {
-    /** {@inheritDoc} */
-    @Override protected Object readCustomObject(BinaryReaderExImpl reader) throws BinaryObjectException {
-        throw new BinaryObjectException("JDBC doesn't support custom objects.");
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectWriter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectWriter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectWriter.java
deleted file mode 100644
index e87ef50..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectWriter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.odbc.jdbc;
-
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.internal.binary.BinaryWriterExImpl;
-import org.apache.ignite.internal.processors.odbc.SqlListenerAbstractObjectWriter;
-
-/**
- * Binary writer with marshaling non-primitive and non-embedded objects with JDK marshaller..
- */
-public class JdbcObjectWriter extends SqlListenerAbstractObjectWriter {
-    /** {@inheritDoc} */
-    @Override protected void writeCustomObject(BinaryWriterExImpl writer, Object obj)
-        throws BinaryObjectException {
-        throw new BinaryObjectException("JDBC doesn't support custom objects.");
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCloseRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCloseRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCloseRequest.java
new file mode 100644
index 0000000..411d1e0
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCloseRequest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * SQL listener query close request.
+ */
+public class JdbcQueryCloseRequest extends JdbcRequest {
+    /** Query ID. */
+    private long queryId;
+
+    /**
+     */
+    public JdbcQueryCloseRequest() {
+        super(QRY_CLOSE);
+    }
+
+    /**
+     * @param queryId Query ID.
+     */
+    public JdbcQueryCloseRequest(long queryId) {
+        super(QRY_CLOSE);
+
+        this.queryId = queryId;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeLong(queryId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        queryId = reader.readLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcQueryCloseRequest.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCursor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCursor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCursor.java
new file mode 100644
index 0000000..b8edb8d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCursor.java
@@ -0,0 +1,132 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
+import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+
+/**
+ * SQL listener query fetch result.
+ */
+class JdbcQueryCursor {
+    /** Query ID. */
+    private final long queryId;
+
+    /** Fetch size. */
+    private int pageSize;
+
+    /** Max rows. */
+    private final long maxRows;
+
+    /** Number of fetched rows. */
+    private long fetched;
+
+    /** Query result rows. */
+    private final QueryCursorImpl<List<Object>> cur;
+
+    /** Query results iterator. */
+    private final Iterator<List<Object>> iter;
+
+    /**
+     * @param queryId Query ID.
+     * @param pageSize Fetch size.
+     * @param maxRows Max rows.
+     * @param cur Query cursor.
+     */
+    JdbcQueryCursor(long queryId, int pageSize, int maxRows, QueryCursorImpl<List<Object>> cur) {
+        this.queryId = queryId;
+        this.pageSize = pageSize;
+        this.maxRows = maxRows;
+        this.cur = cur;
+
+        iter = cur.iterator();
+    }
+
+    /**
+     * @return List of the rows.
+     */
+    List<List<Object>> fetchRows() {
+        List<List<Object>> items = new ArrayList<>();
+
+        int fetchSize0 = (maxRows > 0) ? (int)Math.min(pageSize, maxRows - fetched) : pageSize;
+
+        for (; fetched < fetchSize0 && iter.hasNext(); ++fetched)
+            items.add(iter.next());
+
+        return items;
+    }
+
+    /**
+     * @return Query metadata.
+     */
+    List<JdbcColumnMeta> meta() {
+        List<?> meta = cur.fieldsMeta();
+
+        List<JdbcColumnMeta> res = new ArrayList<>();
+
+        if (meta != null) {
+            for (Object info : meta) {
+                assert info instanceof GridQueryFieldMetadata;
+
+                res.add(new JdbcColumnMeta((GridQueryFieldMetadata)info));
+            }
+        }
+
+        return res;
+    }
+
+    /**
+     * @return {@code true} if the cursor has more rows
+     */
+    boolean hasNext() {
+        return iter.hasNext() && !(maxRows > 0 && fetched >= maxRows);
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /**
+     * Close the cursor.
+     */
+    public void close() {
+        cur.close();
+    }
+
+    /**
+     * @param pageSize New fetch size.
+     */
+    public void pageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * @return {@code true} if this cursor corresponds to a {@link ResultSet} as a result of query,
+     * {@code false} if query was modifying operation like INSERT, UPDATE, or DELETE.
+     */
+    public boolean isQuery() {
+        return cur.isQuery();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
new file mode 100644
index 0000000..f132366
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.processors.odbc.SqlListenerUtils;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * SQL listener query execute request.
+ */
+public class JdbcQueryExecuteRequest extends JdbcRequest {
+    /** Cache name. */
+    private String schemaName;
+
+    /** Fetch size. */
+    private int pageSize;
+
+    /** Max rows. */
+    private int maxRows;
+
+    /** Sql query. */
+    @GridToStringInclude(sensitive = true)
+    private String sqlQry;
+
+    /** Sql query arguments. */
+    @GridToStringInclude(sensitive = true)
+    private Object[] args;
+
+    /**
+     */
+    public JdbcQueryExecuteRequest() {
+        super(QRY_EXEC);
+    }
+
+    /**
+     * @param schemaName Cache name.
+     * @param pageSize Fetch size.
+     * @param maxRows Max rows.
+     * @param sqlQry SQL query.
+     * @param args Arguments list.
+     */
+    public JdbcQueryExecuteRequest(String schemaName, int pageSize, int maxRows, String sqlQry,
+        Object[] args) {
+        super(QRY_EXEC);
+
+        this.schemaName = F.isEmpty(schemaName) ? null : schemaName;
+        this.pageSize = pageSize;
+        this.maxRows = maxRows;
+        this.sqlQry = sqlQry;
+        this.args = args;
+    }
+
+    /**
+     * @return Fetch size.
+     */
+    public int pageSize() {
+        return pageSize;
+    }
+
+    /**
+     * @return Max rows.
+     */
+    public int maxRows() {
+        return maxRows;
+    }
+
+    /**
+     * @return Sql query.
+     */
+    public String sqlQuery() {
+        return sqlQry;
+    }
+
+    /**
+     * @return Sql query arguments.
+     */
+    public Object[] arguments() {
+        return args;
+    }
+
+    /**
+     * @return Cache name.
+     */
+    @Nullable public String schemaName() {
+        return schemaName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeString(schemaName);
+        writer.writeInt(pageSize);
+        writer.writeInt(maxRows);
+        writer.writeString(sqlQry);
+
+        writer.writeInt(args == null ? 0 : args.length);
+
+        if (args != null) {
+            for (Object arg : args)
+                SqlListenerUtils.writeObject(writer, arg, false);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        schemaName = reader.readString();
+        pageSize = reader.readInt();
+        maxRows = reader.readInt();
+        sqlQry = reader.readString();
+
+        int argsNum = reader.readInt();
+
+        args = new Object[argsNum];
+
+        for (int i = 0; i < argsNum; ++i)
+            args[i] = SqlListenerUtils.readObject(reader, false);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcQueryExecuteRequest.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteResult.java
new file mode 100644
index 0000000..a935215
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteResult.java
@@ -0,0 +1,150 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import java.util.List;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+
+/**
+ * SQL listener query execute result.
+ */
+public class JdbcQueryExecuteResult extends JdbcResult {
+    /** Query ID. */
+    private long queryId;
+
+    /** Query result rows. */
+    private List<List<Object>> items;
+
+    /** Flag indicating the query has no unfetched results. */
+    private boolean last;
+
+    /** Flag indicating the query is SELECT query. {@code false} for DML/DDL queries. */
+    private boolean isQuery;
+
+    /** Update count. */
+    private long updateCnt;
+
+    /**
+     * Condtructor.
+     */
+    public JdbcQueryExecuteResult() {
+        super(QRY_EXEC);
+    }
+
+    /**
+     * @param queryId Query ID.
+     * @param items Query result rows.
+     * @param last Flag indicates the query has no unfetched results.
+     */
+    public JdbcQueryExecuteResult(long queryId, List<List<Object>> items, boolean last) {
+        super(QRY_EXEC);
+
+        this.queryId = queryId;
+        this.items = items;
+        this.last = last;
+        this.isQuery = true;
+    }
+
+    /**
+     * @param queryId Query ID.
+     * @param updateCnt Update count for DML queries.
+     */
+    public JdbcQueryExecuteResult(long queryId, long updateCnt) {
+        super(QRY_EXEC);
+
+        this.queryId = queryId;
+        this.last = true;
+        this.isQuery = false;
+        this.updateCnt = updateCnt;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long getQueryId() {
+        return queryId;
+    }
+
+    /**
+     * @return Query result rows.
+     */
+    public List<List<Object>> items() {
+        return items;
+    }
+
+    /**
+     * @return Flag indicating the query has no unfetched results.
+     */
+    public boolean last() {
+        return last;
+    }
+
+    /**
+     * @return Flag indicating the query is SELECT query. {@code false} for DML/DDL queries.
+     */
+    public boolean isQuery() {
+        return isQuery;
+    }
+
+    /**
+     * @return Update count for DML queries.
+     */
+    public long updateCount() {
+        return updateCnt;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeLong(queryId);
+        writer.writeBoolean(isQuery);
+
+        if (isQuery) {
+            assert items != null;
+
+            writer.writeBoolean(last);
+
+            JdbcUtils.writeItems(writer, items);
+        }
+        else
+            writer.writeLong(updateCnt);
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        queryId = reader.readLong();
+        isQuery = reader.readBoolean();
+
+        if (isQuery) {
+            last = reader.readBoolean();
+
+            items = JdbcUtils.readItems(reader);
+        }
+        else {
+            last = true;
+
+            updateCnt = reader.readLong();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchRequest.java
new file mode 100644
index 0000000..2e1f551
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchRequest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * SQL listener query fetch request.
+ */
+public class JdbcQueryFetchRequest extends JdbcRequest {
+    /** Query ID. */
+    private long queryId;
+
+    /** Fetch size. */
+    private int pageSize;
+
+    /**
+     * Constructor.
+     */
+    public JdbcQueryFetchRequest() {
+        super(QRY_FETCH);
+    }
+
+    /**
+     * @param queryId Query ID.
+     * @param pageSize Fetch size.
+     */
+    public JdbcQueryFetchRequest(long queryId, int pageSize) {
+        super(QRY_FETCH);
+
+        this.queryId = queryId;
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /**
+     * @return Fetch page size.
+     */
+    public int pageSize() {
+        return pageSize;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeLong(queryId);
+        writer.writeInt(pageSize);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        queryId = reader.readLong();
+        pageSize = reader.readInt();
+   }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcQueryFetchRequest.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchResult.java
new file mode 100644
index 0000000..6735c6b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchResult.java
@@ -0,0 +1,84 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import java.util.List;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+
+/**
+ * SQL listener query fetch result.
+ */
+public class JdbcQueryFetchResult extends JdbcResult {
+    /** Query result rows. */
+    private List<List<Object>> items;
+
+    /** Flag indicating the query has no unfetched results. */
+    private boolean last;
+
+    /**
+     * Default constructor is used for deserialization.
+     */
+    public JdbcQueryFetchResult() {
+        super(QRY_FETCH);
+    }
+
+    /**
+     * @param items Query result rows.
+     * @param last Flag indicating the query has no unfetched results.
+     */
+    public JdbcQueryFetchResult(List<List<Object>> items, boolean last){
+        super(QRY_FETCH);
+
+        this.items = items;
+        this.last = last;
+    }
+
+    /**
+     * @return Query result rows.
+     */
+    public List<List<Object>> items() {
+        return items;
+    }
+
+    /**
+     * @return Flag indicating the query has no unfetched results.
+     */
+    public boolean last() {
+        return last;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeBoolean(last);
+
+        JdbcUtils.writeItems(writer, items);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        last = reader.readBoolean();
+
+        items = JdbcUtils.readItems(reader);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataRequest.java
new file mode 100644
index 0000000..d14c9df
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataRequest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * SQL listener query metadata request.
+ */
+public class JdbcQueryMetadataRequest extends JdbcRequest {
+    /** Query ID. */
+    private long queryId;
+
+    /**
+     * Constructor.
+     */
+    public JdbcQueryMetadataRequest() {
+        super(QRY_META);
+    }
+
+    /**
+     * @param queryId Query ID.
+     */
+    public JdbcQueryMetadataRequest(long queryId) {
+        super(QRY_META);
+
+        this.queryId = queryId;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeLong(queryId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        queryId = reader.readLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcQueryMetadataRequest.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataResult.java
new file mode 100644
index 0000000..cc193e3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataResult.java
@@ -0,0 +1,93 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.util.typedef.F;
+
+/**
+ * SQL listener query metadata result.
+ */
+public class JdbcQueryMetadataResult extends JdbcResult {
+    /** Fields metadata. */
+    private List<JdbcColumnMeta> meta;
+
+    /**
+     * Default constructor is used for deserialization.
+     */
+    public JdbcQueryMetadataResult() {
+        super(QRY_META);
+    }
+
+    /**
+     * @param queryId Query ID.
+     * @param meta Query metadata.
+     */
+    public JdbcQueryMetadataResult(long queryId, List<JdbcColumnMeta> meta){
+        super(QRY_META);
+
+        this.meta = meta;
+    }
+
+    /**
+     * @return Query result rows.
+     */
+    public List<JdbcColumnMeta> meta() {
+        return meta;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        if (F.isEmpty(meta))
+            writer.writeInt(0);
+        else {
+            writer.writeInt(meta.size());
+
+            for (JdbcColumnMeta m : meta)
+                m.writeBinary(writer);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        int size = reader.readInt();
+
+        if (size == 0)
+            meta = Collections.emptyList();
+        else {
+            meta = new ArrayList<>(size);
+
+            for (int i = 0; i < size; ++i) {
+                JdbcColumnMeta m = new JdbcColumnMeta();
+
+                m.readBinary(reader);
+
+                meta.add(m);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRawBinarylizable.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRawBinarylizable.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRawBinarylizable.java
new file mode 100644
index 0000000..c3f1874
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRawBinarylizable.java
@@ -0,0 +1,44 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+
+/**
+ * Interface that allows to implement custom serialization
+ * logic to raw binary streams.
+ */
+public interface JdbcRawBinarylizable {
+    /**
+     * Writes fields to provided writer.
+     *
+     * @param writer Binary object writer.
+     * @throws BinaryObjectException In case of error.
+     */
+    public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException;
+
+    /**
+     * Reads fields from provided reader.
+     *
+     * @param reader Binary object reader.
+     * @throws BinaryObjectException In case of error.
+     */
+    public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequest.java
new file mode 100644
index 0000000..d6f8fd3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.processors.odbc.jdbc;
+
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
+
+/**
+ * SQL listener command request.
+ */
+public class JdbcRequest extends SqlListenerRequest implements JdbcRawBinarylizable {
+    /** Execute sql query. */
+    public static final byte QRY_EXEC = 2;
+
+    /** Fetch query results. */
+    public static final byte QRY_FETCH = 3;
+
+    /** Close query. */
+    public static final byte QRY_CLOSE = 4;
+
+    /** Get columns meta query. */
+    public static final byte QRY_META = 5;
+
+    /** Request type. */
+    private byte type;
+
+    /**
+     * @param type Command type.
+     */
+    public JdbcRequest(byte type) {
+        this.type = type;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        writer.writeByte(type);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        // No-op.
+    }
+
+    /**
+     * @return Request type.
+     */
+    public byte type() {
+        return type;
+    }
+
+    /**
+     * @param reader Binary reader.
+     * @return Request object.
+     * @throws BinaryObjectException On error.
+     */
+    public static JdbcRequest readRequest(BinaryReaderExImpl reader) throws BinaryObjectException {
+        int reqType = reader.readByte();
+
+        JdbcRequest req;
+
+        switch(reqType) {
+            case QRY_EXEC:
+                req = new JdbcQueryExecuteRequest();
+
+                break;
+
+            case QRY_FETCH:
+                req = new JdbcQueryFetchRequest();
+
+                break;
+
+            case QRY_META:
+                req = new JdbcQueryMetadataRequest();
+
+                break;
+
+            case QRY_CLOSE:
+                req = new JdbcQueryCloseRequest();
+
+                break;
+
+            default:
+                throw new IgniteException("Unknown SQL listener request ID: [request ID=" + reqType + ']');
+        }
+
+        req.readBinary(reader);
+
+        return req;
+    }
+}


[05/50] [abbrv] ignite git commit: IGNITE-5335: Binary serialization: fixed reading of negative decimal values. This closes #2034.

Posted by sb...@apache.org.
IGNITE-5335: Binary serialization: fixed reading of negative decimal values. This closes #2034.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/fd838d5e
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/fd838d5e
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/fd838d5e

Branch: refs/heads/ignite-5075
Commit: fd838d5e2d29d6b1a0d0b68bef013013030c8275
Parents: fbf0e35
Author: Sergey Kalashnikov <sk...@gridgain.com>
Authored: Fri Jun 2 14:28:41 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Jun 2 14:28:41 2017 +0300

----------------------------------------------------------------------
 .../ignite/internal/binary/BinaryFieldImpl.java | 10 ++--
 .../internal/binary/BinaryObjectImpl.java       | 10 ++--
 .../binary/BinaryObjectOffheapImpl.java         | 10 ++--
 .../binary/BinaryFieldExtractionSelfTest.java   | 52 ++++++++++++++++++++
 .../binary/BinaryMarshallerSelfTest.java        | 36 ++++++++++++--
 5 files changed, 101 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/fd838d5e/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldImpl.java
index 477ae37..c318397 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldImpl.java
@@ -222,13 +222,15 @@ public class BinaryFieldImpl implements BinaryFieldEx {
 
                     buf.get(data);
 
-                    BigInteger intVal = new BigInteger(data);
+                    boolean negative = data[0] < 0;
+
+                    if (negative)
+                        data[0] &= 0x7F;
 
-                    if (scale < 0) {
-                        scale &= 0x7FFFFFFF;
+                    BigInteger intVal = new BigInteger(data);
 
+                    if (negative)
                         intVal = intVal.negate();
-                    }
 
                     val = new BigDecimal(intVal, scale);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/fd838d5e/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
index adbb9cb..1e706ae 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
@@ -474,13 +474,15 @@ public final class BinaryObjectImpl extends BinaryObjectExImpl implements Extern
                 int dataLen = BinaryPrimitives.readInt(arr, fieldPos + 5);
                 byte[] data = BinaryPrimitives.readByteArray(arr, fieldPos + 9, dataLen);
 
-                BigInteger intVal = new BigInteger(data);
+                boolean negative = data[0] < 0;
+
+                if (negative)
+                    data[0] &= 0x7F;
 
-                if (scale < 0) {
-                    scale &= 0x7FFFFFFF;
+                BigInteger intVal = new BigInteger(data);
 
+                if (negative)
                     intVal = intVal.negate();
-                }
 
                 val = new BigDecimal(intVal, scale);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/fd838d5e/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
index 3e73e58..05f6963 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
@@ -369,13 +369,15 @@ public class BinaryObjectOffheapImpl extends BinaryObjectExImpl implements Exter
                 int dataLen = BinaryPrimitives.readInt(ptr, fieldPos + 5);
                 byte[] data = BinaryPrimitives.readByteArray(ptr, fieldPos + 9, dataLen);
 
-                BigInteger intVal = new BigInteger(data);
+                boolean negative = data[0] < 0;
+
+                if (negative)
+                    data[0] &= 0x7F;
 
-                if (scale < 0) {
-                    scale &= 0x7FFFFFFF;
+                BigInteger intVal = new BigInteger(data);
 
+                if (negative)
                     intVal = intVal.negate();
-                }
 
                 val = new BigDecimal(intVal, scale);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/fd838d5e/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFieldExtractionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFieldExtractionSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFieldExtractionSelfTest.java
index 5721128..9f39746 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFieldExtractionSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFieldExtractionSelfTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.binary;
 
+import java.math.BigDecimal;
 import java.nio.ByteBuffer;
 import java.util.concurrent.ThreadLocalRandom;
 import org.apache.ignite.configuration.BinaryConfiguration;
@@ -97,6 +98,40 @@ public class BinaryFieldExtractionSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testDecimalFieldMarshalling() throws Exception {
+        BinaryMarshaller marsh = createMarshaller();
+
+        BigDecimal values[] = new BigDecimal[] { BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN,
+            new BigDecimal("-100.5"), BigDecimal.valueOf(Long.MAX_VALUE, 0),
+            BigDecimal.valueOf(Long.MIN_VALUE, 0), BigDecimal.valueOf(Long.MAX_VALUE, 8),
+            BigDecimal.valueOf(Long.MIN_VALUE, 8)};
+
+        DecimalValue decVal = new DecimalValue(values[0]);
+
+        BinaryObjectImpl binObj = toBinary(decVal, marsh);
+
+        BinaryFieldEx field = (BinaryFieldEx)binObj.type().field("decVal");
+
+        ByteBuffer buf = ByteBuffer.allocate(64);
+
+        for (BigDecimal value : values) {
+            decVal = new DecimalValue(value);
+
+            binObj = toBinary(decVal, marsh);
+
+            field.writeField(binObj, buf);
+
+            buf.flip();
+
+            assertEquals(field.value(binObj), field.readField(buf));
+
+            buf.clear();
+        }
+    }
+
+    /**
      * @param obj Object to transform to a binary object.
      * @param marsh Binary marshaller.
      * @return Binary object.
@@ -158,4 +193,21 @@ public class BinaryFieldExtractionSelfTest extends GridCommonAbstractTest {
             dVal = seed;
         }
     }
+
+    /**
+     *
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class DecimalValue {
+        /** */
+        private BigDecimal decVal;
+
+        /**
+         *
+         * @param decVal Value to use
+         */
+        private DecimalValue(BigDecimal decVal) {
+            this.decVal = decVal;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/fd838d5e/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
index ee72919..a4ace13 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
@@ -2626,16 +2626,29 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
         // 1. Test reflective stuff.
         DecimalReflective obj1 = new DecimalReflective();
 
-        obj1.val = BigDecimal.ZERO;
-        obj1.valArr = new BigDecimal[] {BigDecimal.ONE, BigDecimal.TEN};
+        BigDecimal valArr[] = new BigDecimal[] {BigDecimal.ONE, BigDecimal.TEN, new BigDecimal("-100.5"),
+            BigDecimal.valueOf(Long.MAX_VALUE, 0), BigDecimal.valueOf(Long.MIN_VALUE, 0),
+            BigDecimal.valueOf(Long.MAX_VALUE, 8), BigDecimal.valueOf(Long.MIN_VALUE, 8)};
 
+        obj1.val = BigDecimal.ZERO;
+        obj1.valArr = valArr;
         BinaryObjectImpl portObj = marshal(obj1, marsh);
 
-        assertEquals(obj1.val, portObj.field("val"));
         assertArrayEquals(obj1.valArr, portObj.<BigDecimal[]>field("valArr"));
-
-        assertEquals(obj1.val, portObj.<DecimalReflective>deserialize().val);
         assertArrayEquals(obj1.valArr, portObj.<DecimalReflective>deserialize().valArr);
+        assertArrayEquals(obj1.valArr, (BigDecimal[])portObj.type().field("valArr").value(portObj));
+
+        obj1.valArr = null;
+
+        for (BigDecimal v: valArr) {
+            obj1.val = v;
+
+            portObj = marshal(obj1, marsh);
+
+            assertEquals(obj1.val, portObj.field("val"));
+            assertEquals(obj1.val, portObj.<DecimalReflective>deserialize().val);
+            assertEquals(obj1.val, portObj.type().field("val").value(portObj));
+        }
 
         // 2. Test marshal aware stuff.
         DecimalMarshalAware obj2 = new DecimalMarshalAware();
@@ -2654,6 +2667,19 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
         assertArrayEquals(obj2.valArr, portObj.<DecimalMarshalAware>deserialize().valArr);
         assertEquals(obj2.rawVal, portObj.<DecimalMarshalAware>deserialize().rawVal);
         assertArrayEquals(obj2.rawValArr, portObj.<DecimalMarshalAware>deserialize().rawValArr);
+
+        assertEquals(obj2.val, portObj.type().field("val").value(portObj));
+        assertArrayEquals(obj2.valArr, (BigDecimal[])portObj.type().field("valArr").value(portObj));
+
+        for (BigDecimal v: valArr) {
+            obj2.val = v;
+
+            portObj = marshal(obj2, marsh);
+
+            assertEquals(obj2.val, portObj.field("val"));
+            assertEquals(obj2.val, portObj.<DecimalMarshalAware>deserialize().val);
+            assertEquals(obj2.val, portObj.type().field("val").value(portObj));
+        }
     }
 
     /**