You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ni...@apache.org on 2018/04/13 08:57:35 UTC

ignite git commit: IGNITE-7691: Provide info about DECIMAL column precision and scale. - Fixes #3691.

Repository: ignite
Updated Branches:
  refs/heads/master 08a700db3 -> 6df5f99be


IGNITE-7691: Provide info about DECIMAL column precision and scale. - Fixes #3691.

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


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

Branch: refs/heads/master
Commit: 6df5f99bec46d9b0eabd2e623f0d26b32d031e4c
Parents: 08a700d
Author: Nikolay Izhikov <ni...@apache.org>
Authored: Fri Apr 13 11:53:50 2018 +0300
Committer: Nikolay Izhikov <ni...@apache.org>
Committed: Fri Apr 13 11:53:50 2018 +0300

----------------------------------------------------------------------
 .../jdbc/thin/JdbcThinMetadataSelfTest.java     |  22 +-
 .../org/apache/ignite/cache/QueryEntity.java    |  41 ++-
 .../cache/query/annotations/QuerySqlField.java  |  16 +-
 .../internal/client/thin/ClientUtils.java       |  38 ++-
 .../jdbc/thin/JdbcThinDatabaseMetadata.java     |   6 +-
 .../cache/query/QueryEntityTypeDescriptor.java  |  21 ++
 .../processors/odbc/jdbc/JdbcColumnMeta.java    |  14 +
 .../processors/odbc/jdbc/JdbcColumnMetaV4.java  |  90 +++++++
 .../odbc/jdbc/JdbcConnectionContext.java        |   4 +-
 .../odbc/jdbc/JdbcMetaColumnsResultV4.java      |  50 ++++
 .../odbc/jdbc/JdbcRequestHandler.java           |  14 +-
 .../processors/odbc/jdbc/JdbcResult.java        |   8 +
 .../utils/PlatformConfigurationUtils.java       |  20 ++
 .../processors/query/GridQueryProcessor.java    |   2 +-
 .../processors/query/GridQueryProperty.java     |  14 +
 .../internal/processors/query/QueryField.java   |  26 +-
 .../internal/processors/query/QueryUtils.java   |  28 +-
 .../query/property/QueryBinaryProperty.java     |  23 +-
 .../query/property/QueryClassProperty.java      |  10 +
 .../query/h2/ddl/DdlStatementsProcessor.java    |  13 +-
 .../processors/query/h2/sql/GridSqlColumn.java  |  17 +-
 .../cache/index/IgniteDecimalSelfTest.java      | 265 +++++++++++++++++++
 .../h2/GridIndexingSpiAbstractSelfTest.java     |  12 +-
 .../IgniteCacheQuerySelfTestSuite.java          |   2 +
 .../QueryEntityConfigurationParityTest.cs       |   5 +-
 .../Cache/CacheConfigurationTest.cs             |   2 +
 .../Cache/Configuration/QueryEntity.cs          |   4 +-
 .../Cache/Configuration/QueryField.cs           |  16 +-
 .../Configuration/QuerySqlFieldAttribute.cs     |  10 +
 .../IgniteConfigurationSection.xsd              |  10 +
 30 files changed, 773 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 4a34be6..cc6790a 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,6 +18,7 @@
 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;
@@ -143,6 +144,7 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
             stmt.execute("CREATE TABLE \"Quoted\" (\"Id\" INT primary key, \"Name\" VARCHAR(50)) WITH WRAP_KEY");
             stmt.execute("CREATE INDEX \"MyTestIndex quoted\" on \"Quoted\" (\"Id\" DESC)");
             stmt.execute("CREATE INDEX IDX ON TEST (ID ASC)");
+            stmt.execute("CREATE TABLE TEST_DECIMAL_COLUMN (ID INT primary key, DEC_COL DECIMAL(8, 3))");
         }
     }
 
@@ -244,7 +246,8 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
                 "org.ORGANIZATION",
                 "pers.PERSON",
                 "PUBLIC.TEST",
-                "PUBLIC.Quoted"));
+                "PUBLIC.Quoted",
+                "PUBLIC.TEST_DECIMAL_COLUMN"));
 
             Set<String> actualTbls = new HashSet<>(expectedTbls.size());
 
@@ -390,15 +393,25 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
                 "PUBLIC.TEST.VAL.null",
                 "PUBLIC.TEST.AGE.21",
                 "PUBLIC.Quoted.Id.null",
-                "PUBLIC.Quoted.Name.null"));
+                "PUBLIC.Quoted.Name.null",
+                "PUBLIC.TEST_DECIMAL_COLUMN.ID.null",
+                "PUBLIC.TEST_DECIMAL_COLUMN.DEC_COL.null.8.3"
+            ));
 
             Set<String> actualCols = new HashSet<>(expectedCols.size());
 
             while(rs.next()) {
+                int precision = rs.getInt("COLUMN_SIZE");
+
+                int scale = rs.getInt("DECIMAL_DIGITS");
+
                 actualCols.add(rs.getString("TABLE_SCHEM") + '.'
                     + rs.getString("TABLE_NAME") + "."
                     + rs.getString("COLUMN_NAME") + "."
-                    + rs.getString("COLUMN_DEF"));
+                    + rs.getString("COLUMN_DEF")
+                    + (precision == 0 ? "" : ("." + precision))
+                    + (scale == 0 ? "" : ("." + scale))
+                );
             }
 
             assert expectedCols.equals(actualCols) : "expectedCols=" + expectedCols +
@@ -532,7 +545,8 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
                 "pers.PERSON.PK_pers_PERSON._KEY",
                 "PUBLIC.TEST.PK_PUBLIC_TEST.ID",
                 "PUBLIC.TEST.PK_PUBLIC_TEST.NAME",
-                "PUBLIC.Quoted.PK_PUBLIC_Quoted.Id"));
+                "PUBLIC.Quoted.PK_PUBLIC_Quoted.Id",
+                "PUBLIC.TEST_DECIMAL_COLUMN.ID._KEY"));
 
             Set<String> actualPks = new HashSet<>(expectedPks.size());
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 0065bae..aff3461 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
@@ -19,6 +19,7 @@ package org.apache.ignite.cache;
 
 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;
@@ -42,8 +43,11 @@ 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.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.
@@ -89,6 +93,9 @@ 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<>();
+
     /**
      * Creates an empty query entity.
      */
@@ -120,6 +127,8 @@ 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<>();
     }
 
     /**
@@ -391,6 +400,27 @@ public class QueryEntity implements Serializable {
     }
 
     /**
+     * Gets set of field name to precision and scale.
+     *
+     * @return Set of names of fields that must have non-null values.
+     */
+    public Map<String, IgniteBiTuple<Integer, Integer>> getDecimalInfo() {
+        return unmodifiableMap(decimalInfo);
+    }
+
+    /**
+     * Sets decimal fields info.
+     *
+     * @param decimalInfo Set of name to precision and scale for decimal fields.
+     * @return {@code this} for chaining.
+     */
+    public QueryEntity setDecimalInfo(Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo) {
+        this.decimalInfo = decimalInfo;
+
+        return this;
+    }
+
+    /**
      * Gets fields default values.
      *
      * @return Field's name to default value map.
@@ -504,6 +534,9 @@ public class QueryEntity implements Serializable {
         if (!F.isEmpty(desc.notNullFields()))
             entity.setNotNullFields(desc.notNullFields());
 
+        if (!F.isEmpty(desc.decimalInfo()))
+            entity.setDecimalInfo(desc.decimalInfo());
+
         return entity;
     }
 
@@ -629,6 +662,9 @@ 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 ((!F.isEmpty(sqlAnn.groups()) || !F.isEmpty(sqlAnn.orderedGroups()))
                 && sqlAnn.inlineSize() != QueryIndex.DFLT_INLINE_SIZE) {
                 throw new CacheException("Inline size cannot be set on a field with group index [" +
@@ -670,13 +706,14 @@ public class QueryEntity implements Serializable {
             F.eqNotOrdered(idxs, entity.idxs) &&
             F.eq(tableName, entity.tableName) &&
             F.eq(_notNullFields, entity._notNullFields) &&
-            F.eq(defaultFieldValues, entity.defaultFieldValues);
+            F.eq(defaultFieldValues, entity.defaultFieldValues) &&
+            F.eq(decimalInfo, entity.decimalInfo);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
         return Objects.hash(keyType, valType, keyFieldName, valueFieldName, fields, keyFields, aliases, idxs,
-            tableName, _notNullFields, defaultFieldValues);
+            tableName, _notNullFields, defaultFieldValues, decimalInfo);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/core/src/main/java/org/apache/ignite/cache/query/annotations/QuerySqlField.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/query/annotations/QuerySqlField.java b/modules/core/src/main/java/org/apache/ignite/cache/query/annotations/QuerySqlField.java
index 0343474..35b7575 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/query/annotations/QuerySqlField.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/query/annotations/QuerySqlField.java
@@ -64,6 +64,20 @@ public @interface QuerySqlField {
     boolean notNull() default false;
 
     /**
+     * Specifies precision for a decimal field.
+     *
+     * @return precision for a decimal field.
+     */
+    int precision() default -1;
+
+    /**
+     * Specifies scale for a decimal field.
+     *
+     * @return scale for a decimal field.
+     */
+    int scale() default -1;
+
+    /**
      * Array of index groups this field belongs to. Groups are used for compound indexes,
      * whenever index should be created on more than one field. All fields within the same
      * group will belong to the same index.
@@ -155,4 +169,4 @@ public @interface QuerySqlField {
          */
         boolean descending() default false;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 e21cc4e..a50d78e 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,6 +55,7 @@ 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;
 
 /**
  * Shared serialization/deserialization utils.
@@ -309,6 +310,8 @@ final class ClientUtils {
                                 w.writeBoolean(qf.isKey());
                                 w.writeBoolean(qf.isNotNull());
                                 w.writeObject(qf.getDefaultValue());
+                                w.writeInt(qf.getPrecision());
+                                w.writeInt(qf.getScale());
                             }
                         );
                         ClientUtils.collection(
@@ -392,7 +395,9 @@ final class ClientUtils {
                                 reader.readString(),
                                 reader.readBoolean(),
                                 reader.readBoolean(),
-                                reader.readObject()
+                                reader.readObject(),
+                                reader.readInt(),
+                                reader.readInt()
                             )
                         );
 
@@ -494,6 +499,12 @@ final class ClientUtils {
         /** Default value. */
         private final Object dfltVal;
 
+        /** Precision. */
+        private final int precision;
+
+        /** Scale. */
+        private final int scale;
+
         /** Serialization constructor. */
         QueryField(QueryEntity e, Map.Entry<String, String> nameAndTypeName) {
             name = nameAndTypeName.getKey();
@@ -502,19 +513,28 @@ 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();
 
             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();
         }
 
         /** Deserialization constructor. */
-        public QueryField(String name, String typeName, boolean isKey, boolean isNotNull, Object dfltVal) {
+        public QueryField(String name, String typeName, boolean isKey, boolean isNotNull, Object dfltVal,
+            int precision, int scale) {
             this.name = name;
             this.typeName = typeName;
             this.isKey = isKey;
             this.isNotNull = isNotNull;
             this.dfltVal = dfltVal;
+            this.precision = precision;
+            this.scale = scale;
         }
 
         /**
@@ -551,6 +571,20 @@ final class ClientUtils {
         Object getDefaultValue() {
             return dfltVal;
         }
+
+        /**
+         * @return Precision.
+         */
+        public int getPrecision() {
+            return precision;
+        }
+
+        /**
+         * @return Scale.
+         */
+        public int getScale() {
+            return scale;
+        }
     }
 
     /** Thin client protocol cache configuration item codes. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 dd8b733..7adc301 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,9 +846,9 @@ 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((Integer)null);                 // 7. COLUMN_SIZE
+        row.add(colMeta.precision() == -1 ? null : colMeta.precision());                 // 7. COLUMN_SIZE
         row.add((Integer)null);                 // 8. BUFFER_LENGTH
-        row.add((Integer)null);                 // 9. DECIMAL_DIGITS
+        row.add(colMeta.scale() == -1 ? null : colMeta.scale());           // 9. DECIMAL_DIGITS
         row.add(10);                            // 10. NUM_PREC_RADIX
         row.add(colMeta.isNullable() ? columnNullable : columnNoNulls);  // 11. NULLABLE
         row.add((String)null);                  // 12. REMARKS
@@ -1542,4 +1542,4 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     @Override public boolean generatedKeyAlwaysReturned() throws SQLException {
         return false;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 fd0ef2b..9f8abc1 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,6 +30,7 @@ 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.
@@ -54,6 +55,9 @@ public class QueryEntityTypeDescriptor {
     /** */
     private Set<String> notNullFields = new HashSet<>();
 
+    /** Decimal fields information. */
+    private Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo = new HashMap<>();
+
     /** */
     private QueryEntityIndexDescriptor fullTextIdx;
 
@@ -187,6 +191,16 @@ public class QueryEntityTypeDescriptor {
     }
 
     /**
+     * Adds decimal info.
+     *
+     * @param field Field.
+     * @param info Decimal column info.
+     */
+    public void addDecimalInfo(String field, IgniteBiTuple<Integer, Integer> info) {
+        decimalInfo.put(field, info);
+    }
+
+    /**
      * @return notNull fields.
      */
     public Set<String> notNullFields() {
@@ -194,6 +208,13 @@ public class QueryEntityTypeDescriptor {
     }
 
     /**
+     * @return Decimal info for fields.
+     */
+    public Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo() {
+        return decimalInfo;
+    }
+
+    /**
      * @return Class properties.
      */
     public Map<String, QueryEntityClassProperty> properties() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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
index c0ac322..5b6304d 100644
--- 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
@@ -135,6 +135,20 @@ public class JdbcColumnMeta implements JdbcRawBinarylizable {
     }
 
     /**
+     * @return Column's precision.
+     */
+    public int precision() {
+        return -1;
+    }
+
+    /**
+     * @return Column's scale.
+     */
+    public int scale() {
+        return -1;
+    }
+
+    /**
      * Return 'nullable' flag in compatibility mode (according with column name and column type).
      *
      * @return {@code true} in case the column allows null values. Otherwise returns {@code false}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMetaV4.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMetaV4.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMetaV4.java
new file mode 100644
index 0000000..ec76983
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMetaV4.java
@@ -0,0 +1,90 @@
+/*
+ * 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.util.typedef.internal.S;
+
+/**
+ * JDBC column metadata V4.
+ */
+public class JdbcColumnMetaV4 extends JdbcColumnMetaV3 {
+    /** Decimal field precision. */
+    private int precision;
+
+    /** Decimal field scale. */
+    private int scale;
+
+    /**
+     * Default constructor is used for serialization.
+     */
+    JdbcColumnMetaV4() {
+        // No-op.
+    }
+
+    /**
+     * @param schemaName Schema.
+     * @param tblName Table.
+     * @param colName Column.
+     * @param cls Type.
+     * @param nullable Allow nulls.
+     * @param dfltVal Default value.
+     * @param precision Decimal column precision.
+     * @param scale Decimal column scale.
+     */
+    public JdbcColumnMetaV4(String schemaName, String tblName, String colName, Class<?> cls, boolean nullable,
+        Object dfltVal, int precision, int scale) {
+        super(schemaName, tblName, colName, cls, nullable, dfltVal);
+
+        this.precision = precision;
+
+        this.scale = scale;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int precision() {
+        return precision;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int scale() {
+        return scale;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) {
+        super.writeBinary(writer);
+
+        writer.writeInt(precision);
+        writer.writeInt(scale);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) {
+        super.readBinary(reader);
+
+        precision = reader.readInt();
+        scale = reader.readInt();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcColumnMetaV4.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 2fe3b9c..ed37e0b 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
@@ -47,8 +47,8 @@ public class JdbcConnectionContext implements ClientListenerConnectionContext {
     /** Version 2.4.0: adds default values for columns feature. */
     static final ClientListenerProtocolVersion VER_2_4_0 = ClientListenerProtocolVersion.create(2, 4, 0);
 
-    /** Version 2.5.0. */
-    private static final ClientListenerProtocolVersion VER_2_5_0 = ClientListenerProtocolVersion.create(2, 5, 0);
+    /** Version 2.5.0: adds precision and scale for columns feature. */
+    static final ClientListenerProtocolVersion VER_2_5_0 = ClientListenerProtocolVersion.create(2, 5, 0);
 
     /** Current version. */
     private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_5_0;

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResultV4.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResultV4.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResultV4.java
new file mode 100644
index 0000000..9c8e2b7
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMetaColumnsResultV4.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.internal.processors.odbc.jdbc;
+
+import java.util.Collection;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * JDBC columns metadata result.
+ */
+public class JdbcMetaColumnsResultV4 extends JdbcMetaColumnsResult {
+    /**
+     * Default constructor is used for deserialization.
+     */
+    JdbcMetaColumnsResultV4() {
+        super(META_COLUMNS_V4);
+    }
+
+    /**
+     * @param meta Columns metadata.
+     */
+    JdbcMetaColumnsResultV4(Collection<JdbcColumnMeta> meta) {
+        super(META_COLUMNS_V4, meta);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected JdbcColumnMeta createMetaColumn() {
+        return new JdbcColumnMetaV4();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcMetaColumnsResultV4.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 cf0e98b..b9c9cdd 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
@@ -67,6 +67,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.JdbcRequest.BATCH_EXEC;
 import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.BULK_LOAD_BATCH;
 import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.META_COLUMNS;
@@ -744,7 +745,14 @@ public class JdbcRequestHandler implements ClientListenerRequestHandler {
 
                         JdbcColumnMeta columnMeta;
 
-                        if (protocolVer.compareTo(VER_2_4_0) >= 0) {
+                        if (protocolVer.compareTo(VER_2_5_0) >= 0) {
+                            GridQueryProperty prop = table.property(colName);
+
+                            columnMeta = new JdbcColumnMetaV4(table.schemaName(), table.tableName(),
+                                field.getKey(), field.getValue(), !prop.notNull(), prop.defaultValue(),
+                                prop.precision(), prop.scale());
+                        }
+                        else if (protocolVer.compareTo(VER_2_4_0) >= 0) {
                             GridQueryProperty prop = table.property(colName);
 
                             columnMeta = new JdbcColumnMetaV3(table.schemaName(), table.tableName(),
@@ -768,7 +776,9 @@ public class JdbcRequestHandler implements ClientListenerRequestHandler {
 
             JdbcMetaColumnsResult res;
 
-            if (protocolVer.compareTo(VER_2_4_0) >= 0)
+            if (protocolVer.compareTo(VER_2_5_0) >= 0)
+                res = new JdbcMetaColumnsResultV4(meta);
+            else if (protocolVer.compareTo(VER_2_4_0) >= 0)
                 res = new JdbcMetaColumnsResultV3(meta);
             else if (protocolVer.compareTo(VER_2_3_0) >= 0)
                 res = new JdbcMetaColumnsResultV2(meta);

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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
index 43631e9..4fea207 100644
--- 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
@@ -68,6 +68,9 @@ public class JdbcResult implements JdbcRawBinarylizable {
     /** A request to send file from client to server. */
     static final byte BULK_LOAD_ACK = 16;
 
+    /** Columns metadata result V4. */
+    static final byte META_COLUMNS_V4 = 17;
+
     /** Success status. */
     private byte type;
 
@@ -171,6 +174,11 @@ public class JdbcResult implements JdbcRawBinarylizable {
 
                 break;
 
+            case META_COLUMNS_V4:
+                res = new JdbcMetaColumnsResultV4();
+
+                break;
+
             default:
                 throw new IgniteException("Unknown SQL listener request ID: [request ID=" + resId + ']');
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
index 8ebf09e..fa8e509 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
@@ -76,6 +76,8 @@ import org.apache.ignite.internal.processors.platform.cache.affinity.PlatformAff
 import org.apache.ignite.internal.processors.platform.cache.expiry.PlatformExpiryPolicyFactory;
 import org.apache.ignite.internal.processors.platform.events.PlatformLocalEventListener;
 import org.apache.ignite.internal.processors.platform.plugin.cache.PlatformCachePluginConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction;
 import org.apache.ignite.platform.dotnet.PlatformDotNetBinaryConfiguration;
@@ -492,6 +494,7 @@ public class PlatformConfigurationUtils {
         Set<String> keyFields = new HashSet<>(cnt);
         Set<String> notNullFields = new HashSet<>(cnt);
         Map<String, Object> defVals = new HashMap<>(cnt);
+        Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo = new HashMap<>(cnt);
 
         if (cnt > 0) {
             LinkedHashMap<String, String> fields = new LinkedHashMap<>(cnt);
@@ -511,6 +514,13 @@ public class PlatformConfigurationUtils {
                 Object defVal = in.readObject();
                 if (defVal != null)
                     defVals.put(fieldName, defVal);
+
+                int precision = in.readInt();
+
+                int scale = in.readInt();
+
+                if (precision != -1 || scale != -1)
+                    decimalInfo.put(fieldName, F.t(precision, scale));
             }
 
             res.setFields(fields);
@@ -523,6 +533,9 @@ public class PlatformConfigurationUtils {
 
             if (!defVals.isEmpty())
                 res.setDefaultFieldValues(defVals);
+
+            if (!decimalInfo.isEmpty())
+                res.setDecimalInfo(decimalInfo);
         }
 
         // Aliases
@@ -1012,6 +1025,7 @@ public class PlatformConfigurationUtils {
             Set<String> keyFields = qryEntity.getKeyFields();
             Set<String> notNullFields = qryEntity.getNotNullFields();
             Map<String, Object> defVals = qryEntity.getDefaultFieldValues();
+            Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo = qryEntity.getDecimalInfo();
 
             writer.writeInt(fields.size());
 
@@ -1021,6 +1035,12 @@ public class PlatformConfigurationUtils {
                 writer.writeBoolean(keyFields != null && keyFields.contains(field.getKey()));
                 writer.writeBoolean(notNullFields != null && notNullFields.contains(field.getKey()));
                 writer.writeObject(defVals != null ? defVals.get(field.getKey()) : null);
+
+                IgniteBiTuple<Integer, Integer> precisionAndScale =
+                    decimalInfo == null ? null : decimalInfo.get(field.getKey());
+
+                writer.writeInt(precisionAndScale == null ? -1 : precisionAndScale.get1());
+                writer.writeInt(precisionAndScale == null ? -1 : precisionAndScale.get2());
             }
         }
         else

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 03e5254..a74548a 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
@@ -2400,7 +2400,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         for (QueryField col : cols) {
             try {
                 props.add(new QueryBinaryProperty(ctx, col.name(), null, Class.forName(col.typeName()),
-                    false, null, !col.isNullable(), null));
+                    false, null, !col.isNullable(), null, -1, -1));
             }
             catch (ClassNotFoundException e) {
                 throw new SchemaOperationException("Class not found for new property: " + col.typeName());

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
index b258b7c..448c844 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
@@ -77,4 +77,18 @@ public interface GridQueryProperty {
      * @return {@code null} if a default value is not set for the property.
      */
     public Object defaultValue();
+
+    /**
+     * Gets precision for this property.
+     *
+     * @return Precision for a decimal property or -1.
+     */
+    public int precision();
+
+    /**
+     * Gets scale for this property.
+     *
+     * @return Scale for a decimal property or -1.
+     */
+    public int scale();
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryField.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryField.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryField.java
index 1a75ef1..882d816 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryField.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryField.java
@@ -40,13 +40,19 @@ public class QueryField implements Serializable {
     /** Default value. */
     private final Object dfltValue;
 
+    /** Precision. */
+    private final int precision;
+
+    /** Scale. */
+    private final int scale;
+
     /**
      * @param name Field name.
      * @param typeName Class name for this field's values.
      * @param nullable Nullable flag.
      */
     public QueryField(String name, String typeName, boolean nullable) {
-        this(name, typeName, nullable, null);
+        this(name, typeName, nullable, null, -1, -1);
     }
 
     /**
@@ -55,11 +61,13 @@ public class QueryField implements Serializable {
      * @param nullable Nullable flag.
      * @param dfltValue Default value.
      */
-    public QueryField(String name, String typeName, boolean nullable, Object dfltValue) {
+    public QueryField(String name, String typeName, boolean nullable, Object dfltValue, int precision, int scale) {
         this.name = name;
         this.typeName = typeName;
         this.nullable = nullable;
         this.dfltValue = dfltValue;
+        this.precision = precision;
+        this.scale = scale;
     }
 
     /**
@@ -90,6 +98,20 @@ public class QueryField implements Serializable {
         return dfltValue;
     }
 
+    /**
+     * @return Precision.
+     */
+    public int precision() {
+        return precision;
+    }
+
+    /**
+     * @return Scale.
+     */
+    public int scale() {
+        return scale;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(QueryField.class, this);

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 2ee37a1..12eacef 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
@@ -61,6 +61,7 @@ import org.apache.ignite.internal.util.Jsr310Java8DateTimeApiUtils;
 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.U;
+import org.apache.ignite.lang.IgniteBiTuple;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -264,6 +265,7 @@ public class QueryUtils {
         normalEntity.setValueFieldName(entity.getValueFieldName());
         normalEntity.setNotNullFields(entity.getNotNullFields());
         normalEntity.setDefaultFieldValues(entity.getDefaultFieldValues());
+        normalEntity.setDecimalInfo(entity.getDecimalInfo());
 
         // Normalize table name.
         String normalTblName = entity.getTableName();
@@ -541,6 +543,7 @@ public class QueryUtils {
         Set<String> keyFields = qryEntity.getKeyFields();
         Set<String> notNulls = qryEntity.getNotNullFields();
         Map<String, Object> dlftVals = qryEntity.getDefaultFieldValues();
+        Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo  = qryEntity.getDecimalInfo();
 
         // We have to distinguish between empty and null keyFields when the key is not of SQL type -
         // when a key is not of SQL type, absence of a field in nonnull keyFields tell us that this field
@@ -571,9 +574,14 @@ public class QueryUtils {
 
             Object dfltVal = dlftVals != null ? dlftVals.get(entry.getKey()) : null;
 
+            IgniteBiTuple<Integer, Integer> precisionAndScale =
+                decimalInfo != null ? decimalInfo.get(entry.getKey()) : null;
+
             QueryBinaryProperty prop = buildBinaryProperty(ctx, entry.getKey(),
                 U.classForName(entry.getValue(), Object.class, true),
-                d.aliases(), isKeyField, notNull, dfltVal);
+                d.aliases(), isKeyField, notNull, dfltVal,
+                precisionAndScale != null ? precisionAndScale.get1() : -1,
+                precisionAndScale != null ? precisionAndScale.get2() : -1);
 
             d.addProperty(prop, false);
         }
@@ -717,11 +725,14 @@ public class QueryUtils {
      *      to key, {@code false} if it belongs to value, {@code null} if QueryEntity#keyFields is null.
      * @param notNull {@code true} if {@code null} value is not allowed.
      * @param dlftVal Default value.
+     * @param precision Precision.
+     * @param scale Scale.
      * @return Binary property.
      * @throws IgniteCheckedException On error.
      */
     public static QueryBinaryProperty buildBinaryProperty(GridKernalContext ctx, String pathStr, Class<?> resType,
-        Map<String, String> aliases, @Nullable Boolean isKeyField, boolean notNull, Object dlftVal) throws IgniteCheckedException {
+        Map<String, String> aliases, @Nullable Boolean isKeyField, boolean notNull, Object dlftVal,
+        int precision, int scale) throws IgniteCheckedException {
         String[] path = pathStr.split("\\.");
 
         QueryBinaryProperty res = null;
@@ -737,7 +748,8 @@ public class QueryUtils {
             String alias = aliases.get(fullName.toString());
 
             // The key flag that we've found out is valid for the whole path.
-            res = new QueryBinaryProperty(ctx, prop, res, resType, isKeyField, alias, notNull, dlftVal);
+            res = new QueryBinaryProperty(ctx, prop, res, resType, isKeyField, alias, notNull, dlftVal,
+                precision, scale);
         }
 
         return res;
@@ -1400,5 +1412,15 @@ public class QueryUtils {
         @Override public Object defaultValue() {
             return null;
         }
+
+        /** {@inheritDoc} */
+        @Override public int precision() {
+            return -1;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int scale() {
+            return -1;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryBinaryProperty.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryBinaryProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryBinaryProperty.java
index f440d12..7a47c2f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryBinaryProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryBinaryProperty.java
@@ -71,6 +71,12 @@ public class QueryBinaryProperty implements GridQueryProperty {
     /** */
     private final Object defaultValue;
 
+    /** */
+    private final int precision;
+
+    /** */
+    private final int scale;
+
     /**
      * Constructor.
      *
@@ -82,9 +88,12 @@ public class QueryBinaryProperty implements GridQueryProperty {
      * @param alias Field alias.
      * @param notNull {@code true} if null value is not allowed.
      * @param defaultValue Default value.
+     * @param precision Precision.
+     * @param scale Scale.
      */
     public QueryBinaryProperty(GridKernalContext ctx, String propName, QueryBinaryProperty parent,
-        Class<?> type, @Nullable Boolean key, String alias, boolean notNull, Object defaultValue) {
+        Class<?> type, @Nullable Boolean key, String alias, boolean notNull, Object defaultValue,
+        int precision, int scale) {
         this.ctx = ctx;
 
         log = ctx.log(QueryBinaryProperty.class);
@@ -99,6 +108,8 @@ public class QueryBinaryProperty implements GridQueryProperty {
             this.isKeyProp = key ? 1 : -1;
 
         this.defaultValue = defaultValue;
+        this.precision = precision;
+        this.scale = scale;
     }
 
     /** {@inheritDoc} */
@@ -286,4 +297,14 @@ public class QueryBinaryProperty implements GridQueryProperty {
     @Override public Object defaultValue() {
         return defaultValue;
     }
+
+    /** {@inheritDoc} */
+    @Override public int precision() {
+        return precision;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int scale() {
+        return scale;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryClassProperty.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryClassProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryClassProperty.java
index 575fe17..487ee5b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryClassProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryClassProperty.java
@@ -146,4 +146,14 @@ public class QueryClassProperty implements GridQueryProperty {
     @Override public Object defaultValue() {
         return null;
     }
+
+    /** {@inheritDoc} */
+    @Override public int precision() {
+        return -1;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int scale() {
+        return -1;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 bc5c1e0..f907138 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
@@ -71,6 +71,7 @@ import org.apache.ignite.internal.sql.command.SqlIndexColumn;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.plugin.security.SecurityPermission;
 import org.h2.command.Prepared;
 import org.h2.command.ddl.AlterTableAlterColumn;
@@ -80,6 +81,7 @@ import org.h2.command.ddl.DropIndex;
 import org.h2.command.ddl.DropTable;
 import org.h2.table.Column;
 import org.h2.value.DataType;
+import org.h2.value.Value;
 
 import static org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.UPDATE_RESULT_META;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser.PARAM_WRAP_VALUE;
@@ -420,7 +422,8 @@ public class DdlStatementsProcessor {
 
                         QueryField field = new QueryField(col.columnName(),
                             DataType.getTypeClassName(col.column().getType()),
-                            col.column().isNullable(), col.defaultValue());
+                            col.column().isNullable(), col.defaultValue(),
+                            col.precision(), col.scale());
 
                         cols.add(field);
 
@@ -595,6 +598,8 @@ public class DdlStatementsProcessor {
 
         HashMap<String, Object> dfltValues = new HashMap<>();
 
+        Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo = new HashMap<>();
+
         for (Map.Entry<String, GridSqlColumn> e : createTbl.columns().entrySet()) {
             GridSqlColumn gridCol = e.getValue();
 
@@ -613,11 +618,17 @@ public class DdlStatementsProcessor {
 
             if (dfltVal != null)
                 dfltValues.put(e.getKey(), dfltVal);
+
+            if (col.getType() == Value.DECIMAL)
+                decimalInfo.put(e.getKey(), F.t((int)col.getPrecision(), col.getScale()));
         }
 
         if (!F.isEmpty(dfltValues))
             res.setDefaultFieldValues(dfltValues);
 
+        if (!F.isEmpty(decimalInfo))
+            res.setDecimalInfo(decimalInfo);
+
         String valTypeName = QueryUtils.createTableValueTypeName(createTbl.schemaName(), createTbl.tableName());
         String keyTypeName = QueryUtils.createTableKeyTypeName(valTypeName);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
index bc14ae2..0efbd4c 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
@@ -22,6 +22,7 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.h2.command.Parser;
 import org.h2.expression.Expression;
 import org.h2.table.Column;
+import org.h2.value.Value;
 
 /**
  * Column.
@@ -129,9 +130,23 @@ public class GridSqlColumn extends GridSqlElement {
     }
 
     /**
+     * @return Precision.
+     */
+    public int precision() {
+        return (int) col.getPrecision();
+    }
+
+    /**
+     * @return Scale.
+     */
+    public int scale() {
+        return col.getScale();
+    }
+
+    /**
      * @return H2 Column.
      */
     public Column column() {
         return col;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/IgniteDecimalSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/IgniteDecimalSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/IgniteDecimalSelfTest.java
new file mode 100644
index 0000000..9e65276
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/IgniteDecimalSelfTest.java
@@ -0,0 +1,265 @@
+/*
+ * 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.index;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.QueryEntity;
+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.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.jetbrains.annotations.NotNull;
+
+import static java.math.RoundingMode.HALF_UP;
+import static java.util.Arrays.asList;
+
+/**
+ * Test to check decimal columns.
+ */
+public class IgniteDecimalSelfTest extends AbstractSchemaSelfTest {
+    /** */
+    private static final int PRECISION = 9;
+
+    /** */
+    private static final int SCALE = 8;
+
+    /** */
+    private static final String DEC_TAB_NAME = "DECIMAL_TABLE";
+
+    /** */
+    private static final String VALUE = "VALUE";
+
+    /** */
+    private static final String SALARY_TAB_NAME = "SALARY";
+
+    /** */
+    private static final MathContext MATH_CTX = new MathContext(PRECISION);
+
+    /** */
+    private static final BigDecimal VAL_1 = new BigDecimal("123456789", MATH_CTX).setScale(SCALE, HALF_UP);
+
+    /** */
+    private static final BigDecimal VAL_2 = new BigDecimal("12345678.12345678", MATH_CTX).setScale(SCALE, HALF_UP);
+
+    /** */
+    private static final BigDecimal VAL_3 = new BigDecimal(".123456789", MATH_CTX).setScale(SCALE, HALF_UP);
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        IgniteEx grid = startGrid(0);
+
+        execute(grid, "CREATE TABLE " + DEC_TAB_NAME +
+            "(id LONG PRIMARY KEY, " + VALUE + " DECIMAL(" + PRECISION + ", " + SCALE + "))");
+
+        String insertQry = "INSERT INTO " + DEC_TAB_NAME + " VALUES (?, ?)";
+
+        execute(grid, insertQry, 1, VAL_1);
+        execute(grid, insertQry, 2, VAL_2);
+        execute(grid, insertQry, 3, VAL_3);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        CacheConfiguration<Integer, Salary> ccfg = cacheCfg(SALARY_TAB_NAME, "salary_cache");
+
+        cfg.setCacheConfiguration(ccfg);
+
+        return cfg;
+    }
+
+    /** */
+    @NotNull private CacheConfiguration<Integer, Salary> cacheCfg(String tabName, String cacheName) {
+        CacheConfiguration<Integer, Salary> ccfg = new CacheConfiguration<>(cacheName);
+
+        QueryEntity queryEntity = new QueryEntity(Integer.class.getName(), Salary.class.getName());
+
+        queryEntity.setTableName(tabName);
+
+        queryEntity.addQueryField("id", Integer.class.getName(), null);
+        queryEntity.addQueryField("amount", BigDecimal.class.getName(), null);
+
+        Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo = new HashMap<>();
+
+        decimalInfo.put("amount", F.t(PRECISION, SCALE));
+
+        queryEntity.setDecimalInfo(decimalInfo);
+
+        ccfg.setQueryEntities(Collections.singletonList(queryEntity));
+
+        return ccfg;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testConfiguredFromDdl() throws Exception {
+        checkDecimalInfo(DEC_TAB_NAME, VALUE, PRECISION, SCALE);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testConfiguredFromQueryEntity() throws Exception {
+        checkDecimalInfo(SALARY_TAB_NAME, "amount", PRECISION, SCALE);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testConfiguredFromQueryEntityInDynamicallyCreatedCache() throws Exception {
+        IgniteEx grid = grid(0);
+
+        String tabName = SALARY_TAB_NAME + "2";
+
+        CacheConfiguration<Integer, Salary> ccfg = cacheCfg(tabName, "SalaryCache-2");
+
+        IgniteCache<Integer, Salary> cache = grid.createCache(ccfg);
+
+        checkDecimalInfo(tabName, "amount", PRECISION, SCALE);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testConfiguredFromAnnotations() throws Exception {
+        IgniteEx grid = grid(0);
+
+        CacheConfiguration<Integer, Salary> ccfg = new CacheConfiguration<>("SalaryCache-3");
+
+        ccfg.setIndexedTypes(Integer.class, SalaryWithAnnotations.class);
+
+        grid.createCache(ccfg);
+
+        checkDecimalInfo(SalaryWithAnnotations.class.getSimpleName().toUpperCase(), "amount", PRECISION, SCALE);
+    }
+
+    /** */
+    public void testSelectDecimal() throws Exception {
+        IgniteEx grid = grid(0);
+
+        List rows = execute(grid, "SELECT id, value FROM " + DEC_TAB_NAME + " order by id");
+
+        assertEquals(rows.size(), 3);
+
+        assertEquals(asList(1L, VAL_1), rows.get(0));
+        assertEquals(asList(2L, VAL_2), rows.get(1));
+        assertEquals(asList(3L, VAL_3), rows.get(2));
+    }
+
+    /** */
+    private void checkDecimalInfo(String tabName, String colName, Integer precision, Integer scale) {
+        QueryEntity queryEntity = findTableInfo(tabName);
+
+        assertNotNull(queryEntity);
+
+        Map<String, IgniteBiTuple<Integer, Integer>> decimalInfo = queryEntity.getDecimalInfo();
+
+        assertNotNull(decimalInfo);
+
+        IgniteBiTuple<Integer, Integer> columnInfo = decimalInfo.get(colName);
+
+        assertNotNull(columnInfo);
+
+        assertEquals(columnInfo.get1(), precision);
+        assertEquals(columnInfo.get2(), scale);
+    }
+
+    /**
+     * @param tabName Table name.
+     * @return QueryEntity of table.
+     */
+    private QueryEntity findTableInfo(String tabName) {
+        IgniteEx ignite = grid(0);
+
+        Collection<String> cacheNames = ignite.cacheNames();
+
+        for (String cacheName : cacheNames) {
+            CacheConfiguration ccfg = ignite.cache(cacheName).getConfiguration(CacheConfiguration.class);
+
+            Collection<QueryEntity> entities = ccfg.getQueryEntities();
+
+            for (QueryEntity entity : entities)
+                if (entity.getTableName().equalsIgnoreCase(tabName))
+                    return entity;
+        }
+
+        return null;
+    }
+
+    /**
+     * Execute DDL statement on given node.
+     *
+     * @param node Node.
+     * @param sql Statement.
+     */
+    private List<List<?>> execute(Ignite node, String sql, Object... args) {
+        SqlFieldsQuery qry = new SqlFieldsQuery(sql)
+            .setArgs(args)
+            .setSchema("PUBLIC");
+
+        return queryProcessor(node).querySqlFields(qry, true).getAll();
+    }
+
+    /** */
+    private static class Salary {
+        /** */
+        private BigDecimal amount;
+
+        /** */
+        public BigDecimal getAmount() {
+            return amount;
+        }
+
+        /** */
+        public void setAmount(BigDecimal amount) {
+            this.amount = amount;
+        }
+    }
+
+    /** */
+    private static class SalaryWithAnnotations {
+        /** */
+        @QuerySqlField(index = true, precision = PRECISION, scale = SCALE)
+        private BigDecimal amount;
+
+        /** */
+        public BigDecimal getAmount() {
+            return amount;
+        }
+
+        /** */
+        public void setAmount(BigDecimal amount) {
+            this.amount = amount;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
index 1da695b..235b28b 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
@@ -565,6 +565,16 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
                 @Override public Object defaultValue() {
                     return null;
                 }
+
+                /** */
+                @Override public int precision() {
+                    return -1;
+                }
+
+                /** */
+                @Override public int scale() {
+                    return -1;
+                }
             };
         }
 
@@ -783,4 +793,4 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
             return false;
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/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 e10fff1..619e7cf 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
@@ -108,6 +108,7 @@ import org.apache.ignite.internal.processors.cache.index.DynamicIndexServerCoord
 import org.apache.ignite.internal.processors.cache.index.DynamicIndexServerNodeFIlterBasicSelfTest;
 import org.apache.ignite.internal.processors.cache.index.DynamicIndexServerNodeFilterCoordinatorBasicSelfTest;
 import org.apache.ignite.internal.processors.cache.index.H2ConnectionLeaksSelfTest;
+import org.apache.ignite.internal.processors.cache.index.IgniteDecimalSelfTest;
 import org.apache.ignite.internal.processors.cache.index.H2DynamicColumnsClientBasicSelfTest;
 import org.apache.ignite.internal.processors.cache.index.H2DynamicColumnsServerBasicSelfTest;
 import org.apache.ignite.internal.processors.cache.index.H2DynamicColumnsServerCoordinatorBasicSelfTest;
@@ -397,6 +398,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
         suite.addTestSuite(OptimizedMarshallerIndexNameTest.class);
 
         suite.addTestSuite(IgniteSqlDefaultValueTest.class);
+        suite.addTestSuite(IgniteDecimalSelfTest.class);
 
         // H2 Rows on-heap cache
         suite.addTestSuite(H2RowCacheSelfTest.class);

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/QueryEntityConfigurationParityTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/QueryEntityConfigurationParityTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/QueryEntityConfigurationParityTest.cs
index a9830d8..ba10cda 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/QueryEntityConfigurationParityTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/QueryEntityConfigurationParityTest.cs
@@ -32,7 +32,8 @@ namespace Apache.Ignite.Core.Tests.ApiParity
             "findValueType",
             "KeyFields",
             "NotNullFields",
-            "DefaultFieldValues"
+            "DefaultFieldValues",
+            "DecimalInfo"
         };
 
         /// <summary>
@@ -47,4 +48,4 @@ namespace Apache.Ignite.Core.Tests.ApiParity
                 UnneededProperties);
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
index 6834d5d..9d59a50 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
@@ -551,6 +551,8 @@ namespace Apache.Ignite.Core.Tests.Cache
             Assert.AreEqual(x.IsKeyField, y.IsKeyField);
             Assert.AreEqual(x.NotNull, y.NotNull);
             Assert.AreEqual(x.DefaultValue, y.DefaultValue);
+            Assert.AreEqual(x.Precision, y.Precision);
+            Assert.AreEqual(x.Scale, y.Scale);
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
index 8855535..32173ba 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
@@ -458,7 +458,9 @@ namespace Apache.Ignite.Core.Cache.Configuration
                     {
                         IsKeyField = isKey,
                         NotNull = attr.NotNull,
-                        DefaultValue = attr.DefaultValue
+                        DefaultValue = attr.DefaultValue,
+                        Precision = attr.Precision,
+                        Scale = attr.Scale
                     });
 
                     ScanAttributes(memberInfo.Value, fields, indexes, columnName, visitedTypes, isKey);

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryField.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryField.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryField.cs
index a96f1bf..869ce7d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryField.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryField.cs
@@ -85,6 +85,8 @@ namespace Apache.Ignite.Core.Cache.Configuration
             IsKeyField = reader.ReadBoolean();
             NotNull = reader.ReadBoolean();
             DefaultValue = reader.ReadObject<object>();
+            Precision = reader.ReadInt();
+            Scale = reader.ReadInt();
         }
 
         /// <summary>
@@ -99,6 +101,8 @@ namespace Apache.Ignite.Core.Cache.Configuration
             writer.WriteBoolean(IsKeyField);
             writer.WriteBoolean(NotNull);
             writer.WriteObject(DefaultValue);
+            writer.WriteInt(Precision);
+            writer.WriteInt(Scale);
         }
 
         /// <summary>
@@ -154,6 +158,16 @@ namespace Apache.Ignite.Core.Cache.Configuration
         public object DefaultValue { get; set; }
 
         /// <summary>
+        /// Gets or sets the precision for the field.
+        /// </summary>
+        public int Precision { get; set; }
+
+        /// <summary>
+        /// Gets or sets the scale for the field.
+        /// </summary>
+        public int Scale { get; set; }
+
+        /// <summary>
         /// Validates this instance and outputs information to the log, if necessary.
         /// </summary>
         internal void Validate(ILogger log, string logInfo)
@@ -179,4 +193,4 @@ namespace Apache.Ignite.Core.Cache.Configuration
             }
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QuerySqlFieldAttribute.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QuerySqlFieldAttribute.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QuerySqlFieldAttribute.cs
index dd131f9..bfd3575 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QuerySqlFieldAttribute.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QuerySqlFieldAttribute.cs
@@ -81,5 +81,15 @@ namespace Apache.Ignite.Core.Cache.Configuration
         /// Gets or sets the default value for the field (has effect when inserting with DML).
         /// </summary>
         public object DefaultValue { get; set; }
+
+        /// <summary>
+        /// Gets or sets the precision for the field.
+        /// </summary>
+        public int Precision { get; set; }
+
+        /// <summary>
+        /// Gets or sets the scale for the field.
+        /// </summary>
+        public int Scale { get; set; }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/6df5f99b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
index a97136f..8707272 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -340,6 +340,16 @@
                                                                                             <xs:documentation>Indicates whether null value is allowed for the field.</xs:documentation>
                                                                                         </xs:annotation>
                                                                                     </xs:attribute>
+                                                                                    <xs:attribute name="precision" type="xs:int">
+                                                                                        <xs:annotation>
+                                                                                            <xs:documentation>Precision of field</xs:documentation>
+                                                                                        </xs:annotation>
+                                                                                    </xs:attribute>
+                                                                                    <xs:attribute name="scale" type="xs:int">
+                                                                                        <xs:annotation>
+                                                                                            <xs:documentation>Scale of field</xs:documentation>
+                                                                                        </xs:annotation>
+                                                                                    </xs:attribute>
                                                                                 </xs:complexType>
                                                                             </xs:element>
                                                                         </xs:sequence>