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/11/02 10:17:37 UTC

ignite git commit: IGNITE-8331: Add Decimal precision and scale constraint - Fixes #4689.

Repository: ignite
Updated Branches:
  refs/heads/master 9e35993c0 -> 66755c1a2


IGNITE-8331: Add Decimal precision and scale constraint - Fixes #4689.

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/66755c1a
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/66755c1a
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/66755c1a

Branch: refs/heads/master
Commit: 66755c1a2f39f9da948e4033a8b64afd9ba242f5
Parents: 9e35993
Author: ololo3000 <pm...@gmail.com>
Authored: Fri Nov 2 12:44:27 2018 +0300
Committer: Nikolay Izhikov <ni...@apache.org>
Committed: Fri Nov 2 13:13:57 2018 +0300

----------------------------------------------------------------------
 .../jdbc/thin/JdbcThinMetadataSelfTest.java     |  11 +-
 .../cache/query/IgniteQueryErrorCode.java       |   8 +
 .../query/QueryTypeDescriptorImpl.java          |  25 +-
 .../internal/processors/query/QueryUtils.java   |  21 +-
 .../cache/index/IgniteDecimalSelfTest.java      |   7 +-
 ...ePartitionedAtomicColumnConstraintsTest.java | 405 ++++++++++++++++++-
 ...ansactionalSnapshotColumnConstraintTest.java | 120 ++++++
 ...ansactionalSnapshotColumnConstraintTest.java | 120 ++++++
 .../sql/IgniteSQLColumnConstraintsTest.java     | 288 +++++++++++--
 ...gniteTransactionSQLColumnConstraintTest.java |  71 ++++
 .../IgniteBinaryCacheQueryTestSuite.java        |   6 +
 11 files changed, 1015 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/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 2bc569d..6e08862 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
@@ -155,6 +155,7 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
             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))");
+            stmt.execute("CREATE TABLE TEST_DECIMAL_COLUMN_PRECISION (ID INT primary key, DEC_COL DECIMAL(8))");
         }
     }
 
@@ -253,7 +254,8 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
                 "dep.DEPARTMENT",
                 "PUBLIC.TEST",
                 "PUBLIC.Quoted",
-                "PUBLIC.TEST_DECIMAL_COLUMN"));
+                "PUBLIC.TEST_DECIMAL_COLUMN",
+                "PUBLIC.TEST_DECIMAL_COLUMN_PRECISION"));
 
             Set<String> actualTbls = new HashSet<>(expectedTbls.size());
 
@@ -403,7 +405,9 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
                 "PUBLIC.Quoted.Id.null",
                 "PUBLIC.Quoted.Name.null.50",
                 "PUBLIC.TEST_DECIMAL_COLUMN.ID.null",
-                "PUBLIC.TEST_DECIMAL_COLUMN.DEC_COL.null.8.3"
+                "PUBLIC.TEST_DECIMAL_COLUMN.DEC_COL.null.8.3",
+                "PUBLIC.TEST_DECIMAL_COLUMN_PRECISION.ID.null",
+                "PUBLIC.TEST_DECIMAL_COLUMN_PRECISION.DEC_COL.null.8"
             ));
 
             Set<String> actualCols = new HashSet<>(expectedCols.size());
@@ -555,7 +559,8 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
                 "PUBLIC.TEST.PK_PUBLIC_TEST.ID",
                 "PUBLIC.TEST.PK_PUBLIC_TEST.NAME",
                 "PUBLIC.Quoted.PK_PUBLIC_Quoted.Id",
-                "PUBLIC.TEST_DECIMAL_COLUMN.ID.ID"));
+                "PUBLIC.TEST_DECIMAL_COLUMN.ID.ID",
+                "PUBLIC.TEST_DECIMAL_COLUMN_PRECISION.ID.ID"));
 
             Set<String> actualPks = new HashSet<>(expectedPks.size());
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/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 fd017f2..39f1b60 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
@@ -106,6 +106,12 @@ public final class IgniteQueryErrorCode {
     /** Attempt to INSERT, UPDATE or MERGE value that exceed maximum column length. */
     public static final int TOO_LONG_VALUE = 4008;
 
+    /** Attempt to INSERT, UPDATE or MERGE value which scale exceed maximum DECIMAL column scale. */
+    public static final int VALUE_SCALE_OUT_OF_RANGE = 4009;
+
+    /** Attempt to INSERT, UPDATE or MERGE value which scale exceed maximum DECIMAL column scale. */
+    public static final int KEY_SCALE_OUT_OF_RANGE = 4010;
+
     /* 5xxx - transactions related runtime errors. */
 
     /** Transaction is already open. */
@@ -151,6 +157,8 @@ public final class IgniteQueryErrorCode {
             case DUPLICATE_KEY:
             case TOO_LONG_KEY:
             case TOO_LONG_VALUE:
+            case KEY_SCALE_OUT_OF_RANGE:
+            case VALUE_SCALE_OUT_OF_RANGE:
                 return SqlStateCode.CONSTRAINT_VIOLATION;
 
             case NULL_KEY:

http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
index 6d8085e..87394f6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.processors.query;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -36,10 +37,12 @@ import org.apache.ignite.internal.util.typedef.internal.A;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.jetbrains.annotations.Nullable;
 
+import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.KEY_SCALE_OUT_OF_RANGE;
 import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.NULL_KEY;
 import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.NULL_VALUE;
 import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TOO_LONG_KEY;
 import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TOO_LONG_VALUE;
+import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.VALUE_SCALE_OUT_OF_RANGE;
 import static org.apache.ignite.internal.processors.query.QueryUtils.KEY_FIELD_NAME;
 import static org.apache.ignite.internal.processors.query.QueryUtils.VAL_FIELD_NAME;
 
@@ -579,14 +582,30 @@ public class QueryTypeDescriptorImpl implements GridQueryTypeDescriptor {
                     isKey ? NULL_KEY : NULL_VALUE);
             }
 
-            if (prop.precision() != -1 &&
-                propVal != null &&
-                String.class == propVal.getClass() && 
+            if (propVal == null || prop.precision() == -1)
+                continue;
+
+            if (String.class == propVal.getClass() &&
                 ((String)propVal).length() > prop.precision()) {
                 throw new IgniteSQLException("Value for a column '" + prop.name() + "' is too long. " + 
                     "Maximum length: " + prop.precision() + ", actual length: " + ((CharSequence)propVal).length(),
                     isKey ? TOO_LONG_KEY : TOO_LONG_VALUE);
             }
+            else if (BigDecimal.class == propVal.getClass()) {
+                BigDecimal dec = (BigDecimal)propVal;
+
+                if (dec.precision() > prop.precision()) {
+                    throw new IgniteSQLException("Value for a column '" + prop.name() + "' is out of range. " +
+                        "Maximum precision: " + prop.precision() + ", actual precision: " + dec.precision(),
+                        isKey ? TOO_LONG_KEY : TOO_LONG_VALUE);
+                }
+                else if (prop.scale() != -1 &&
+                    dec.scale() > prop.scale()) {
+                    throw new IgniteSQLException("Value for a column '" + prop.name() + "' is out of range. " +
+                        "Maximum scale : " + prop.scale() + ", actual scale: " + dec.scale(),
+                        isKey ? KEY_SCALE_OUT_OF_RANGE : VALUE_SCALE_OUT_OF_RANGE);
+                }
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/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 e9420f1..44e07a6 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
@@ -67,6 +67,8 @@ import org.jetbrains.annotations.Nullable;
 
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_INDEXING_DISCOVERY_HISTORY_SIZE;
 import static org.apache.ignite.IgniteSystemProperties.getInteger;
+import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TOO_LONG_VALUE;
+import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.VALUE_SCALE_OUT_OF_RANGE;
 
 /**
  * Utility methods for queries.
@@ -1271,6 +1273,7 @@ public class QueryUtils {
 
         Map<String, Object> dfltVals = entity.getDefaultFieldValues();
         Map<String, Integer> precision = entity.getFieldsPrecision();
+        Map<String, Integer> scale = entity.getFieldsScale();
 
         if (!F.isEmpty(precision)) {
             for (String fld : precision.keySet()) {
@@ -1282,9 +1285,23 @@ public class QueryUtils {
                 if (dfltVal == null)
                     continue;
 
-                if (dfltVal.toString().length() > precision.get(fld)) {
+                if (dfltVal.getClass() == String.class && dfltVal.toString().length() > precision.get(fld)) {
                     throw new IgniteSQLException("Default value '" + dfltVal +
-                        "' is longer than maximum length " + precision.get(fld));
+                        "' is longer than maximum length " + precision.get(fld), TOO_LONG_VALUE);
+                }
+                else if (dfltVal.getClass() == BigDecimal.class) {
+                    BigDecimal dec = (BigDecimal)dfltVal;
+
+                    if (dec.precision() > precision.get(fld)) {
+                        throw new IgniteSQLException("Default value: '" + dfltVal + "' for a column " + fld +
+                            " is out of range. Maximum precision: " + precision.get(fld) +
+                            ", actual precision: " + dec.precision(), TOO_LONG_VALUE);
+                    }
+                    else if (!F.isEmpty(scale) && scale.containsKey(fld) && dec.scale() > scale.get(fld)) {
+                        throw new IgniteSQLException("Default value:: '" + dfltVal + "' for a column " + fld +
+                            " is out of range. Maximum scale: " + scale.get(fld) +
+                            ", actual scale: " + dec.scale(), VALUE_SCALE_OUT_OF_RANGE);
+                    }
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/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
index 96926ea..b3743de 100644
--- 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
@@ -34,7 +34,6 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteEx;
 import org.jetbrains.annotations.NotNull;
 
-import static java.math.RoundingMode.HALF_UP;
 import static java.util.Arrays.asList;
 
 /**
@@ -60,13 +59,13 @@ public class IgniteDecimalSelfTest extends AbstractSchemaSelfTest {
     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_1 = BigDecimal.valueOf(123456789);
 
     /** */
-    private static final BigDecimal VAL_2 = new BigDecimal("12345678.12345678", MATH_CTX).setScale(SCALE, HALF_UP);
+    private static final BigDecimal VAL_2 = BigDecimal.valueOf(1.23456789);
 
     /** */
-    private static final BigDecimal VAL_3 = new BigDecimal(".123456789", MATH_CTX).setScale(SCALE, HALF_UP);
+    private static final BigDecimal VAL_3 = BigDecimal.valueOf(.12345678);
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {

http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCachePartitionedAtomicColumnConstraintsTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCachePartitionedAtomicColumnConstraintsTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCachePartitionedAtomicColumnConstraintsTest.java
index 3715cf7..71bedaa 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCachePartitionedAtomicColumnConstraintsTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCachePartitionedAtomicColumnConstraintsTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.processors.sql;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -39,6 +40,7 @@ import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.jetbrains.annotations.NotNull;
 
 import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT;
 import static org.apache.ignite.cache.CacheMode.PARTITIONED;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
 import static org.apache.ignite.internal.processors.query.QueryUtils.KEY_FIELD_NAME;
@@ -55,13 +57,32 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
 
     /** */
     private static final String STR_ORG_CACHE_NAME = "STR_ORG";
-    
+
+    /** */
     private static final String STR_ORG_WITH_FIELDS_CACHE_NAME = "STR_ORG_WITH_FIELDS";
 
     /** */
     private static final String OBJ_CACHE_NAME = "ORG_ADDRESS";
 
     /** */
+    private static final String DEC_CACHE_NAME_FOR_SCALE = "DEC_DEC_FOR_SCALE";
+
+    /** */
+    private static final String OBJ_CACHE_NAME_FOR_SCALE = "ORG_EMPLOYEE_FOR_SCALE";
+
+    /** */
+    private static final String DEC_EMPL_CACHE_NAME_FOR_SCALE = "DEC_EMPLOYEE_FOR_SCALE";
+
+    /** */
+    private static final String DEC_CACHE_NAME_FOR_PREC = "DEC_DEC_FOR_PREC";
+
+    /** */
+    private static final String OBJ_CACHE_NAME_FOR_PREC = "ORG_EMPLOYEE_FOR_PREC";
+
+    /** */
+    private static final String DEC_EMPL_CACHE_NAME_FOR_PREC = "DEC_EMPLOYEE_FOR_PREC";
+
+    /** */
     private Consumer<Runnable> shouldFail = (op) -> assertThrowsWithCause(op, IgniteException.class);
 
     /** */
@@ -71,6 +92,15 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
     @Override protected void beforeTestsStarted() throws Exception {
         startGrid(0);
 
+        createCachesForStringTests();
+
+        createCachesForDecimalPrecisionTests();
+
+        createCachesForDecimalScaleTests();
+    }
+
+    /** @throws Exception If failed.*/
+    private void createCachesForStringTests() throws Exception {
         Map<String, Integer> strStrPrecision = new HashMap<>();
 
         strStrPrecision.put(KEY_FIELD_NAME, 5);
@@ -102,10 +132,88 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
             .setFieldsPrecision(strOrgPrecision)), STR_ORG_WITH_FIELDS_CACHE_NAME);
     }
 
+    /** @throws Exception If failed.*/
+    private void createCachesForDecimalPrecisionTests() throws Exception {
+        Map<String, Integer> decDecPrecision = new HashMap<>();
+
+        decDecPrecision.put(KEY_FIELD_NAME, 4);
+        decDecPrecision.put(VAL_FIELD_NAME, 4);
+
+        jcache(grid(0), cacheConfiguration(new QueryEntity(BigDecimal.class.getName(), BigDecimal.class.getName())
+            .setFieldsPrecision(decDecPrecision)), DEC_CACHE_NAME_FOR_PREC);
+
+        Map<String, Integer> orgEmployeePrecision = new HashMap<>();
+
+        orgEmployeePrecision.put("id", 4);
+        orgEmployeePrecision.put("salary", 4);
+
+        jcache(grid(0), cacheConfiguration(new QueryEntity(DecOrganization.class.getName(), Employee.class.getName())
+            .addQueryField("id", "java.math.BigDecimal", "id")
+            .addQueryField("salary", "java.math.BigDecimal", "salary")
+            .setFieldsPrecision(orgEmployeePrecision)), OBJ_CACHE_NAME_FOR_PREC);
+
+        Map<String, Integer> decEmployeePrecision = new HashMap<>();
+
+        decEmployeePrecision.put(KEY_FIELD_NAME, 4);
+        decEmployeePrecision.put("salary", 4);
+
+        jcache(grid(0), cacheConfiguration(new QueryEntity(BigDecimal.class.getName(), Employee.class.getName())
+            .addQueryField("salary", "java.math.BigDecimal", "salary")
+            .setFieldsPrecision(decEmployeePrecision)), DEC_EMPL_CACHE_NAME_FOR_PREC);
+    }
+
+    /** @throws Exception If failed.*/
+    private void createCachesForDecimalScaleTests() throws Exception {
+        Map<String, Integer> decDecPrecision = new HashMap<>();
+
+        decDecPrecision.put(KEY_FIELD_NAME, 4);
+        decDecPrecision.put(VAL_FIELD_NAME, 4);
+
+        Map<String, Integer> decDecScale = new HashMap<>();
+
+        decDecScale.put(KEY_FIELD_NAME, 2);
+        decDecScale.put(VAL_FIELD_NAME, 2);
+
+        jcache(grid(0), cacheConfiguration(new QueryEntity(BigDecimal.class.getName(), BigDecimal.class.getName())
+            .setFieldsScale(decDecScale)
+            .setFieldsPrecision(decDecPrecision)), DEC_CACHE_NAME_FOR_SCALE);
+
+        Map<String, Integer> orgEmployeePrecision = new HashMap<>();
+
+        orgEmployeePrecision.put("id", 4);
+        orgEmployeePrecision.put("salary", 4);
+
+        Map<String, Integer> orgEmployeeScale = new HashMap<>();
+
+        orgEmployeeScale.put("id", 2);
+        orgEmployeeScale.put("salary", 2);
+
+        jcache(grid(0), cacheConfiguration(new QueryEntity(DecOrganization.class.getName(), Employee.class.getName())
+            .addQueryField("id", "java.math.BigDecimal", "id")
+            .addQueryField("salary", "java.math.BigDecimal", "salary")
+            .setFieldsScale(orgEmployeeScale)
+            .setFieldsPrecision(orgEmployeePrecision)), OBJ_CACHE_NAME_FOR_SCALE);
+
+        Map<String, Integer> decEmployeePrecision = new HashMap<>();
+
+        decEmployeePrecision.put(KEY_FIELD_NAME, 4);
+        decEmployeePrecision.put("salary", 4);
+
+        Map<String, Integer> decEmployeeScale = new HashMap<>();
+
+        decEmployeeScale.put(KEY_FIELD_NAME, 2);
+        decEmployeeScale.put("salary", 2);
+
+        jcache(grid(0), cacheConfiguration(new QueryEntity(BigDecimal.class.getName(), Employee.class.getName())
+            .addQueryField("salary", "java.math.BigDecimal", "salary")
+            .setFieldsPrecision(decEmployeePrecision)
+            .setFieldsScale(decEmployeeScale)), DEC_EMPL_CACHE_NAME_FOR_SCALE);
+    }
+
     /**
      * @throws Exception If failed.
      */
-    public void testPutTooLongValueFail() throws Exception {
+    public void testPutTooLongStringValueFail() throws Exception {
         IgniteCache<String, String> cache = jcache(0, STR_CACHE_NAME);
 
         T2<String, String> val = new T2<>("3", "123456");
@@ -113,14 +221,14 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
         checkPutAll(shouldFail, cache, new T2<>("1", "1"), val);
 
         checkPutOps(shouldFail, cache, val);
-        
+
         checkReplaceOps(shouldFail, cache, val, "1");
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testPutTooLongKeyFail() throws Exception {
+    public void testPutTooLongStringKeyFail() throws Exception {
         IgniteCache<String, String> cache = jcache(0, STR_CACHE_NAME);
 
         T2<String, String> val = new T2<>("123456", "2");
@@ -133,7 +241,7 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
     /**
      * @throws Exception If failed.
      */
-    public void testPutTooLongValueFieldFail() throws Exception {
+    public void testPutTooLongStringValueFieldFail() throws Exception {
         IgniteCache<Organization, Address> cache = jcache(0, OBJ_CACHE_NAME);
 
         T2<Organization, Address> val = new T2<>(new Organization("3"), new Address("123456"));
@@ -148,7 +256,7 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
     /**
      * @throws Exception If failed.
      */
-    public void testPutTooLongKeyFieldFail() throws Exception {
+    public void testPutTooLongStringKeyFieldFail() throws Exception {
         IgniteCache<Organization, Address> cache = jcache(0, OBJ_CACHE_NAME);
 
         T2<Organization, Address> val = new T2<>(new Organization("123456"), new Address("2"));
@@ -161,19 +269,21 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
     /**
      * @throws Exception If failed.
      */
-    public void testPutTooLongKeyFail2() throws Exception {
-        doCheckPutTooLongKeyFail2(STR_ORG_CACHE_NAME);
+    public void testPutTooLongStringKeyFail2() throws Exception {
+        doCheckPutTooLongStringKeyFail2(STR_ORG_CACHE_NAME);
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testPutTooLongKeyFail3() throws Exception {
-        doCheckPutTooLongKeyFail2(STR_ORG_WITH_FIELDS_CACHE_NAME);
+    public void testPutTooLongStringKeyFail3() throws Exception {
+        doCheckPutTooLongStringKeyFail2(STR_ORG_WITH_FIELDS_CACHE_NAME);
     }
 
-
-    private void doCheckPutTooLongKeyFail2(String cacheName) {
+    /**
+     * @throws Exception If failed.
+     */
+    private void doCheckPutTooLongStringKeyFail2(String cacheName) {
         IgniteCache<String, Organization> cache = jcache(0, cacheName);
 
         T2<String, Organization> val = new T2<>("123456", new Organization("1"));
@@ -186,7 +296,7 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
     /**
      * @throws Exception If failed.
      */
-    public void testPutLongValue() throws Exception {
+    public void testPutLongStringValue() throws Exception {
         IgniteCache<String, String> cache = jcache(0, STR_CACHE_NAME);
 
         T2<String, String> val = new T2<>("3", "12345");
@@ -201,7 +311,7 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
     /**
      * @throws Exception If failed.
      */
-    public void testPutLongKey() throws Exception {
+    public void testPutLongStringKey() throws Exception {
         IgniteCache<String, String> cache = jcache(0, STR_CACHE_NAME);
 
         T2<String, String> val = new T2<>("12345", "2");
@@ -214,7 +324,7 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
     /**
      * @throws Exception If failed.
      */
-    public void testPutLongValueField() throws Exception {
+    public void testPutLongStringValueField() throws Exception {
         IgniteCache<Organization, Address> cache = jcache(0, OBJ_CACHE_NAME);
 
         T2<Organization, Address> val = new T2<>(new Organization("3"), new Address("12345"));
@@ -229,7 +339,7 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
     /**
      * @throws Exception If failed.
      */
-    public void testPutLongKeyField() throws Exception {
+    public void testPutLongStringKeyField() throws Exception {
         IgniteCache<Organization, Address> cache = jcache(0, OBJ_CACHE_NAME);
 
         T2<Organization, Address> val = new T2<>(new Organization("12345"), new Address("2"));
@@ -242,18 +352,21 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
     /**
      * @throws Exception If failed.
      */
-    public void testPutLongKey2() throws Exception {
-        doCheckPutLongKey2(STR_ORG_CACHE_NAME);
+    public void testPutLongStringKey2() throws Exception {
+        doCheckPutLongStringKey2(STR_ORG_CACHE_NAME);
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testPutLongKey3() throws Exception {
-        doCheckPutLongKey2(STR_ORG_WITH_FIELDS_CACHE_NAME);
+    public void testPutLongStringKey3() throws Exception {
+        doCheckPutLongStringKey2(STR_ORG_WITH_FIELDS_CACHE_NAME);
     }
 
-    private void doCheckPutLongKey2(String cacheName) {
+    /**
+     * @throws Exception If failed.
+     */
+    private void doCheckPutLongStringKey2(String cacheName) {
         IgniteCache<String, Organization> cache = jcache(0, cacheName);
 
         T2<String, Organization> key2 = new T2<>("12345", new Organization("1"));
@@ -263,6 +376,224 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
         checkPutOps(shouldSucceed, cache, key2);
     }
 
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalValueFail() throws Exception {
+        IgniteCache<BigDecimal, BigDecimal> cache = jcache(0, DEC_CACHE_NAME_FOR_PREC);
+
+        T2<BigDecimal, BigDecimal> val = new T2<>(d(12.36), d(123.45));
+
+        checkPutAll(shouldFail, cache, new T2<>(d(12.34), d(12.34)), val);
+
+        checkPutOps(shouldFail, cache, val);
+
+        checkReplaceOps(shouldFail, cache, val, d(12.34));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalKeyFail() throws Exception {
+        IgniteCache<BigDecimal, BigDecimal> cache = jcache(0, DEC_CACHE_NAME_FOR_PREC);
+
+        T2<BigDecimal, BigDecimal> val =  new T2<>(d(123.45), d(12.34));
+
+        checkPutAll(shouldFail, cache, new T2<>(d(12.35), d(12.34)), val);
+
+        checkPutOps(shouldFail, cache, val);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalKeyFail2() throws Exception {
+        IgniteCache<BigDecimal, Employee> cache = jcache(0, DEC_EMPL_CACHE_NAME_FOR_PREC);
+
+        T2<BigDecimal, Employee> val =  new T2<>(d(123.45), new Employee(d(12.34)));
+
+        checkPutAll(shouldFail, cache, new T2<>(d(12.35), new Employee(d(12.34))), val);
+
+        checkPutOps(shouldFail, cache, val);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalValueFieldFail() throws Exception {
+        IgniteCache<DecOrganization, Employee> cache = jcache(0, OBJ_CACHE_NAME_FOR_PREC);
+
+        T2<DecOrganization, Employee> val = new T2<>(new DecOrganization(d(12.36)), new Employee(d(123.45)));
+
+        checkPutAll(shouldFail, cache, new T2<>(new DecOrganization(d(12.34)), new Employee(d(12.34))), val);
+
+        checkPutOps(shouldFail, cache, val);
+
+        checkReplaceOps(shouldFail, cache, val, new Employee(d(12.34)));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalValueFieldFail2() throws Exception {
+        IgniteCache<BigDecimal, Employee> cache = jcache(0, DEC_EMPL_CACHE_NAME_FOR_PREC);
+
+        T2<BigDecimal, Employee> val = new T2<>(d(12.36), new Employee(d(123.45)));
+
+        checkPutAll(shouldFail, cache, new T2<>(d(12.34), new Employee(d(12.34))), val);
+
+        checkPutOps(shouldFail, cache, val);
+
+        checkReplaceOps(shouldFail, cache, val, new Employee(d(12.34)));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalKeyFieldFail() throws Exception {
+        IgniteCache<DecOrganization, Employee> cache = jcache(0, OBJ_CACHE_NAME_FOR_PREC);
+
+        T2<DecOrganization, Employee> val = new T2<>(new DecOrganization(d(123.45)), new Employee(d(12.34)));
+
+        checkPutAll(shouldFail, cache, new T2<>(new DecOrganization(d(12.35)), new Employee(d(12.34))), val);
+
+        checkPutOps(shouldFail, cache, val);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalValueScaleFail() throws Exception {
+        IgniteCache<BigDecimal, BigDecimal> cache = jcache(0, DEC_CACHE_NAME_FOR_SCALE);
+
+        T2<BigDecimal, BigDecimal> val = new T2<>(d(12.36), d(3.456));
+
+        checkPutAll(shouldFail, cache, new T2<>(d(12.34), d(12.34)), val);
+
+        checkPutOps(shouldFail, cache, val);
+
+        checkReplaceOps(shouldFail, cache, val, d(12.34));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalKeyScaleFail() throws Exception {
+        IgniteCache<BigDecimal, BigDecimal> cache = jcache(0, DEC_CACHE_NAME_FOR_SCALE);
+
+        T2<BigDecimal, BigDecimal> val = new T2<>(d(3.456), d(12.34));
+
+        checkPutAll(shouldFail, cache, new T2<>(d(12.35), d(12.34)), val);
+
+        checkPutOps(shouldFail, cache, val);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalKeyScaleFail2() throws Exception {
+        IgniteCache<BigDecimal, Employee> cache = jcache(0, DEC_EMPL_CACHE_NAME_FOR_SCALE);
+
+        T2<BigDecimal, Employee> val = new T2<>(d(3.456), new Employee(d(12.34)));
+
+        checkPutAll(shouldFail, cache, new T2<>(d(12.35), new Employee(d(12.34))), val);
+
+        checkPutOps(shouldFail, cache, val);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalValueFieldScaleFail() throws Exception {
+        IgniteCache<DecOrganization, Employee> cache = jcache(0, OBJ_CACHE_NAME_FOR_SCALE);
+
+        T2<DecOrganization, Employee> val = new T2<>(new DecOrganization(d(12.36)), new Employee(d(3.456)));
+
+        checkPutAll(shouldFail, cache, new T2<>(new DecOrganization(d(12.34)), new Employee(d(12.34))), val);
+
+        checkPutOps(shouldFail, cache, val);
+
+        checkReplaceOps(shouldFail, cache, val, new Employee(d(12.34)));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalValueFieldScaleFail2() throws Exception {
+        IgniteCache<BigDecimal, Employee> cache = jcache(0, DEC_EMPL_CACHE_NAME_FOR_SCALE);
+
+        T2<BigDecimal, Employee> val = new T2<>(d(12.36), new Employee(d(3.456)));
+
+        checkPutAll(shouldFail, cache, new T2<>(d(12.34), new Employee(d(12.34))), val);
+
+        checkPutOps(shouldFail, cache, val);
+
+        checkReplaceOps(shouldFail, cache, val, new Employee(d(12.34)));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTooLongDecimalKeyFieldScaleFail() throws Exception {
+        IgniteCache<DecOrganization, Employee> cache = jcache(0, OBJ_CACHE_NAME_FOR_SCALE);
+
+        T2<DecOrganization, Employee> val = new T2<>(new DecOrganization(d(3.456)), new Employee(d(12.34)));
+
+        checkPutAll(shouldFail, cache, new T2<>(new DecOrganization(d(12.35)), new Employee(d(12.34))), val);
+
+        checkPutOps(shouldFail, cache, val);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutValidDecimalKeyAndValue() throws Exception {
+        IgniteCache<BigDecimal, BigDecimal> cache = jcache(0, DEC_CACHE_NAME_FOR_SCALE);
+
+        T2<BigDecimal, BigDecimal> val = new T2<>(d(12.37), d(12.34));
+
+        checkPutAll(shouldSucceed, cache, new T2<>(d(12.36), d(12.34)), val);
+
+        checkPutOps(shouldSucceed, cache, val);
+
+        checkReplaceOps(shouldSucceed, cache, val, d(12.34));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutValidDecimalKeyAndValueField() throws Exception {
+        IgniteCache<DecOrganization, Employee> cache = jcache(0, OBJ_CACHE_NAME_FOR_SCALE);
+
+        T2<DecOrganization, Employee> val = new T2<>(new DecOrganization(d(12.37)), new Employee(d(12.34)));
+
+        checkPutAll(shouldSucceed, cache, new T2<>(new DecOrganization(d(12.36)), new Employee(d(12.34))), val);
+
+        checkPutOps(shouldSucceed, cache, val);
+
+        checkReplaceOps(shouldSucceed, cache, val, new Employee(d(12.34)));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutValidDecimalKeyAndValueField2() throws Exception {
+        IgniteCache<BigDecimal, Employee> cache = jcache(0, DEC_EMPL_CACHE_NAME_FOR_SCALE);
+
+        T2<BigDecimal, Employee> val = new T2<>(d(12.37), new Employee(d(12.34)));
+
+        checkPutAll(shouldSucceed, cache, new T2<>(d(12.36), new Employee(d(12.34))), val);
+
+        checkPutOps(shouldSucceed, cache, val);
+
+        checkReplaceOps(shouldSucceed, cache, val, new Employee(d(12.34)));
+    }
+
+    /** */
+    private BigDecimal d(double val) {
+        return BigDecimal.valueOf(val);
+    }
+
     /** */
     private <K, V> void checkReplaceOps(Consumer<Runnable> checker, IgniteCache<K, V> cache, T2<K, V> val, V okVal) {
         K k = val.get1();
@@ -352,9 +683,11 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
         cache.setAtomicityMode(atomicityMode());
         cache.setBackups(1);
         cache.setWriteSynchronizationMode(FULL_SYNC);
-
         cache.setQueryEntities(Collections.singletonList(qryEntity));
 
+        if (TRANSACTIONAL_SNAPSHOT.equals(atomicityMode()))
+            cache.setNearConfiguration(null);
+
         return cache;
     }
 
@@ -393,4 +726,32 @@ public class IgniteCachePartitionedAtomicColumnConstraintsTest extends GridCommo
             this.address = address;
         }
     }
+
+    /** */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class DecOrganization implements Serializable {
+        /** Id. */
+        private final BigDecimal id;
+
+        /**
+         * @param id Id.
+         */
+        private DecOrganization(BigDecimal id) {
+            this.id = id;
+        }
+    }
+
+    /** */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Employee implements Serializable {
+        /** Salary. */
+        private final BigDecimal salary;
+
+        /**
+         * @param salary Salary.
+         */
+        private Employee(BigDecimal salary) {
+            this.salary = salary;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCachePartitionedTransactionalSnapshotColumnConstraintTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCachePartitionedTransactionalSnapshotColumnConstraintTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCachePartitionedTransactionalSnapshotColumnConstraintTest.java
new file mode 100644
index 0000000..a636a3c
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCachePartitionedTransactionalSnapshotColumnConstraintTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.sql;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.jetbrains.annotations.NotNull;
+
+/** */
+public class IgniteCachePartitionedTransactionalSnapshotColumnConstraintTest
+    extends IgniteCachePartitionedAtomicColumnConstraintsTest {
+    /** {@inheritDoc} */
+    @NotNull @Override protected CacheAtomicityMode atomicityMode() {
+        return CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT;
+    }
+
+    /** */
+    @Override public void testPutTooLongStringValueFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongStringKeyFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongStringValueFieldFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongStringKeyFieldFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongStringKeyFail2() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongStringKeyFail3() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyFail2() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueFieldFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueFieldFail2() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyFieldFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueScaleFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyScaleFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyScaleFail2() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueFieldScaleFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueFieldScaleFail2() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyFieldScaleFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCacheReplicatedTransactionalSnapshotColumnConstraintTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCacheReplicatedTransactionalSnapshotColumnConstraintTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCacheReplicatedTransactionalSnapshotColumnConstraintTest.java
new file mode 100644
index 0000000..2a7f6b5
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteCacheReplicatedTransactionalSnapshotColumnConstraintTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.sql;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.jetbrains.annotations.NotNull;
+
+/** */
+public class IgniteCacheReplicatedTransactionalSnapshotColumnConstraintTest
+    extends IgniteCacheReplicatedAtomicColumnConstraintsTest {
+    /** {@inheritDoc} */
+    @NotNull @Override protected CacheAtomicityMode atomicityMode() {
+        return CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT;
+    }
+
+    /** */
+    @Override public void testPutTooLongStringValueFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongStringKeyFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongStringValueFieldFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongStringKeyFieldFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongStringKeyFail2() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongStringKeyFail3() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyFail2() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueFieldFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueFieldFail2() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyFieldFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueScaleFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyScaleFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyScaleFail2() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueFieldScaleFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalValueFieldScaleFail2() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+
+    /** */
+    @Override public void testPutTooLongDecimalKeyFieldScaleFail() {
+        fail("https://issues.apache.org/jira/browse/IGNITE-10066");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteSQLColumnConstraintsTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteSQLColumnConstraintsTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteSQLColumnConstraintsTest.java
index af0b432..8e82063 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteSQLColumnConstraintsTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteSQLColumnConstraintsTest.java
@@ -17,13 +17,16 @@
 
 package org.apache.ignite.internal.processors.sql;
 
+import java.math.BigDecimal;
 import java.util.List;
+import java.util.Objects;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.internal.processors.query.IgniteSQLException;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 
 import static org.apache.ignite.internal.processors.odbc.SqlStateCode.CONSTRAINT_VIOLATION;
+import static org.apache.ignite.internal.processors.odbc.SqlStateCode.INTERNAL_ERROR;
 
 /**
  */
@@ -32,111 +35,330 @@ public class IgniteSQLColumnConstraintsTest extends GridCommonAbstractTest {
     @Override protected void beforeTestsStarted() throws Exception {
         startGrid(0);
 
-        execSQL("CREATE TABLE varchar_table(id INT PRIMARY KEY, str VARCHAR(5))");
+        String mvccQry = mvccEnabled() ? " WITH \"atomicity=transactional_snapshot\"" : "";
+
+        runSQL("CREATE TABLE varchar_table(id INT PRIMARY KEY, str VARCHAR(5))" + mvccQry);
 
         execSQL("INSERT INTO varchar_table VALUES(?, ?)", 1, "12345");
 
-        execSQL("CREATE TABLE char_table(id INT PRIMARY KEY, str CHAR(5))");
+        checkSQLResults("SELECT * FROM varchar_table WHERE id = 1", 1, "12345");
+
+        runSQL("CREATE TABLE decimal_table(id INT PRIMARY KEY, val DECIMAL(4, 2))" + mvccQry);
+
+        execSQL("INSERT INTO decimal_table VALUES(?, ?)", 1, 12.34);
+
+        checkSQLResults("SELECT * FROM decimal_table WHERE id = 1", 1, BigDecimal.valueOf(12.34));
+
+        runSQL("CREATE TABLE char_table(id INT PRIMARY KEY, str CHAR(5))" + mvccQry);
 
         execSQL("INSERT INTO char_table VALUES(?, ?)", 1, "12345");
+
+        checkSQLResults("SELECT * FROM char_table WHERE id = 1", 1, "12345");
+
+        runSQL("CREATE TABLE decimal_table_4(id INT PRIMARY KEY, field DECIMAL(4, 2))" + mvccQry);
+
+        runSQL("CREATE TABLE char_table_2(id INT PRIMARY KEY, field INTEGER)" + mvccQry);
+
+        runSQL("CREATE TABLE decimal_table_2(id INT PRIMARY KEY, field INTEGER)" + mvccQry);
+
+        runSQL("CREATE TABLE char_table_3(id INT PRIMARY KEY, field CHAR(5), field2 INTEGER)" + mvccQry);
+
+        runSQL("CREATE TABLE decimal_table_3(id INT PRIMARY KEY, field DECIMAL(4, 2), field2 INTEGER)" + mvccQry);
+
+        runSQL("CREATE TABLE char_table_4(id INT PRIMARY KEY, field CHAR(5))" + mvccQry);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCreateTableWithTooLongCharDefault() throws Exception {
+        checkSQLThrows("CREATE TABLE too_long_default(id INT PRIMARY KEY, str CHAR(5) DEFAULT '123456')",
+            INTERNAL_ERROR);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCreateTableWithTooLongScaleDecimalDefault() throws Exception {
+        checkSQLThrows("CREATE TABLE too_long_decimal_default_scale(id INT PRIMARY KEY, val DECIMAL(4, 2)" +
+            " DEFAULT 1.345)", INTERNAL_ERROR);
+    }
+
+    public void testCreateTableWithTooLongDecimalDefault() throws Exception {
+        checkSQLThrows("CREATE TABLE too_long_decimal_default(id INT PRIMARY KEY, val DECIMAL(4, 2)" +
+            " DEFAULT 123.45)", INTERNAL_ERROR);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testInsertTooLongDecimal() throws Exception {
+        checkSQLThrows("INSERT INTO decimal_table VALUES(?, ?)", CONSTRAINT_VIOLATION, 2, 123.45);
+
+        assertTrue(execSQL("SELECT * FROM  decimal_table WHERE id = ?", 2).isEmpty());
+
+        checkSQLThrows("UPDATE decimal_table SET val = ? WHERE id = ?", CONSTRAINT_VIOLATION, 123.45, 1);
+
+        checkSQLResults("SELECT * FROM decimal_table WHERE id = 1", 1, BigDecimal.valueOf(12.34));
+
+        checkSQLThrows("MERGE INTO decimal_table(id, val) VALUES(?, ?)", CONSTRAINT_VIOLATION, 1, 123.45);
+
+        checkSQLResults("SELECT * FROM decimal_table WHERE id = 1", 1, BigDecimal.valueOf(12.34));
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testCreateTableWithTooLongDefault() throws Exception {
-        checkSQLThrows("CREATE TABLE too_long_default(id INT PRIMARY KEY, str CHAR(5) DEFAULT '123456')");
+    public void testInsertTooLongScaleDecimal() throws Exception {
+        checkSQLThrows("INSERT INTO decimal_table VALUES(?, ?)", CONSTRAINT_VIOLATION, 3, 1.234);
+
+        assertTrue(execSQL("SELECT * FROM  decimal_table WHERE id = ?", 3).isEmpty());
+
+        checkSQLThrows("UPDATE decimal_table SET val = ? WHERE id = ?", CONSTRAINT_VIOLATION, 1.234, 1);
+
+        checkSQLResults("SELECT * FROM decimal_table WHERE id = 1", 1, BigDecimal.valueOf(12.34));
+
+        checkSQLThrows("MERGE INTO decimal_table(id, val) VALUES(?, ?)", CONSTRAINT_VIOLATION, 1, 1.234);
+
+        checkSQLResults("SELECT * FROM decimal_table WHERE id = 1", 1, BigDecimal.valueOf(12.34));
     }
 
     /**
      * @throws Exception If failed.
      */
     public void testInsertTooLongVarchar() throws Exception {
-        checkSQLThrows("INSERT INTO varchar_table VALUES(?, ?)", 2, "123456");
+        checkSQLThrows("INSERT INTO varchar_table VALUES(?, ?)", CONSTRAINT_VIOLATION, 2, "123456");
+
+        assertTrue(execSQL("SELECT * FROM  varchar_table WHERE id = ?", 2).isEmpty());
+
+        checkSQLThrows("UPDATE varchar_table SET str = ? WHERE id = ?", CONSTRAINT_VIOLATION, "123456", 1);
+
+        checkSQLResults("SELECT * FROM varchar_table WHERE id = 1", 1, "12345");
 
-        checkSQLThrows("UPDATE varchar_table SET str = ? WHERE id = ?", "123456", 1);
+        checkSQLThrows("MERGE INTO varchar_table(id, str) VALUES(?, ?)", CONSTRAINT_VIOLATION, 1, "123456");
 
-        checkSQLThrows("MERGE INTO varchar_table(id, str) VALUES(?, ?)", 1, "123456");
+        checkSQLResults("SELECT * FROM varchar_table WHERE id = 1", 1, "12345");
     }
 
     /**
      * @throws Exception If failed.
      */
     public void testInsertTooLongChar() throws Exception {
-        checkSQLThrows("INSERT INTO char_table VALUES(?, ?)", 2, "123456");
+        checkSQLThrows("INSERT INTO char_table VALUES(?, ?)", CONSTRAINT_VIOLATION, 2, "123456");
+
+        assertTrue(execSQL("SELECT * FROM  char_table WHERE id = ?", 2).isEmpty());
+
+        checkSQLThrows("UPDATE char_table SET str = ? WHERE id = ?", CONSTRAINT_VIOLATION, "123456", 1);
+
+        checkSQLResults("SELECT * FROM char_table WHERE id = 1", 1, "12345");
 
-        checkSQLThrows("UPDATE char_table SET str = ? WHERE id = ?", "123456", 1);
+        checkSQLThrows("MERGE INTO char_table(id, str) VALUES(?, ?)", CONSTRAINT_VIOLATION, 1, "123456");
 
-        checkSQLThrows("MERGE INTO char_table(id, str) VALUES(?, ?)", 1, "123456");
+        checkSQLResults("SELECT * FROM char_table WHERE id = 1", 1, "12345");
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testConstraintsAfterAlterTable() throws Exception {
-        execSQL("CREATE TABLE char_table_2(id INT PRIMARY KEY, field INTEGER)");
-
+    public void testCharConstraintsAfterAlterTable() throws Exception {
         execSQL("ALTER TABLE char_table_2 ADD COLUMN str CHAR(5) NOT NULL");
         
         execSQL("INSERT INTO char_table_2(id, str) VALUES(?, ?)", 1, "1");
 
-        checkSQLThrows("INSERT INTO char_table_2(id, str) VALUES(?, ?)", 2, "123456");
+        checkSQLResults("SELECT * FROM char_table_2 WHERE id = 1", 1, null, "1");
+
+        checkSQLThrows("INSERT INTO char_table_2(id, str) VALUES(?, ?)", CONSTRAINT_VIOLATION, 2, "123456");
+
+        assertTrue(execSQL("SELECT * FROM decimal_table_2 WHERE id = ?", 2).isEmpty());
+
+        checkSQLThrows("UPDATE char_table_2 SET str = ? WHERE id = ?", CONSTRAINT_VIOLATION, "123456", 1);
 
-        checkSQLThrows("UPDATE char_table_2 SET str = ? WHERE id = ?", "123456", 1);
+        checkSQLResults("SELECT * FROM char_table_2 WHERE id = 1", 1, null, "1");
 
-        checkSQLThrows("MERGE INTO char_table_2(id, str) VALUES(?, ?)", 1, "123456");
+        checkSQLThrows("MERGE INTO char_table_2(id, str) VALUES(?, ?)", CONSTRAINT_VIOLATION, 1, "123456");
+
+        checkSQLResults("SELECT * FROM char_table_2 WHERE id = 1", 1, null, "1");
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testDropColumnWithConstraint() throws Exception {
-        execSQL("CREATE TABLE char_table_3(id INT PRIMARY KEY, field CHAR(5), field2 INTEGER)");
+    public void testDecimalConstraintsAfterAlterTable() throws Exception {
+        execSQL("ALTER TABLE decimal_table_2 ADD COLUMN val DECIMAL(4, 2) NOT NULL");
+
+        execSQL("INSERT INTO decimal_table_2(id, val) VALUES(?, ?)", 1, 12.34);
+
+        checkSQLResults("SELECT * FROM decimal_table_2 WHERE id = 1", 1, null, BigDecimal.valueOf(12.34));
+
+        checkSQLThrows("INSERT INTO decimal_table_2(id, val) VALUES(?, ?)", CONSTRAINT_VIOLATION, 2, 1234.56);
+
+        assertTrue(execSQL("SELECT * FROM decimal_table_2 WHERE id = ?", 2).isEmpty());
+
+        checkSQLThrows("UPDATE decimal_table_2 SET val = ? WHERE id = ?", CONSTRAINT_VIOLATION, 1234.56, 1);
+
+        checkSQLResults("SELECT * FROM decimal_table_2 WHERE id = 1", 1, null, BigDecimal.valueOf(12.34));
+
+        checkSQLThrows("MERGE INTO decimal_table_2(id, val) VALUES(?, ?)", CONSTRAINT_VIOLATION, 1, 12345.6);
+
+        checkSQLResults("SELECT * FROM decimal_table_2 WHERE id = 1", 1, null, BigDecimal.valueOf(12.34));
+
+        checkSQLThrows("INSERT INTO decimal_table_2(id, val) VALUES(?, ?)", CONSTRAINT_VIOLATION, 3, 1.234);
+
+        checkSQLResults("SELECT * FROM decimal_table_2 WHERE id = 1", 1, null, BigDecimal.valueOf(12.34));
 
+        checkSQLThrows("UPDATE decimal_table_2 SET val = ? WHERE id = ?", CONSTRAINT_VIOLATION, 1.234, 1);
+
+        checkSQLResults("SELECT * FROM decimal_table_2 WHERE id = 1", 1, null, BigDecimal.valueOf(12.34));
+
+        checkSQLThrows("MERGE INTO decimal_table_2(id, val) VALUES(?, ?)", CONSTRAINT_VIOLATION, 1, 1.234);
+
+        checkSQLResults("SELECT * FROM decimal_table_2 WHERE id = 1", 1, null, BigDecimal.valueOf(12.34));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCharDropColumnWithConstraint() throws Exception {
         execSQL("INSERT INTO char_table_3(id, field, field2) VALUES(?, ?, ?)", 1, "12345", 1);
 
-        checkSQLThrows("INSERT INTO char_table_3(id, field, field2) VALUES(?, ?, ?)", 2, "123456", 1);
+        checkSQLResults("SELECT * FROM char_table_3 WHERE id = 1", 1, "12345", 1);
+
+        checkSQLThrows("INSERT INTO char_table_3(id, field, field2) VALUES(?, ?, ?)", CONSTRAINT_VIOLATION,
+            2, "123456", 1);
+
+        assertTrue(execSQL("SELECT * FROM decimal_table_3 WHERE id = ?", 2).isEmpty());
 
         execSQL("ALTER TABLE char_table_3 DROP COLUMN field");
 
         execSQL("INSERT INTO char_table_3(id, field2) VALUES(?, ?)", 3, 3);
+
+        checkSQLResults("SELECT * FROM char_table_3 WHERE id = 3", 3, 3);
     }
 
-    public void testSqlState() throws Exception {
-        execSQL("CREATE TABLE char_table_4(id INT PRIMARY KEY, field CHAR(5))");
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDecimalDropColumnWithConstraint() throws Exception {
+        execSQL("INSERT INTO decimal_table_3(id, field, field2) VALUES(?, ?, ?)", 1, 12.34, 1);
+
+        checkSQLResults("SELECT * FROM decimal_table_3 WHERE id = 1", 1, BigDecimal.valueOf(12.34), 1);
 
-        IgniteSQLException err = (IgniteSQLException)
-            checkSQLThrows("INSERT INTO char_table_4(id, field) VALUES(?, ?)", 1, "123456");
+        checkSQLThrows("INSERT INTO decimal_table_3(id, field, field2) VALUES(?, ?, ?)", CONSTRAINT_VIOLATION,
+            2, 12.3456, 1);
 
-        assertEquals(err.sqlState(), CONSTRAINT_VIOLATION);
+        assertTrue(execSQL("SELECT * FROM decimal_table_3 WHERE id = ?", 2).isEmpty());
+
+        execSQL("ALTER TABLE decimal_table_3 DROP COLUMN field");
+
+        execSQL("INSERT INTO decimal_table_3(id, field2) VALUES(?, ?)", 3, 3);
+
+        checkSQLResults("SELECT * FROM decimal_table_3 WHERE id = 3", 3, 3);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCharSqlState() throws Exception {
+        checkSQLThrows("INSERT INTO char_table_4(id, field) VALUES(?, ?)", CONSTRAINT_VIOLATION, 1, "123456");
+
+        assertTrue(execSQL("SELECT * FROM decimal_table_4 WHERE id = ?", 1).isEmpty());
 
         execSQL("INSERT INTO char_table_4(id, field) VALUES(?, ?)", 2, "12345");
 
-        err = (IgniteSQLException)
-            checkSQLThrows("UPDATE char_table_4 SET field = ? WHERE id = ?", "123456", 2);
+        checkSQLResults("SELECT * FROM char_table_4 WHERE id = 2", 2, "12345");
+
+        checkSQLThrows("UPDATE char_table_4 SET field = ? WHERE id = ?", CONSTRAINT_VIOLATION, "123456", 2);
 
-        assertEquals(err.sqlState(), CONSTRAINT_VIOLATION);
+        checkSQLResults("SELECT * FROM char_table_4 WHERE id = 2", 2, "12345");
 
-        err = (IgniteSQLException)
-            checkSQLThrows("MERGE INTO char_table_4(id, field) VALUES(?, ?)", 2, "123456");
+        checkSQLThrows("MERGE INTO char_table_4(id, field) VALUES(?, ?)", CONSTRAINT_VIOLATION, 2, "123456");
 
-        assertEquals(err.sqlState(), CONSTRAINT_VIOLATION);
+        checkSQLResults("SELECT * FROM char_table_4 WHERE id = 2", 2, "12345");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDecimalSqlState() throws Exception {
+        checkSQLThrows("INSERT INTO decimal_table_4 VALUES(?, ?)", CONSTRAINT_VIOLATION,
+            1, BigDecimal.valueOf(1234.56));
+
+        assertTrue(execSQL("SELECT * FROM decimal_table_4 WHERE id = ?", 1).isEmpty());
+
+        checkSQLThrows("INSERT INTO decimal_table_4 VALUES(?, ?)", CONSTRAINT_VIOLATION,
+            1, BigDecimal.valueOf(1.345));
+
+        assertTrue(execSQL("SELECT * FROM decimal_table_4 WHERE id = ?", 1).isEmpty());
+
+        execSQL("INSERT INTO decimal_table_4 (id, field) VALUES(?, ?)", 2, 12.34);
+
+        checkSQLResults("SELECT * FROM decimal_table_4 WHERE id = 2", 2, BigDecimal.valueOf(12.34));
+
+        checkSQLThrows("UPDATE decimal_table_4 SET field = ? WHERE id = ?", CONSTRAINT_VIOLATION,
+            BigDecimal.valueOf(1234.56), 2);
+
+        checkSQLResults("SELECT * FROM decimal_table_4 WHERE id = 2", 2, BigDecimal.valueOf(12.34));
+
+        checkSQLThrows("MERGE INTO decimal_table_4(id, field) VALUES(?, ?)", CONSTRAINT_VIOLATION,
+            2, BigDecimal.valueOf(1234.56));
+
+        checkSQLResults("SELECT * FROM decimal_table_4 WHERE id = 2", 2, BigDecimal.valueOf(12.34));
+
+        checkSQLThrows("UPDATE decimal_table_4 SET field = ? WHERE id = ?", CONSTRAINT_VIOLATION,
+            BigDecimal.valueOf(1.345), 2);
+
+        checkSQLResults("SELECT * FROM decimal_table_4 WHERE id = 2", 2, BigDecimal.valueOf(12.34));
+
+        checkSQLThrows("MERGE INTO decimal_table_4(id, field) VALUES(?, ?)", CONSTRAINT_VIOLATION,
+            2, BigDecimal.valueOf(1.345));
+
+        checkSQLResults("SELECT * FROM decimal_table_4 WHERE id = 2", 2, BigDecimal.valueOf(12.34));
     }
 
     /** */
-    private Throwable checkSQLThrows(String sql, Object... args) {
-        return GridTestUtils.assertThrowsWithCause(() -> {
+    protected void checkSQLThrows(String sql, String sqlStateCode, Object... args) {
+        IgniteSQLException err = (IgniteSQLException)GridTestUtils.assertThrowsWithCause(() -> {
             execSQL(sql, args);
 
             return 0;
         }, IgniteSQLException.class);
+
+        assertEquals(err.sqlState(), sqlStateCode);
     }
 
     /** */
-    private List<?> execSQL(String sql, Object... args) {
+    protected List<?> execSQL(String sql, Object... args) {
+        return runSQL(sql, args);
+    }
+
+    /** */
+    protected List<?> runSQL(String sql, Object... args) {
         SqlFieldsQuery qry = new SqlFieldsQuery(sql)
             .setArgs(args);
 
         return grid(0).context().query().querySqlFields(qry, true).getAll();
     }
+
+    /** */
+    protected void checkSQLResults(String sql, Object... args) {
+        List<?> rows = execSQL(sql);
+
+        assertNotNull(rows);
+
+        assertTrue(!rows.isEmpty());
+
+        assertEquals(rows.size(), 1);
+
+        List<?> row = (List<?>)rows.get(0);
+
+        assertEquals(row.size(), args.length);
+
+        for (int i = 0; i < args.length; i++)
+            assertTrue(args[i] + " != " + row.get(i), Objects.equals(args[i], row.get(i)));
+    }
+
+    /** */
+    protected boolean mvccEnabled() {
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteTransactionSQLColumnConstraintTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteTransactionSQLColumnConstraintTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteTransactionSQLColumnConstraintTest.java
new file mode 100644
index 0000000..5239e1f
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/IgniteTransactionSQLColumnConstraintTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.sql;
+
+import java.util.List;
+import org.apache.ignite.internal.processors.query.IgniteSQLException;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/**
+ */
+public class IgniteTransactionSQLColumnConstraintTest extends IgniteSQLColumnConstraintsTest {
+    /** {@inheritDoc} */
+    @Override protected void checkSQLThrows(String sql, String sqlStateCode, Object... args) {
+        runSQL("BEGIN TRANSACTION");
+
+        IgniteSQLException err = (IgniteSQLException)GridTestUtils.assertThrowsWithCause(() -> {
+            runSQL(sql, args);
+
+            return 0;
+        }, IgniteSQLException.class);
+
+        runSQL("ROLLBACK TRANSACTION");
+
+        assertEquals(err.sqlState(), sqlStateCode);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected List<?> execSQL(String sql, Object... args) {
+        runSQL("BEGIN TRANSACTION");
+
+        List<?> res = runSQL(sql, args);
+
+        runSQL("COMMIT TRANSACTION");
+
+        return res;
+    }
+
+    /**
+     * That test is ignored due to drop column(s) operation is unsupported for the MVCC tables.
+     */
+    @Override public void testCharDropColumnWithConstraint() {
+        // No-op.
+    }
+
+    /**
+     * That test is ignored due to drop column(s) operation is unsupported for the MVCC tables.
+     */
+    @Override public void testDecimalDropColumnWithConstraint() {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean mvccEnabled() {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/66755c1a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
index ee82b7a..2fe9323 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
@@ -209,9 +209,12 @@ import org.apache.ignite.internal.processors.query.h2.sql.H2CompareBigQueryTest;
 import org.apache.ignite.internal.processors.query.h2.twostep.InOperationExtractPartitionSelfTest;
 import org.apache.ignite.internal.processors.sql.IgniteCachePartitionedAtomicColumnConstraintsTest;
 import org.apache.ignite.internal.processors.sql.IgniteCachePartitionedTransactionalColumnConstraintsTest;
+import org.apache.ignite.internal.processors.sql.IgniteCachePartitionedTransactionalSnapshotColumnConstraintTest;
 import org.apache.ignite.internal.processors.sql.IgniteCacheReplicatedAtomicColumnConstraintsTest;
 import org.apache.ignite.internal.processors.sql.IgniteCacheReplicatedTransactionalColumnConstraintsTest;
+import org.apache.ignite.internal.processors.sql.IgniteCacheReplicatedTransactionalSnapshotColumnConstraintTest;
 import org.apache.ignite.internal.processors.sql.IgniteSQLColumnConstraintsTest;
+import org.apache.ignite.internal.processors.sql.IgniteTransactionSQLColumnConstraintTest;
 import org.apache.ignite.internal.processors.sql.SqlConnectorConfigurationValidationSelfTest;
 import org.apache.ignite.internal.sql.SqlParserBulkLoadSelfTest;
 import org.apache.ignite.internal.sql.SqlParserCreateIndexSelfTest;
@@ -475,11 +478,14 @@ public class IgniteBinaryCacheQueryTestSuite extends TestSuite {
         suite.addTestSuite(IgniteSqlDefaultValueTest.class);
         suite.addTestSuite(IgniteDecimalSelfTest.class);
         suite.addTestSuite(IgniteSQLColumnConstraintsTest.class);
+        suite.addTestSuite(IgniteTransactionSQLColumnConstraintTest.class);
 
         suite.addTestSuite(IgniteCachePartitionedAtomicColumnConstraintsTest.class);
         suite.addTestSuite(IgniteCachePartitionedTransactionalColumnConstraintsTest.class);
+        suite.addTestSuite(IgniteCachePartitionedTransactionalSnapshotColumnConstraintTest.class);
         suite.addTestSuite(IgniteCacheReplicatedAtomicColumnConstraintsTest.class);
         suite.addTestSuite(IgniteCacheReplicatedTransactionalColumnConstraintsTest.class);
+        suite.addTestSuite(IgniteCacheReplicatedTransactionalSnapshotColumnConstraintTest.class);
 
         // H2 Rows on-heap cache
         suite.addTestSuite(H2RowCacheSelfTest.class);