IGNITE-6055: SQL. Add string length constraint - Fixes #3973.

Signed-off-by: Nikolay Izhikov <nizhi...@apache.org>


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

Branch: refs/heads/master
Commit: baab0a6ddd3973fb8fca6ecb0a7d841d7d3a72be
Parents: a98dcb9
Author: Nikolay Izhikov <nizhi...@apache.org>
Authored: Tue Aug 28 09:59:15 2018 +0300
Committer: Nikolay Izhikov <nizhi...@apache.org>
Committed: Tue Aug 28 09:59:15 2018 +0300

----------------------------------------------------------------------
 .../jdbc/thin/JdbcThinMetadataSelfTest.java     |  49 ++-
 .../org/apache/ignite/cache/QueryEntity.java    |  91 +++--
 .../internal/client/thin/ClientChannel.java     |   5 +
 .../internal/client/thin/ClientUtils.java       |  62 ++-
 .../internal/client/thin/ReliableChannel.java   |   7 +
 .../internal/client/thin/TcpClientCache.java    |   3 +-
 .../internal/client/thin/TcpClientChannel.java  |  16 +-
 .../internal/client/thin/TcpIgniteClient.java   |  17 +-
 .../jdbc/thin/JdbcThinDatabaseMetadata.java     |   2 +-
 .../internal/jdbc/thin/JdbcThinTcpIo.java       |   7 +-
 .../cache/query/IgniteQueryErrorCode.java       |   8 +
 .../cache/query/QueryEntityTypeDescriptor.java  |  39 +-
 .../odbc/jdbc/JdbcConnectionContext.java        |   6 +-
 .../odbc/jdbc/JdbcRequestHandler.java           |   7 +-
 .../processors/odbc/odbc/OdbcColumnMeta.java    |  37 +-
 .../odbc/odbc/OdbcConnectionContext.java        |   8 +-
 .../processors/odbc/odbc/OdbcQueryResults.java  |  10 +-
 .../odbc/odbc/OdbcRequestHandler.java           |  20 +-
 .../processors/odbc/odbc/OdbcResultSet.java     |  16 +-
 .../platform/PlatformProcessorImpl.java         |   9 +-
 .../platform/cache/PlatformCache.java           |   4 +-
 .../client/ClientConnectionContext.java         |  17 +-
 .../platform/client/ClientMessageParser.java    |  16 +-
 .../ClientCacheConfigurationSerializer.java     |  11 +-
 ...ientCacheCreateWithConfigurationRequest.java |   6 +-
 .../ClientCacheGetConfigurationRequest.java     |  11 +-
 .../ClientCacheGetConfigurationResponse.java    |  11 +-
 ...acheGetOrCreateWithConfigurationRequest.java |   6 +-
 .../PlatformDotNetConfigurationClosure.java     |   4 +-
 .../utils/PlatformConfigurationUtils.java       |  77 ++--
 .../query/GridQueryFieldMetadata.java           |  16 +-
 .../processors/query/GridQueryProcessor.java    |  13 +-
 .../internal/processors/query/QueryField.java   |   2 +
 .../query/QueryTypeDescriptorImpl.java          |  71 +++-
 .../internal/processors/query/QueryUtils.java   | 103 ++++-
 .../ignite/testframework/GridTestUtils.java     |  18 +
 .../processors/query/h2/H2SqlFieldMetadata.java |  28 +-
 .../internal/processors/query/h2/H2Utils.java   |   4 +-
 .../processors/query/h2/IgniteH2Indexing.java   |  38 +-
 .../query/h2/ddl/DdlStatementsProcessor.java    |  23 +-
 .../IgniteCacheAbstractFieldsQuerySelfTest.java | 104 ++++-
 .../cache/index/IgniteDecimalSelfTest.java      |  35 +-
 ...ePartitionedAtomicColumnConstraintsTest.java | 398 +++++++++++++++++++
 ...ionedTransactionalColumnConstraintsTest.java |  30 ++
 ...heReplicatedAtomicColumnConstraintsTest.java |  32 ++
 ...catedTransactionalColumnConstraintsTest.java |  30 ++
 .../sql/IgniteSQLColumnConstraintsTest.java     | 143 +++++++
 .../IgniteCacheQuerySelfTestSuite.java          |  11 +
 .../cpp/common/include/ignite/common/utils.h    |   2 +-
 .../cpp/odbc-test/config/queries-default.xml    |   6 +
 .../cpp/odbc-test/src/meta_queries_test.cpp     |  17 +
 .../odbc/include/ignite/odbc/meta/column_meta.h |  47 ++-
 .../odbc/include/ignite/odbc/protocol_version.h |   5 +-
 modules/platforms/cpp/odbc/src/message.cpp      |  10 +-
 .../platforms/cpp/odbc/src/meta/column_meta.cpp |  68 +++-
 .../platforms/cpp/odbc/src/protocol_version.cpp |   4 +-
 .../QueryEntityConfigurationParityTest.cs       |   3 +-
 .../Cache/ClientCacheConfigurationTest.cs       |   5 +-
 .../Cache/Configuration/CacheConfiguration.cs   |  27 +-
 .../Cache/Configuration/QueryEntity.cs          |  12 +-
 .../Cache/Configuration/QueryField.cs           |  28 +-
 .../Configuration/QuerySqlFieldAttribute.cs     |   2 +
 .../Client/Cache/CacheClientConfiguration.cs    |   9 +-
 .../Apache.Ignite.Core/IgniteConfiguration.cs   |  26 +-
 .../dotnet/Apache.Ignite.Core/Ignition.cs       |   3 +-
 .../Impl/Binary/BinaryWriterExtensions.cs       |  31 +-
 .../Impl/Binary/IBinaryRawWriteAware.cs         |  25 +-
 .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs  |   3 +-
 .../Impl/Client/Cache/CacheClient.cs            |   3 +-
 .../Cache/ClientCacheConfigurationSerializer.cs |   9 +-
 .../Impl/Client/ClientSocket.cs                 |  22 +-
 .../Impl/Client/IgniteClient.cs                 |  11 +-
 .../dotnet/Apache.Ignite.Core/Impl/Ignite.cs    |   8 +-
 .../nodejs/lib/internal/ClientSocket.js         |  10 +-
 74 files changed, 1779 insertions(+), 298 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/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
index 8e35a86..59382f1 100644
--- 
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
@@ -18,7 +18,6 @@
 package org.apache.ignite.jdbc.thin;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.DriverManager;
@@ -32,13 +31,16 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Set;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.QueryIndex;
 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.IgniteVersionUtils;
@@ -99,10 +101,15 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
 
         startGridsMultiThreaded(3);
 
+        Map<String, Integer> orgPrecision = new HashMap<>();
+        
+        orgPrecision.put("name", 42);
+
         IgniteCache<String, Organization> orgCache = jcache(grid(0),
             cacheConfiguration(new QueryEntity(String.class.getName(), 
Organization.class.getName())
                 .addQueryField("id", Integer.class.getName(), null)
                 .addQueryField("name", String.class.getName(), null)
+                .setFieldsPrecision(orgPrecision)
                 .setIndexes(Arrays.asList(
                     new QueryIndex("id"),
                     new QueryIndex("name", false, "org_name_index")
@@ -136,6 +143,9 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
         personCache.put(new AffinityKey<>("p2", "o1"), new Person("Joe Black", 
35, 1));
         personCache.put(new AffinityKey<>("p3", "o2"), new Person("Mike 
Green", 40, 2));
 
+        IgniteCache<Integer, Department> departmentCache = jcache(grid(0), 
+            defaultCacheConfiguration().setIndexedTypes(Integer.class, 
Department.class), "dep");
+
         try (Connection conn = DriverManager.getConnection(URL)) {
             Statement stmt = conn.createStatement();
 
@@ -240,6 +250,7 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
             Set<String> expectedTbls = new HashSet<>(Arrays.asList(
                 "org.ORGANIZATION",
                 "pers.PERSON",
+                "dep.DEPARTMENT",
                 "PUBLIC.TEST",
                 "PUBLIC.Quoted",
                 "PUBLIC.TEST_DECIMAL_COLUMN"));
@@ -379,16 +390,18 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
 
             Set<String> expectedCols = new HashSet<>(Arrays.asList(
                 "org.ORGANIZATION.ID.null",
-                "org.ORGANIZATION.NAME.null",
+                "org.ORGANIZATION.NAME.null.42",
                 "pers.PERSON.ORGID.null",
                 "pers.PERSON.AGE.null",
                 "pers.PERSON.NAME.null",
+                "dep.DEPARTMENT.ID.null",
+                "dep.DEPARTMENT.NAME.null.43",
                 "PUBLIC.TEST.ID.null",
-                "PUBLIC.TEST.NAME.'default name'",
-                "PUBLIC.TEST.VAL.null",
+                "PUBLIC.TEST.NAME.'default name'.50",
+                "PUBLIC.TEST.VAL.null.50",
                 "PUBLIC.TEST.AGE.21",
                 "PUBLIC.Quoted.Id.null",
-                "PUBLIC.Quoted.Name.null",
+                "PUBLIC.Quoted.Name.null.50",
                 "PUBLIC.TEST_DECIMAL_COLUMN.ID.null",
                 "PUBLIC.TEST_DECIMAL_COLUMN.DEC_COL.null.8.3"
             ));
@@ -538,6 +551,7 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
             Set<String> expectedPks = new HashSet<>(Arrays.asList(
                 "org.ORGANIZATION.PK_org_ORGANIZATION._KEY",
                 "pers.PERSON.PK_pers_PERSON._KEY",
+                "dep.DEPARTMENT.PK_dep_DEPARTMENT._KEY",
                 "PUBLIC.TEST.PK_PUBLIC_TEST.ID",
                 "PUBLIC.TEST.PK_PUBLIC_TEST.NAME",
                 "PUBLIC.Quoted.PK_PUBLIC_Quoted.Id",
@@ -588,7 +602,7 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
         try (Connection conn = DriverManager.getConnection(URL)) {
             ResultSet rs = conn.getMetaData().getSchemas();
 
-            Set<String> expectedSchemas = new 
HashSet<>(Arrays.asList("PUBLIC", "pers", "org"));
+            Set<String> expectedSchemas = new 
HashSet<>(Arrays.asList("PUBLIC", "pers", "org", "dep"));
 
             Set<String> schemas = new HashSet<>();
 
@@ -674,4 +688,27 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
             this.name = name;
         }
     }
+
+    /**
+     * Organization.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Department implements Serializable {
+        /** ID. */
+        @QuerySqlField
+        private final int id;
+
+        /** Name. */
+        @QuerySqlField(precision = 43)
+        private final String name;
+
+        /**
+         * @param id ID.
+         * @param name Name.
+         */
+        private Department(int id, String name) {
+            this.id = id;
+            this.name = name;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java 
b/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
index 37a7f15..769d74f 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
@@ -20,7 +20,6 @@ package org.apache.ignite.cache;
 import javax.cache.CacheException;
 import java.io.Serializable;
 import java.lang.reflect.Field;
-import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -49,12 +48,9 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.A;
 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.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import static java.util.Collections.unmodifiableMap;
-
 /**
  * Query entity is a description of {@link org.apache.ignite.IgniteCache 
cache} entry (composed of key and value)
  * in a way of how it must be indexed and can be queried.
@@ -100,8 +96,11 @@ public class QueryEntity implements Serializable {
     /** Fields default values. */
     private Map<String, Object> defaultFieldValues = new HashMap<>();
 
-    /** Decimal fields information. */
-    private Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo = new 
HashMap<>();
+    /** Precision(Maximum length) for fields. */
+    private Map<String, Integer> fieldsPrecision = new HashMap<>();
+
+    /** Scale for fields. */
+    private Map<String, Integer> fieldsScale = new HashMap<>();
 
     /**
      * Creates an empty query entity.
@@ -135,7 +134,9 @@ public class QueryEntity implements Serializable {
         defaultFieldValues = other.defaultFieldValues != null ? new 
HashMap<>(other.defaultFieldValues)
             : new HashMap<String, Object>();
 
-        decimalInfo = other.decimalInfo != null ? new 
HashMap<>(other.decimalInfo) : new HashMap<>();
+        fieldsPrecision = other.fieldsPrecision != null ? new 
HashMap<>(other.fieldsPrecision) : new HashMap<>();
+
+        fieldsScale = other.fieldsScale != null ? new 
HashMap<>(other.fieldsScale) : new HashMap<>();
     }
 
     /**
@@ -282,13 +283,29 @@ public class QueryEntity implements Serializable {
                     getFromMap(getDefaultFieldValues(), targetFieldName),
                     getFromMap(target.getDefaultFieldValues(), targetFieldName)
                 );
+
+                checkEquals(conflicts,
+                    "precision of " + targetFieldName,
+                    getFromMap(getFieldsPrecision(), targetFieldName),
+                    getFromMap(target.getFieldsPrecision(), targetFieldName));
+
+                checkEquals(
+                    conflicts,
+                    "scale of " + targetFieldName,
+                    getFromMap(getFieldsScale(), targetFieldName),
+                    getFromMap(target.getFieldsScale(), targetFieldName));
             }
             else {
+                Integer precision = getFromMap(target.getFieldsPrecision(), 
targetFieldName);
+                Integer scale = getFromMap(target.getFieldsScale(), 
targetFieldName);
+
                 queryFieldsToAdd.add(new QueryField(
                     targetFieldName,
                     targetFieldType,
                     !contains(target.getNotNullFields(),targetFieldName),
-                    getFromMap(target.getDefaultFieldValues(), targetFieldName)
+                    getFromMap(target.getDefaultFieldValues(), 
targetFieldName),
+                    precision == null ? -1 : precision,
+                    scale == null ? -1 : scale
                 ));
             }
         }
@@ -308,7 +325,7 @@ public class QueryEntity implements Serializable {
     /**
      * @return Value from sourceMap or null if map is null.
      */
-    private static Object getFromMap(Map<String, Object> sourceMap, String 
key) {
+    private static <V> V getFromMap(Map<String, V> sourceMap, String key) {
         return sourceMap == null ? null : sourceMap.get(key);
     }
 
@@ -320,7 +337,7 @@ public class QueryEntity implements Serializable {
      * @param local Local object.
      * @param received Received object.
      */
-    private void checkEquals(StringBuilder conflicts, String name, Object 
local, Object received) {
+    private <V> void checkEquals(StringBuilder conflicts, String name, V 
local, V received) {
         if (!Objects.equals(local, received))
             conflicts.append(String.format("%s is different: local=%s, 
received=%s\n", name, local, received));
     }
@@ -573,22 +590,39 @@ public class QueryEntity implements Serializable {
     }
 
     /**
-     * Gets set of field name to precision and scale.
+     * @return Precision map for a fields.
+     */
+    public Map<String, Integer> getFieldsPrecision() {
+        return fieldsPrecision;
+    }
+
+    /**
+     * Sets fieldsPrecision map for a fields.
      *
-     * @return Set of names of fields that must have non-null values.
+     * @param fieldsPrecision Precision map for a fields.
+     * @return {@code This} for chaining.
      */
-    public Map<String, IgniteBiTuple<Integer, Integer>> getDecimalInfo() {
-        return decimalInfo == null ? Collections.emptyMap() : 
unmodifiableMap(decimalInfo);
+    public QueryEntity setFieldsPrecision(Map<String, Integer> 
fieldsPrecision) {
+        this.fieldsPrecision = fieldsPrecision;
+
+        return this;
     }
 
     /**
-     * Sets decimal fields info.
+     * @return Scale map for a fields.
+     */
+    public Map<String, Integer> getFieldsScale() {
+        return fieldsScale;
+    }
+
+    /**
+     * Sets fieldsScale map for a fields.
      *
-     * @param decimalInfo Set of name to precision and scale for decimal 
fields.
-     * @return {@code this} for chaining.
+     * @param fieldsScale Scale map for a fields.
+     * @return {@code This} for chaining.
      */
-    public QueryEntity setDecimalInfo(Map<String, IgniteBiTuple<Integer, 
Integer>> decimalInfo) {
-        this.decimalInfo = decimalInfo;
+    public QueryEntity setFieldsScale(Map<String, Integer> fieldsScale) {
+        this.fieldsScale = fieldsScale;
 
         return this;
     }
@@ -707,8 +741,11 @@ public class QueryEntity implements Serializable {
         if (!F.isEmpty(desc.notNullFields()))
             entity.setNotNullFields(desc.notNullFields());
 
-        if (!F.isEmpty(desc.decimalInfo()))
-            entity.setDecimalInfo(desc.decimalInfo());
+        if (!F.isEmpty(desc.fieldsPrecision()))
+            entity.setFieldsPrecision(desc.fieldsPrecision());
+
+        if (!F.isEmpty(desc.fieldsScale()))
+            entity.setFieldsScale(desc.fieldsScale());
 
         return entity;
     }
@@ -835,8 +872,11 @@ public class QueryEntity implements Serializable {
             if (sqlAnn.notNull())
                 desc.addNotNullField(prop.fullName());
 
-            if (BigDecimal.class == fldCls && sqlAnn.precision() != -1 && 
sqlAnn.scale() != -1)
-                desc.addDecimalInfo(prop.fullName(), F.t(sqlAnn.precision(), 
sqlAnn.scale()));
+            if (sqlAnn.precision() != -1)
+                desc.addPrecision(prop.fullName(), sqlAnn.precision());
+
+            if (sqlAnn.scale() != -1)
+                desc.addScale(prop.fullName(), sqlAnn.scale());
 
             if ((!F.isEmpty(sqlAnn.groups()) || 
!F.isEmpty(sqlAnn.orderedGroups()))
                 && sqlAnn.inlineSize() != QueryIndex.DFLT_INLINE_SIZE) {
@@ -880,13 +920,14 @@ public class QueryEntity implements Serializable {
             F.eq(tableName, entity.tableName) &&
             F.eq(_notNullFields, entity._notNullFields) &&
             F.eq(defaultFieldValues, entity.defaultFieldValues) &&
-            F.eq(decimalInfo, entity.decimalInfo);
+            F.eq(fieldsPrecision, entity.fieldsPrecision) &&
+            F.eq(fieldsScale, entity.fieldsScale);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
         return Objects.hash(keyType, valType, keyFieldName, valueFieldName, 
fields, keyFields, aliases, idxs,
-            tableName, _notNullFields, defaultFieldValues, decimalInfo);
+            tableName, _notNullFields, defaultFieldValues, fieldsPrecision, 
fieldsScale);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientChannel.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientChannel.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientChannel.java
index eb62c80..9e97b34 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientChannel.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientChannel.java
@@ -43,4 +43,9 @@ interface ClientChannel extends AutoCloseable {
      */
     public <T> T receive(ClientOperation op, long reqId, 
Function<BinaryInputStream, T> payloadReader)
         throws ClientConnectionException, ClientAuthorizationException;
+
+    /**
+     * @return Server version.
+     */
+    public ProtocolVersion serverVersion();
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java
index a50d78e..3114fc0 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java
@@ -55,7 +55,9 @@ import org.apache.ignite.internal.binary.BinarySchema;
 import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 import org.apache.ignite.internal.binary.streams.BinaryInputStream;
 import org.apache.ignite.internal.binary.streams.BinaryOutputStream;
-import org.apache.ignite.lang.IgniteBiTuple;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
+
+import static 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext.VER_1_2_0;
 
 /**
  * Shared serialization/deserialization utils.
@@ -232,7 +234,7 @@ final class ClientUtils {
     }
 
     /** Serialize configuration to stream. */
-    void cacheConfiguration(ClientCacheConfiguration cfg, BinaryOutputStream 
out) {
+    void cacheConfiguration(ClientCacheConfiguration cfg, BinaryOutputStream 
out, ClientListenerProtocolVersion ver) {
         try (BinaryRawWriterEx writer = new 
BinaryWriterExImpl(marsh.context(), out, null, null)) {
             int origPos = out.position();
 
@@ -310,8 +312,11 @@ final class ClientUtils {
                                 w.writeBoolean(qf.isKey());
                                 w.writeBoolean(qf.isNotNull());
                                 w.writeObject(qf.getDefaultValue());
-                                w.writeInt(qf.getPrecision());
-                                w.writeInt(qf.getScale());
+
+                                if (ver.compareTo(VER_1_2_0) >= 0) {
+                                    w.writeInt(qf.getPrecision());
+                                    w.writeInt(qf.getScale());
+                                }
                             }
                         );
                         ClientUtils.collection(
@@ -344,7 +349,8 @@ final class ClientUtils {
     }
 
     /** Deserialize configuration from stream. */
-    ClientCacheConfiguration cacheConfiguration(BinaryInputStream in) throws 
IOException {
+    ClientCacheConfiguration cacheConfiguration(BinaryInputStream in, 
ClientListenerProtocolVersion ver)
+        throws IOException {
         try (BinaryReaderExImpl reader = new 
BinaryReaderExImpl(marsh.context(), in, null, true)) {
             reader.readInt(); // Do not need length to read data. The protocol 
defines fixed configuration layout.
 
@@ -388,17 +394,27 @@ final class ClientUtils {
                             .setKeyFieldName(reader.readString())
                             .setValueFieldName(reader.readString());
 
+                        boolean isCliVer1_2 = ver.compareTo(VER_1_2_0) >= 0;
+
                         Collection<QueryField> qryFields = 
ClientUtils.collection(
                             in,
-                            unused2 -> new QueryField(
-                                reader.readString(),
-                                reader.readString(),
-                                reader.readBoolean(),
-                                reader.readBoolean(),
-                                reader.readObject(),
-                                reader.readInt(),
-                                reader.readInt()
-                            )
+                            unused2 -> {
+                                String name = reader.readString();
+                                String typeName = reader.readString();
+                                boolean isKey = reader.readBoolean();
+                                boolean isNotNull = reader.readBoolean(); 
+                                Object dfltVal = reader.readObject();
+                                int precision = isCliVer1_2 ? reader.readInt() 
: -1;
+                                int scale = isCliVer1_2 ? reader.readInt() : 
-1; 
+
+                                return new QueryField(name,
+                                    typeName,
+                                    isKey,
+                                    isNotNull,
+                                    dfltVal,
+                                    precision,
+                                    scale);
+                            }
                         );
 
                         return qryEntity
@@ -419,6 +435,14 @@ final class ClientUtils {
                                 .filter(f -> f.getDefaultValue() != null)
                                 .collect(Collectors.toMap(QueryField::getName, 
QueryField::getDefaultValue))
                             )
+                            .setFieldsPrecision(qryFields.stream()
+                                .filter(f -> f.getPrecision() != -1)
+                                .collect(Collectors.toMap(QueryField::getName, 
QueryField::getPrecision))
+                            )
+                            .setFieldsScale(qryFields.stream()
+                                .filter(f -> f.getScale() != -1)
+                                .collect(Collectors.toMap(QueryField::getName, 
QueryField::getScale))
+                            )
                             .setAliases(ClientUtils.collection(
                                 in,
                                 unused3 -> new 
SimpleEntry<>(reader.readString(), reader.readString())
@@ -513,16 +537,14 @@ final class ClientUtils {
             Set<String> keys = e.getKeyFields();
             Set<String> notNulls = e.getNotNullFields();
             Map<String, Object> dflts = e.getDefaultFieldValues();
-            Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo = 
e.getDecimalInfo();
+            Map<String, Integer> fldsPrecision = e.getFieldsPrecision();
+            Map<String, Integer> fldsScale = e.getFieldsScale();
 
             isKey = keys != null && keys.contains(name);
             isNotNull = notNulls != null && notNulls.contains(name);
             dfltVal = dflts == null ? null : dflts.get(name);
-
-            IgniteBiTuple<Integer, Integer> precisionAndScale = decimalInfo == 
null ? null : decimalInfo.get(name);
-
-            precision = precisionAndScale == null? -1 : 
precisionAndScale.get1();
-            scale = precisionAndScale == null? -1 : precisionAndScale.get2();
+            precision = fldsPrecision == null ? -1 : 
fldsPrecision.getOrDefault(name, -1);
+            scale = fldsScale == null? -1 : fldsScale.getOrDefault(name, -1);
         }
 
         /** Deserialization constructor. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ReliableChannel.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ReliableChannel.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ReliableChannel.java
index dac4320..537ce75 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ReliableChannel.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ReliableChannel.java
@@ -163,6 +163,13 @@ final class ReliableChannel implements AutoCloseable {
     }
 
     /**
+     * @return Server version.
+     */
+    public ProtocolVersion serverVersion() {
+        return ch.serverVersion();
+    }
+
+    /**
      * @return host:port_range address lines parsed as {@link 
InetSocketAddress}.
      */
     private static List<InetSocketAddress> parseAddresses(String[] addrs) 
throws ClientException {

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientCache.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientCache.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientCache.java
index bb659d0..92d9da8 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientCache.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientCache.java
@@ -40,6 +40,7 @@ import 
org.apache.ignite.internal.binary.streams.BinaryInputStream;
 import org.apache.ignite.internal.binary.streams.BinaryOutputStream;
 
 import static java.util.AbstractMap.SimpleEntry;
+import static 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext.CURRENT_VER;
 
 /**
  * Implementation of {@link ClientCache} over TCP protocol.
@@ -133,7 +134,7 @@ class TcpClientCache<K, V> implements ClientCache<K, V> {
             this::writeCacheInfo,
             res -> {
                 try {
-                    return serDes.cacheConfiguration(res);
+                    return serDes.cacheConfiguration(res, CURRENT_VER);
                 }
                 catch (IOException e) {
                     return null;

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientChannel.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientChannel.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientChannel.java
index 10dc865..6f83e94 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientChannel.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientChannel.java
@@ -69,6 +69,9 @@ import 
org.apache.ignite.internal.processors.platform.client.ClientStatus;
  * Implements {@link ClientChannel} over TCP.
  */
 class TcpClientChannel implements ClientChannel {
+    /** Protocol version: 1.2.0. */
+    private static final ProtocolVersion V1_2_0 = new 
ProtocolVersion((short)1, (short)2, (short)0);
+    
     /** Protocol version: 1.1.0. */
     private static final ProtocolVersion V1_1_0 = new 
ProtocolVersion((short)1, (short)1, (short)0);
 
@@ -76,10 +79,14 @@ class TcpClientChannel implements ClientChannel {
     private static final ProtocolVersion V1_0_0 = new 
ProtocolVersion((short)1, (short)0, (short)0);
 
     /** Supported protocol versions. */
-    private static final Collection<ProtocolVersion> supportedVers = 
Arrays.asList(V1_1_0, V1_0_0);
+    private static final Collection<ProtocolVersion> supportedVers = 
Arrays.asList(
+        V1_2_0, 
+        V1_1_0, 
+        V1_0_0
+    );
 
     /** Protocol version agreed with the server. */
-    private ProtocolVersion ver = V1_1_0;
+    private ProtocolVersion ver = V1_2_0;
 
     /** Channel. */
     private final Socket sock;
@@ -182,6 +189,11 @@ class TcpClientChannel implements ClientChannel {
         return payloadReader.apply(payload);
     }
 
+    /** {@inheritDoc} */
+    public ProtocolVersion serverVersion() {
+        return ver;
+    }
+
     /** Validate {@link ClientConfiguration}. */
     private static void validateConfiguration(ClientChannelConfiguration cfg) {
         String error = null;

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
index 7a0bc7a..c4af5ee 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
@@ -47,6 +47,7 @@ import org.apache.ignite.internal.binary.BinaryUtils;
 import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 import org.apache.ignite.internal.binary.streams.BinaryInputStream;
 import org.apache.ignite.internal.binary.streams.BinaryOutputStream;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.marshaller.MarshallerContext;
@@ -112,7 +113,8 @@ public class TcpIgniteClient implements IgniteClient {
         ClientCacheConfiguration cfg) throws ClientException {
         ensureCacheConfiguration(cfg);
 
-        ch.request(ClientOperation.CACHE_GET_OR_CREATE_WITH_CONFIGURATION, req 
-> serDes.cacheConfiguration(cfg, req));
+        ch.request(ClientOperation.CACHE_GET_OR_CREATE_WITH_CONFIGURATION, 
+            req -> serDes.cacheConfiguration(cfg, req, 
toClientVersion(ch.serverVersion())));
 
         return new TcpClientCache<>(cfg.getName(), ch, marsh);
     }
@@ -149,11 +151,22 @@ public class TcpIgniteClient implements IgniteClient {
     @Override public <K, V> ClientCache<K, V> 
createCache(ClientCacheConfiguration cfg) throws ClientException {
         ensureCacheConfiguration(cfg);
 
-        ch.request(ClientOperation.CACHE_CREATE_WITH_CONFIGURATION, req -> 
serDes.cacheConfiguration(cfg, req));
+        ch.request(ClientOperation.CACHE_CREATE_WITH_CONFIGURATION, 
+            req -> serDes.cacheConfiguration(cfg, req, 
toClientVersion(ch.serverVersion())));
 
         return new TcpClientCache<>(cfg.getName(), ch, marsh);
     }
 
+    /**
+     * Converts {@link ProtocolVersion} to {@link 
ClientListenerProtocolVersion}.
+     *
+     * @param srvVer Server protocol version.
+     * @return Client protocol version.
+     */
+    private ClientListenerProtocolVersion toClientVersion(ProtocolVersion 
srvVer) {
+        return ClientListenerProtocolVersion.create(srvVer.major(), 
srvVer.minor(), srvVer.patch());
+    }
+
     /** {@inheritDoc} */
     @Override public IgniteBinary binary() {
         return binary;

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
index 7adc301..6c128a4 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
@@ -846,7 +846,7 @@ public class JdbcThinDatabaseMetadata implements 
DatabaseMetaData {
         row.add(colMeta.columnName());          // 4. COLUMN_NAME
         row.add(colMeta.dataType());            // 5. DATA_TYPE
         row.add(colMeta.dataTypeName());        // 6. TYPE_NAME
-        row.add(colMeta.precision() == -1 ? null : colMeta.precision());       
          // 7. COLUMN_SIZE
+        row.add(colMeta.precision() == -1 ? null : colMeta.precision()); // 7. 
COLUMN_SIZE
         row.add((Integer)null);                 // 8. BUFFER_LENGTH
         row.add(colMeta.scale() == -1 ? null : colMeta.scale());           // 
9. DECIMAL_DIGITS
         row.add(10);                            // 10. NUM_PREC_RADIX

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/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 9dcf74d..6128d07 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
@@ -70,8 +70,11 @@ public class JdbcThinTcpIo {
     /** Version 2.5.0. */
     private static final ClientListenerProtocolVersion VER_2_5_0 = 
ClientListenerProtocolVersion.create(2, 5, 0);
 
+    /** Version 2.7.0. */
+    private static final ClientListenerProtocolVersion VER_2_7_0 = 
ClientListenerProtocolVersion.create(2, 7, 0);
+
     /** Current version. */
-    private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_5_0;
+    private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_7_0;
 
     /** Initial output stream capacity for handshake. */
     private static final int HANDSHAKE_MSG_SIZE = 13;
@@ -644,4 +647,4 @@ public class JdbcThinTcpIo {
 
         return srvProtocolVer.compareTo(VER_2_5_0) >= 0;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java
index e0ff9a4..2547e1b 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java
@@ -100,6 +100,12 @@ public final class IgniteQueryErrorCode {
     /** Cache not found. */
     public final static int CACHE_NOT_FOUND = 4006;
 
+    /** Attempt to INSERT, UPDATE or MERGE key that exceed maximum column 
length. */
+    public final static int TOO_LONG_KEY = 4007;
+
+    /** Attempt to INSERT, UPDATE or MERGE value that exceed maximum column 
length. */
+    public final static int TOO_LONG_VALUE = 4008;
+
     /** */
     private IgniteQueryErrorCode() {
         // No-op.
@@ -126,6 +132,8 @@ public final class IgniteQueryErrorCode {
     public static String codeToSqlState(int statusCode) {
         switch (statusCode) {
             case DUPLICATE_KEY:
+            case TOO_LONG_KEY:
+            case TOO_LONG_VALUE:
                 return SqlStateCode.CONSTRAINT_VIOLATION;
 
             case NULL_KEY:

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/QueryEntityTypeDescriptor.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/QueryEntityTypeDescriptor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/QueryEntityTypeDescriptor.java
index 9f8abc1..d8c0c39 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/QueryEntityTypeDescriptor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/QueryEntityTypeDescriptor.java
@@ -30,7 +30,6 @@ import 
org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
 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.apache.ignite.lang.IgniteBiTuple;
 
 /**
  * Descriptor of type.
@@ -55,8 +54,11 @@ public class QueryEntityTypeDescriptor {
     /** */
     private Set<String> notNullFields = new HashSet<>();
 
-    /** Decimal fields information. */
-    private Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo = new 
HashMap<>();
+    /** Precision information. */
+    private Map<String, Integer> fieldsPrecision = new HashMap<>();
+
+    /** Scale information. */
+    private Map<String, Integer> fieldsScale = new HashMap<>();
 
     /** */
     private QueryEntityIndexDescriptor fullTextIdx;
@@ -191,13 +193,23 @@ public class QueryEntityTypeDescriptor {
     }
 
     /**
-     * Adds decimal info.
+     * Adds fieldsPrecision info.
      *
      * @param field Field.
-     * @param info Decimal column info.
+     * @param precision Precision.
      */
-    public void addDecimalInfo(String field, IgniteBiTuple<Integer, Integer> 
info) {
-        decimalInfo.put(field, info);
+    public void addPrecision(String field, Integer precision) {
+        fieldsPrecision.put(field, precision);
+    }
+
+    /**
+     * Adds fieldsScale info.
+     *
+     * @param field Field.
+     * @param scale Scale.
+     */
+    public void addScale(String field, int scale) {
+        fieldsScale.put(field, scale);
     }
 
     /**
@@ -208,10 +220,17 @@ public class QueryEntityTypeDescriptor {
     }
 
     /**
-     * @return Decimal info for fields.
+     * @return Precision info for fields.
+     */
+    public Map<String, Integer> fieldsPrecision() {
+        return fieldsPrecision;
+    }
+
+    /**
+     * @return Scale info for fields.
      */
-    public Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo() {
-        return decimalInfo;
+    public Map<String, Integer> fieldsScale() {
+        return fieldsScale;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
index e74b25a..23f4d49 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
@@ -51,8 +51,11 @@ public class JdbcConnectionContext extends 
ClientListenerAbstractConnectionConte
     /** Version 2.5.0: adds precision and scale for columns feature. */
     static final ClientListenerProtocolVersion VER_2_5_0 = 
ClientListenerProtocolVersion.create(2, 5, 0);
 
+    /** Version 2.7.0: adds maximum length for columns feature.*/
+    static final ClientListenerProtocolVersion VER_2_7_0 = 
ClientListenerProtocolVersion.create(2, 7, 0);
+
     /** Current version. */
-    private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_5_0;
+    private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_7_0;
 
     /** Supported versions. */
     private static final Set<ClientListenerProtocolVersion> SUPPORTED_VERS = 
new HashSet<>();
@@ -77,6 +80,7 @@ public class JdbcConnectionContext extends 
ClientListenerAbstractConnectionConte
 
     static {
         SUPPORTED_VERS.add(CURRENT_VER);
+        SUPPORTED_VERS.add(VER_2_7_0);
         SUPPORTED_VERS.add(VER_2_5_0);
         SUPPORTED_VERS.add(VER_2_4_0);
         SUPPORTED_VERS.add(VER_2_3_0);

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/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 f8b1c40..8facd32 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
@@ -32,7 +32,6 @@ import java.util.PriorityQueue;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.LockSupport;
 import javax.cache.configuration.Factory;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cache.query.BulkLoadContextCursor;
@@ -72,7 +71,7 @@ import static 
org.apache.ignite.internal.processors.odbc.jdbc.JdbcBulkLoadBatchR
 import static 
org.apache.ignite.internal.processors.odbc.jdbc.JdbcBulkLoadBatchRequest.CMD_FINISHED_ERROR;
 import static 
org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext.VER_2_3_0;
 import static 
org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext.VER_2_4_0;
-import static 
org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext.VER_2_5_0;
+import static 
org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext.VER_2_7_0;
 import static 
org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.BATCH_EXEC;
 import static 
org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.BATCH_EXEC_ORDERED;
 import static 
org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.BULK_LOAD_BATCH;
@@ -822,7 +821,7 @@ public class JdbcRequestHandler implements 
ClientListenerRequestHandler {
 
                         JdbcColumnMeta columnMeta;
 
-                        if (protocolVer.compareTo(VER_2_5_0) >= 0) {
+                        if (protocolVer.compareTo(VER_2_7_0) >= 0) {
                             GridQueryProperty prop = table.property(colName);
 
                             columnMeta = new 
JdbcColumnMetaV4(table.schemaName(), table.tableName(),
@@ -853,7 +852,7 @@ public class JdbcRequestHandler implements 
ClientListenerRequestHandler {
 
             JdbcMetaColumnsResult res;
 
-            if (protocolVer.compareTo(VER_2_5_0) >= 0)
+            if (protocolVer.compareTo(VER_2_7_0) >= 0)
                 res = new JdbcMetaColumnsResultV4(meta);
             else if (protocolVer.compareTo(VER_2_4_0) >= 0)
                 res = new JdbcMetaColumnsResultV3(meta);

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/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 1d4f1a8..173ab39 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,6 +19,7 @@ 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.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
 
 /**
@@ -32,31 +33,51 @@ public class OdbcColumnMeta {
     private final String tableName;
 
     /** Column name. */
-    private final String columnName;
+    public final String columnName;
 
     /** Data type. */
     private final Class<?> dataType;
 
+    /** Precision. */
+    public final int precision;
+
+    /** Scale. */
+    public final int scale;
+
+    /** Client version. */
+    private final ClientListenerProtocolVersion ver;
+
     /**
      * @param schemaName Cache name.
      * @param tableName Table name.
      * @param columnName Column name.
      * @param dataType Data type.
+     * @param precision Precision.
+     * @param scale Scale.
+     * @param ver Client version.
      */
-    public OdbcColumnMeta(String schemaName, String tableName, String 
columnName, Class<?> dataType) {
+    public OdbcColumnMeta(String schemaName, String tableName, String 
columnName, Class<?> dataType,
+        int precision, int scale, ClientListenerProtocolVersion ver) {
         this.schemaName = OdbcUtils.addQuotationMarksIfNeeded(schemaName);
         this.tableName = tableName;
         this.columnName = columnName;
         this.dataType = dataType;
+        this.precision = precision;
+        this.scale = scale;
+        this.ver = ver;
     }
 
     /**
      * @param info Field metadata.
+     * @param ver Client version.
      */
-    public OdbcColumnMeta(GridQueryFieldMetadata info) {
+    public OdbcColumnMeta(GridQueryFieldMetadata info, 
ClientListenerProtocolVersion ver) {
         this.schemaName = 
OdbcUtils.addQuotationMarksIfNeeded(info.schemaName());
         this.tableName = info.typeName();
         this.columnName = info.fieldName();
+        this.precision = info.precision();
+        this.scale = info.scale();
+        this.ver = ver;
 
         Class<?> type;
 
@@ -77,6 +98,8 @@ public class OdbcColumnMeta {
         hash = 31 * hash + tableName.hashCode();
         hash = 31 * hash + columnName.hashCode();
         hash = 31 * hash + dataType.hashCode();
+        hash = 31 * hash + Integer.hashCode(precision);
+        hash = 31 * hash + Integer.hashCode(scale);
 
         return hash;
     }
@@ -87,7 +110,8 @@ public class OdbcColumnMeta {
             OdbcColumnMeta other = (OdbcColumnMeta) o;
 
             return this == other || schemaName.equals(other.schemaName) && 
tableName.equals(other.tableName) &&
-                columnName.equals(other.columnName) && 
dataType.equals(other.dataType);
+                columnName.equals(other.columnName) && 
dataType.equals(other.dataType) &&
+                precision == other.precision && scale == other.scale;
         }
 
         return false;
@@ -106,5 +130,10 @@ public class OdbcColumnMeta {
         byte typeId = BinaryUtils.typeByClass(dataType);
 
         writer.writeByte(typeId);
+
+        if (ver.compareTo(OdbcConnectionContext.VER_2_7_0) >= 0) {
+            writer.writeInt(precision);
+            writer.writeInt(scale);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java
index 8d8c745..253b183 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java
@@ -48,8 +48,11 @@ public class OdbcConnectionContext extends 
ClientListenerAbstractConnectionConte
     /** Version 2.5.0: added authentication. */
     public static final ClientListenerProtocolVersion VER_2_5_0 = 
ClientListenerProtocolVersion.create(2, 5, 0);
 
+    /** Version 2.7.0: added precision and scale. */
+    public static final ClientListenerProtocolVersion VER_2_7_0 = 
ClientListenerProtocolVersion.create(2, 7, 0);
+
     /** Current version. */
-    private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_5_0;
+    private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_7_0;
 
     /** Supported versions. */
     private static final Set<ClientListenerProtocolVersion> SUPPORTED_VERS = 
new HashSet<>();
@@ -68,6 +71,7 @@ public class OdbcConnectionContext extends 
ClientListenerAbstractConnectionConte
 
     static {
         SUPPORTED_VERS.add(CURRENT_VER);
+        SUPPORTED_VERS.add(VER_2_5_0);
         SUPPORTED_VERS.add(VER_2_3_0);
         SUPPORTED_VERS.add(VER_2_3_2);
         SUPPORTED_VERS.add(VER_2_1_5);
@@ -128,7 +132,7 @@ public class OdbcConnectionContext extends 
ClientListenerAbstractConnectionConte
         AuthorizationContext actx = authenticate(user, passwd);
 
         handler = new OdbcRequestHandler(ctx, busyLock, maxCursors, 
distributedJoins,
-                enforceJoinOrder, replicatedOnly, collocated, lazy, 
skipReducerOnUpdate, actx);
+                enforceJoinOrder, replicatedOnly, collocated, lazy, 
skipReducerOnUpdate, actx, ver);
 
         parser = new OdbcMessageParser(ctx, ver);
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryResults.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryResults.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryResults.java
index 23788c7..9781ffe 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryResults.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryResults.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.List;
 import org.apache.ignite.cache.query.FieldsQueryCursor;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 
 /**
  * ODBC result set
@@ -38,12 +39,17 @@ public class OdbcQueryResults {
     /** Current result set index. */
     private int currentResultSetIdx;
 
+    /** Client version. */
+    private ClientListenerProtocolVersion ver;
+
     /**
      * @param cursors Result set cursors.
+     * @param ver Client version.
      */
-    OdbcQueryResults(List<FieldsQueryCursor<List<?>>> cursors) {
+    OdbcQueryResults(List<FieldsQueryCursor<List<?>>> cursors, 
ClientListenerProtocolVersion ver) {
         this.cursors = cursors;
         this.currentResultSetIdx = 0;
+        this.ver = ver;
 
         rowsAffected = new ArrayList<>(cursors.size());
 
@@ -99,7 +105,7 @@ public class OdbcQueryResults {
         currentResultSet = null;
 
         if (currentResultSetIdx != cursors.size()) {
-            currentResultSet = new 
OdbcResultSet(cursors.get(currentResultSetIdx));
+            currentResultSet = new 
OdbcResultSet(cursors.get(currentResultSetIdx), ver);
             ++currentResultSetIdx;
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/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 bf0601b..b0f27d0 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
@@ -38,10 +38,12 @@ import 
org.apache.ignite.internal.binary.GridBinaryMarshaller;
 import 
org.apache.ignite.internal.processors.authentication.AuthorizationContext;
 import org.apache.ignite.internal.processors.cache.query.SqlFieldsQueryEx;
 import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.processors.odbc.ClientListenerRequest;
 import org.apache.ignite.internal.processors.odbc.ClientListenerRequestHandler;
 import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
 import org.apache.ignite.internal.processors.odbc.odbc.escape.OdbcEscapeUtils;
+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.util.GridSpinBusyLock;
@@ -101,6 +103,9 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
     /** Authentication context */
     private AuthorizationContext actx;
 
+    /** Client version. */
+    private ClientListenerProtocolVersion ver;
+
     /**
      * Constructor.
      * @param ctx Context.
@@ -113,10 +118,11 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
      * @param lazy Lazy flag.
      * @param skipReducerOnUpdate Skip reducer on update flag.
      * @param actx Authentication context.
+     * @param ver Client protocol version.
      */
     public OdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock 
busyLock, int maxCursors,
         boolean distributedJoins, boolean enforceJoinOrder, boolean 
replicatedOnly, boolean collocated, boolean lazy,
-        boolean skipReducerOnUpdate, AuthorizationContext actx) {
+        boolean skipReducerOnUpdate, AuthorizationContext actx, 
ClientListenerProtocolVersion ver) {
         this.ctx = ctx;
         this.busyLock = busyLock;
         this.maxCursors = maxCursors;
@@ -127,6 +133,7 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
         this.lazy = lazy;
         this.skipReducerOnUpdate = skipReducerOnUpdate;
         this.actx = actx;
+        this.ver = ver;
 
         log = ctx.log(getClass());
     }
@@ -261,7 +268,8 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
 
             List<FieldsQueryCursor<List<?>>> cursors = 
ctx.query().querySqlFields(qry, true, false);
 
-            OdbcQueryResults results = new OdbcQueryResults(cursors);
+            OdbcQueryResults results = new OdbcQueryResults(cursors, ver);
+
             Collection<OdbcColumnMeta> fieldsMeta;
 
             if (!results.hasUnfetchedRows()) {
@@ -272,6 +280,10 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
                 qryResults.put(qryId, results);
 
                 fieldsMeta = results.currentResultSet().fieldsMeta();
+
+                for (OdbcColumnMeta meta : fieldsMeta) {
+                    log.warning("Meta - " + meta.columnName + ", " + 
meta.precision + ", " + meta.scale);
+                }
             }
 
             OdbcQueryExecuteResult res = new OdbcQueryExecuteResult(qryId, 
fieldsMeta, results.rowsAffected());
@@ -436,8 +448,10 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
                         if (!matches(field.getKey(), req.columnPattern()))
                             continue;
 
+                        GridQueryProperty prop = 
table.property(field.getKey());
+
                         OdbcColumnMeta columnMeta = new 
OdbcColumnMeta(table.schemaName(), table.tableName(),
-                            field.getKey(), field.getValue());
+                            field.getKey(), field.getValue(), 
prop.precision(), prop.scale(), ver);
 
                         if (!meta.contains(columnMeta))
                             meta.add(columnMeta);

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcResultSet.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcResultSet.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcResultSet.java
index 66b0776..945b85d 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcResultSet.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcResultSet.java
@@ -23,6 +23,7 @@ import java.util.Iterator;
 import java.util.List;
 import org.apache.ignite.cache.query.FieldsQueryCursor;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
 
 /**
@@ -35,14 +36,19 @@ public class OdbcResultSet {
     /** Current iterator. */
     private Iterator iter;
 
+    /** Client version. */
+    private ClientListenerProtocolVersion ver;
+
     /**
      * Constructor.
      * @param cursor Result set cursor.
+     * @param ver Client version.
      */
-    OdbcResultSet(FieldsQueryCursor<List<?>> cursor) {
+    OdbcResultSet(FieldsQueryCursor<List<?>> cursor, 
ClientListenerProtocolVersion ver) {
         assert cursor instanceof QueryCursorImpl;
 
         this.cursor = (QueryCursorImpl<List<?>>)cursor;
+        this.ver = ver;
 
         if (this.cursor.isQuery())
             iter = this.cursor.iterator();
@@ -61,7 +67,7 @@ public class OdbcResultSet {
      * @return Fields metadata of the current result set.
      */
     public Collection<OdbcColumnMeta> fieldsMeta() {
-        return convertMetadata(cursor.fieldsMeta());
+        return convertMetadata(cursor.fieldsMeta(), ver);
     }
 
     /**
@@ -86,14 +92,16 @@ public class OdbcResultSet {
      * {@link OdbcColumnMeta}.
      *
      * @param meta Internal query field metadata.
+     * @param ver Client version.
      * @return Odbc query field metadata.
      */
-    private static Collection<OdbcColumnMeta> 
convertMetadata(Collection<GridQueryFieldMetadata> meta) {
+    private static Collection<OdbcColumnMeta> 
convertMetadata(Collection<GridQueryFieldMetadata> meta,
+        ClientListenerProtocolVersion ver) {
         List<OdbcColumnMeta> res = new ArrayList<>();
 
         if (meta != null) {
             for (GridQueryFieldMetadata info : meta)
-                res.add(new OdbcColumnMeta(info));
+                res.add(new OdbcColumnMeta(info, ver));
         }
 
         return res;

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformProcessorImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformProcessorImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformProcessorImpl.java
index 1c0878c..4e5803e 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformProcessorImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformProcessorImpl.java
@@ -71,6 +71,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import static 
org.apache.ignite.internal.processors.platform.PlatformAbstractTarget.FALSE;
 import static 
org.apache.ignite.internal.processors.platform.PlatformAbstractTarget.TRUE;
+import static 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext.CURRENT_VER;
 
 /**
  * GridGain platform processor.
@@ -478,7 +479,7 @@ public class PlatformProcessorImpl extends 
GridProcessorAdapter implements Platf
             }
 
             case OP_ADD_CACHE_CONFIGURATION:
-                CacheConfiguration cfg = 
PlatformConfigurationUtils.readCacheConfiguration(reader);
+                CacheConfiguration cfg = 
PlatformConfigurationUtils.readCacheConfiguration(reader, CURRENT_VER);
 
                 ctx.grid().addCacheConfiguration(cfg);
 
@@ -547,7 +548,7 @@ public class PlatformProcessorImpl extends 
GridProcessorAdapter implements Platf
             }
 
             case OP_CREATE_CACHE_FROM_CONFIG: {
-                CacheConfiguration cfg = 
PlatformConfigurationUtils.readCacheConfiguration(reader);
+                CacheConfiguration cfg = 
PlatformConfigurationUtils.readCacheConfiguration(reader, CURRENT_VER);
 
                 IgniteCacheProxy cache = reader.readBoolean()
                         ? (IgniteCacheProxy)ctx.grid().createCache(cfg, 
PlatformConfigurationUtils.readNearConfiguration(reader))
@@ -557,7 +558,7 @@ public class PlatformProcessorImpl extends 
GridProcessorAdapter implements Platf
             }
 
             case OP_GET_OR_CREATE_CACHE_FROM_CONFIG: {
-                CacheConfiguration cfg = 
PlatformConfigurationUtils.readCacheConfiguration(reader);
+                CacheConfiguration cfg = 
PlatformConfigurationUtils.readCacheConfiguration(reader, CURRENT_VER);
 
                 IgniteCacheProxy cache = reader.readBoolean()
                         ? (IgniteCacheProxy)ctx.grid().getOrCreateCache(cfg,
@@ -672,7 +673,7 @@ public class PlatformProcessorImpl extends 
GridProcessorAdapter implements Platf
     @Override public void processOutStream(int type, BinaryRawWriterEx writer) 
throws IgniteCheckedException {
         switch (type) {
             case OP_GET_IGNITE_CONFIGURATION: {
-                PlatformConfigurationUtils.writeIgniteConfiguration(writer, 
ignite().configuration());
+                PlatformConfigurationUtils.writeIgniteConfiguration(writer, 
ignite().configuration(), CURRENT_VER);
 
                 return;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/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 8f3f2ef..7b91575 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
@@ -76,6 +76,8 @@ import 
org.apache.ignite.transactions.TransactionDeadlockException;
 import org.apache.ignite.transactions.TransactionTimeoutException;
 import org.jetbrains.annotations.Nullable;
 
+import static 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext.CURRENT_VER;
+
 /**
  * Native cache wrapper implementation.
  */
@@ -980,7 +982,7 @@ public class PlatformCache extends PlatformAbstractTarget {
                 CacheConfiguration ccfg = ((IgniteCache<Object, Object>)cache).
                         getConfiguration(CacheConfiguration.class);
 
-                PlatformConfigurationUtils.writeCacheConfiguration(writer, 
ccfg);
+                PlatformConfigurationUtils.writeCacheConfiguration(writer, 
ccfg, CURRENT_VER);
 
                 break;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientConnectionContext.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientConnectionContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientConnectionContext.java
index c957901..ffe38ca 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientConnectionContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientConnectionContext.java
@@ -44,11 +44,18 @@ public class ClientConnectionContext extends 
ClientListenerAbstractConnectionCon
     /** Version 1.2.0. */
     public static final ClientListenerProtocolVersion VER_1_2_0 = 
ClientListenerProtocolVersion.create(1, 2, 0);
 
+    /** Version 1.2.0. */
+    public static final ClientListenerProtocolVersion CURRENT_VER = VER_1_2_0;
+
     /** Supported versions. */
-    private static final Collection<ClientListenerProtocolVersion> 
SUPPORTED_VERS = Arrays.asList(VER_1_2_0, VER_1_1_0, VER_1_0_0);
+    private static final Collection<ClientListenerProtocolVersion> 
SUPPORTED_VERS = Arrays.asList(
+        VER_1_2_0,
+        VER_1_1_0,
+        VER_1_0_0
+    );
 
     /** Message parser. */
-    private final ClientMessageParser parser;
+    private ClientMessageParser parser;
 
     /** Request handler. */
     private ClientRequestHandler handler;
@@ -72,8 +79,6 @@ public class ClientConnectionContext extends 
ClientListenerAbstractConnectionCon
     public ClientConnectionContext(GridKernalContext ctx, long connId, int 
maxCursors) {
         super(ctx, connId);
 
-        parser = new ClientMessageParser(ctx);
-
         this.maxCursors = maxCursors;
     }
 
@@ -93,7 +98,7 @@ public class ClientConnectionContext extends 
ClientListenerAbstractConnectionCon
 
     /** {@inheritDoc} */
     @Override public ClientListenerProtocolVersion currentVersion() {
-        return VER_1_1_0;
+        return CURRENT_VER;
     }
 
     /** {@inheritDoc} */
@@ -121,6 +126,8 @@ public class ClientConnectionContext extends 
ClientListenerAbstractConnectionCon
         AuthorizationContext authCtx = authenticate(user, pwd);
 
         handler = new ClientRequestHandler(this, authCtx);
+
+        parser = new ClientMessageParser(kernalContext(), ver);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
index c887b3c..c65e64a 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
@@ -27,6 +27,7 @@ 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.ClientListenerMessageParser;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.processors.odbc.ClientListenerRequest;
 import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
 import 
org.apache.ignite.internal.processors.platform.client.binary.ClientBinaryTypeGetRequest;
@@ -204,17 +205,24 @@ public class ClientMessageParser implements 
ClientListenerMessageParser {
 
     /** Marshaller. */
     private final GridBinaryMarshaller marsh;
+    
+    /** Client version */
+    private final ClientListenerProtocolVersion ver;
 
     /**
      * Ctor.
      *
      * @param ctx Kernal context.
+     * @param ver Client version.
      */
-    ClientMessageParser(GridKernalContext ctx) {
+    ClientMessageParser(GridKernalContext ctx, ClientListenerProtocolVersion 
ver) {
         assert ctx != null;
+        assert ver != null;
 
         CacheObjectBinaryProcessorImpl cacheObjProc = 
(CacheObjectBinaryProcessorImpl)ctx.cacheObjects();
         marsh = cacheObjProc.marshaller();
+        
+        this.ver = ver;
     }
 
     /** {@inheritDoc} */
@@ -343,13 +351,13 @@ public class ClientMessageParser implements 
ClientListenerMessageParser {
                 return new ClientCacheGetNamesRequest(reader);
 
             case OP_CACHE_GET_CONFIGURATION:
-                return new ClientCacheGetConfigurationRequest(reader);
+                return new ClientCacheGetConfigurationRequest(reader, ver);
 
             case OP_CACHE_CREATE_WITH_CONFIGURATION:
-                return new ClientCacheCreateWithConfigurationRequest(reader);
+                return new ClientCacheCreateWithConfigurationRequest(reader, 
ver);
 
             case OP_CACHE_GET_OR_CREATE_WITH_CONFIGURATION:
-                return new 
ClientCacheGetOrCreateWithConfigurationRequest(reader);
+                return new 
ClientCacheGetOrCreateWithConfigurationRequest(reader, ver);
 
             case OP_QUERY_SQL:
                 return new ClientCacheSqlQueryRequest(reader);

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
index 839720b..331b6d8 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
@@ -30,6 +30,7 @@ import org.apache.ignite.internal.binary.BinaryRawWriterEx;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 
 import static 
org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils.readQueryEntity;
 import static 
org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils.writeEnumInt;
@@ -134,8 +135,9 @@ public class ClientCacheConfigurationSerializer {
      * Writes the cache configuration.
      * @param writer Writer.
      * @param cfg Configuration.
+     * @param ver Client version.
      */
-    static void write(BinaryRawWriterEx writer, CacheConfiguration cfg) {
+    static void write(BinaryRawWriterEx writer, CacheConfiguration cfg, 
ClientListenerProtocolVersion ver) {
         assert writer != null;
         assert cfg != null;
 
@@ -191,7 +193,7 @@ public class ClientCacheConfigurationSerializer {
             writer.writeInt(qryEntities.size());
 
             for (QueryEntity e : qryEntities)
-                writeQueryEntity(writer, e);
+                writeQueryEntity(writer, e, ver);
         } else
             writer.writeInt(0);
 
@@ -203,9 +205,10 @@ public class ClientCacheConfigurationSerializer {
      * Reads the cache configuration.
      *
      * @param reader Reader.
+     * @param ver Client version.
      * @return Configuration.
      */
-    static CacheConfiguration read(BinaryRawReader reader) {
+    static CacheConfiguration read(BinaryRawReader reader, 
ClientListenerProtocolVersion ver) {
         reader.readInt();  // Skip length.
 
         short propCnt = reader.readShort();
@@ -349,7 +352,7 @@ public class ClientCacheConfigurationSerializer {
                         Collection<QueryEntity> entities = new 
ArrayList<>(qryEntCnt);
 
                         for (int j = 0; j < qryEntCnt; j++)
-                            entities.add(readQueryEntity(reader));
+                            entities.add(readQueryEntity(reader, ver));
 
                         cfg.setQueryEntities(entities);
                     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
index 65f9784..9f1d63fc 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
@@ -20,6 +20,7 @@ package 
org.apache.ignite.internal.processors.platform.client.cache;
 import org.apache.ignite.binary.BinaryRawReader;
 import org.apache.ignite.cache.CacheExistsException;
 import org.apache.ignite.configuration.CacheConfiguration;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
 import org.apache.ignite.internal.processors.platform.client.ClientRequest;
 import org.apache.ignite.internal.processors.platform.client.ClientResponse;
@@ -39,11 +40,12 @@ public class ClientCacheCreateWithConfigurationRequest 
extends ClientRequest {
      * Constructor.
      *
      * @param reader Reader.
+     * @param ver Client version.
      */
-    public ClientCacheCreateWithConfigurationRequest(BinaryRawReader reader) {
+    public ClientCacheCreateWithConfigurationRequest(BinaryRawReader reader, 
ClientListenerProtocolVersion ver) {
         super(reader);
 
-        cacheCfg = ClientCacheConfigurationSerializer.read(reader);
+        cacheCfg = ClientCacheConfigurationSerializer.read(reader, ver);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
index 3632095..f2c83fc 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
@@ -20,6 +20,7 @@ package 
org.apache.ignite.internal.processors.platform.client.cache;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.binary.BinaryRawReader;
 import org.apache.ignite.configuration.CacheConfiguration;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
 import org.apache.ignite.internal.processors.platform.client.ClientResponse;
 
@@ -27,13 +28,19 @@ import 
org.apache.ignite.internal.processors.platform.client.ClientResponse;
  * Cache configuration request.
  */
 public class ClientCacheGetConfigurationRequest extends ClientCacheRequest {
+    /** Client version. */
+    private final ClientListenerProtocolVersion ver;
+    
     /**
      * Constructor.
      *
      * @param reader Reader.
+     * @param ver Client version.
      */
-    public ClientCacheGetConfigurationRequest(BinaryRawReader reader) {
+    public ClientCacheGetConfigurationRequest(BinaryRawReader reader, 
ClientListenerProtocolVersion ver) {
         super(reader);
+        
+        this.ver = ver;
     }
 
     /** {@inheritDoc} */
@@ -42,6 +49,6 @@ public class ClientCacheGetConfigurationRequest extends 
ClientCacheRequest {
         CacheConfiguration cfg = ((IgniteCache<Object, Object>) rawCache(ctx))
                 .getConfiguration(CacheConfiguration.class);
 
-        return new ClientCacheGetConfigurationResponse(requestId(), cfg);
+        return new ClientCacheGetConfigurationResponse(requestId(), cfg, ver);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
index 2033dfe..f7d6896 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
@@ -19,6 +19,7 @@ package 
org.apache.ignite.internal.processors.platform.client.cache;
 
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.processors.platform.client.ClientResponse;
 
 /**
@@ -28,24 +29,30 @@ public class ClientCacheGetConfigurationResponse extends 
ClientResponse {
     /** Cache configuration. */
     private final CacheConfiguration cfg;
 
+    /** Client version. */
+    private final ClientListenerProtocolVersion ver;
+    
     /**
      * Constructor.
      *
      * @param reqId Request id.
      * @param cfg Cache configuration.
+     * @param ver Client version.
      */
-    ClientCacheGetConfigurationResponse(long reqId, CacheConfiguration cfg) {
+    ClientCacheGetConfigurationResponse(long reqId, CacheConfiguration cfg, 
ClientListenerProtocolVersion ver) {
         super(reqId);
 
         assert cfg != null;
+        assert ver != null;
 
         this.cfg = cfg;
+        this.ver = ver;
     }
 
     /** {@inheritDoc} */
     @Override public void encode(BinaryRawWriterEx writer) {
         super.encode(writer);
 
-        ClientCacheConfigurationSerializer.write(writer, cfg);
+        ClientCacheConfigurationSerializer.write(writer, cfg, ver);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
index 48569b4..b005fb2 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
@@ -20,6 +20,7 @@ package 
org.apache.ignite.internal.processors.platform.client.cache;
 import org.apache.ignite.binary.BinaryRawReader;
 import org.apache.ignite.cache.CacheExistsException;
 import org.apache.ignite.configuration.CacheConfiguration;
+import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
 import org.apache.ignite.internal.processors.platform.client.ClientRequest;
 import org.apache.ignite.internal.processors.platform.client.ClientResponse;
@@ -39,11 +40,12 @@ public class ClientCacheGetOrCreateWithConfigurationRequest 
extends ClientReques
      * Constructor.
      *
      * @param reader Reader.
+     * @param ver Client version.
      */
-    public ClientCacheGetOrCreateWithConfigurationRequest(BinaryRawReader 
reader) {
+    public ClientCacheGetOrCreateWithConfigurationRequest(BinaryRawReader 
reader, ClientListenerProtocolVersion ver) {
         super(reader);
 
-        cacheCfg = ClientCacheConfigurationSerializer.read(reader);
+        cacheCfg = ClientCacheConfigurationSerializer.read(reader, ver);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/baab0a6d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
index 9ee2f5e..7c50062 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
@@ -45,6 +45,8 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import static 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext.CURRENT_VER;
+
 /**
  * Closure to apply dot net configuration.
  */
@@ -196,7 +198,7 @@ public class PlatformDotNetConfigurationClosure extends 
PlatformAbstractConfigur
     private void processPrepareResult(BinaryReaderExImpl in) {
         assert cfg != null;
 
-        PlatformConfigurationUtils.readIgniteConfiguration(in, cfg);
+        PlatformConfigurationUtils.readIgniteConfiguration(in, cfg, 
CURRENT_VER);
 
         // Process beans
         List<PlatformDotNetLifecycleBean> beans = beans(cfg);

Reply via email to