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

[ignite-3] branch main updated: IGNITE-14692 Validate tuple for STRICT schema (#123)

This is an automated email from the ASF dual-hosted git repository.

tledkov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 1a32ff6  IGNITE-14692 Validate tuple for STRICT schema (#123)
1a32ff6 is described below

commit 1a32ff60032da3df00aed7661ec829c21515cdea
Author: Taras Ledkov <tl...@gridgain.com>
AuthorDate: Thu May 20 16:34:58 2021 +0300

    IGNITE-14692 Validate tuple for STRICT schema (#123)
---
 .../main/java/org/apache/ignite/table/Tuple.java   |   7 +
 .../{Bitmask.java => BitmaskNativeType.java}       |  20 +-
 .../org/apache/ignite/internal/schema/Column.java  |  74 +++++-
 .../org/apache/ignite/internal/schema/Columns.java |  22 +-
 .../apache/ignite/internal/schema/NativeType.java  |  68 ++---
 .../ignite/internal/schema/NativeTypeSpec.java     |  61 +++++
 .../apache/ignite/internal/schema/NativeTypes.java | 189 ++++++++++++++
 .../ignite/internal/schema/NumericNativeType.java  |  88 +++++++
 .../org/apache/ignite/internal/schema/Row.java     |   8 +-
 .../ignite/internal/schema/RowAssembler.java       |  40 +--
 .../ignite/internal/schema/SchemaDescriptor.java   |  28 ++-
 .../ignite/internal/schema/SchemaManager.java      |  28 ++-
 .../ignite/internal/schema/VarlenNativeType.java}  |  40 +--
 .../benchmarks/SerializerBenchmarkTest.java        |   5 +-
 .../apache/ignite/internal/schema/ColumnTest.java  |  13 +-
 .../apache/ignite/internal/schema/ColumnsTest.java | 280 +++++++++++----------
 .../ignite/internal/schema/NativeTypeTest.java     |  65 +++--
 .../ignite/internal/schema/RowAssemblerTest.java   |  79 +++---
 .../org/apache/ignite/internal/schema/RowTest.java |  34 +--
 .../internal/schema/SchemaDescriptorTest.java      |  17 +-
 .../internal/schema/SchemaRegistryImplTest.java    |  73 +++---
 .../apache/ignite/internal/schema/TestUtils.java   |   2 +-
 .../schema/marshaller/JavaSerializerTest.java      |  71 +++---
 .../marshaller/reflection/FieldAccessorTest.java   |  30 +--
 .../ignite/distributed/ITDistributedTableTest.java |  12 +-
 .../ignite/internal/table/AbstractTableView.java   |   2 +-
 .../internal/table/ColumnNotFoundException.java}   |  32 +--
 .../ignite/internal/table/KVBinaryViewImpl.java    |   3 +-
 .../internal/table/SchemaMismatchException.java}   |  32 +--
 .../apache/ignite/internal/table/TableImpl.java    |   2 +-
 .../org/apache/ignite/internal/table/TableRow.java |  15 ++
 .../ignite/internal/table/TupleBuilderImpl.java    |  32 ++-
 .../ignite/internal/table/TupleMarshallerImpl.java |  62 +++--
 .../internal/table/KVViewOperationsTest.java       |  54 ++--
 .../internal/table/StrictSchemaOperationsTest.java | 108 ++++++++
 .../table/TableBinaryViewOperationsTest.java       | 148 ++++++++---
 .../internal/table/impl/TestTupleBuilder.java}     |  25 +-
 37 files changed, 1304 insertions(+), 565 deletions(-)

diff --git a/modules/api/src/main/java/org/apache/ignite/table/Tuple.java b/modules/api/src/main/java/org/apache/ignite/table/Tuple.java
index 7b75ebe..b27a6e4 100644
--- a/modules/api/src/main/java/org/apache/ignite/table/Tuple.java
+++ b/modules/api/src/main/java/org/apache/ignite/table/Tuple.java
@@ -28,6 +28,13 @@ import org.apache.ignite.binary.BinaryObject;
  */
 public interface Tuple {
     /**
+     * Returns {@code true} if this tuple contains a column with the specified name.
+     *
+     * @return {@code true} if this tuple contains a column with the specified name. Otherwise returns {@code false}.
+     */
+    boolean contains(String colName);
+
+    /**
      * Gets column value for given column name.
      *
      * @param colName Column name.
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Bitmask.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BitmaskNativeType.java
similarity index 81%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/Bitmask.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/BitmaskNativeType.java
index 172b195..ee6813b 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Bitmask.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BitmaskNativeType.java
@@ -23,26 +23,16 @@ import org.apache.ignite.internal.tostring.S;
  * A fixed-sized type representing a bitmask of <code>n</code> bits. The actual size of a bitmask will round up
  * to the smallest number of bytes required to store <code>n</code> bits.
  */
-public class Bitmask extends NativeType {
+public class BitmaskNativeType extends NativeType {
     /** */
     private final int bits;
 
     /**
-     * Factory method for creating the bitmask type.
-     *
-     * @param nBits Maximum number of bits in the bitmask.
-     * @return Bitmask type.
-     */
-    public static Bitmask of(int nBits) {
-        return new Bitmask(nBits);
-    }
-
-    /**
      * Creates a bitmask type of size <code>bits</code>. In row will round up to the closest full byte.
      *
      * @param bits The number of bits in the bitmask.
      */
-    protected Bitmask(int bits) {
+    protected BitmaskNativeType(int bits) {
         super(NativeTypeSpec.BITMASK, (bits + 7) / 8);
 
         this.bits = bits;
@@ -63,7 +53,7 @@ public class Bitmask extends NativeType {
         if (o == null || getClass() != o.getClass())
             return false;
 
-        Bitmask that = (Bitmask)o;
+        BitmaskNativeType that = (BitmaskNativeType)o;
 
         return bits == that.bits;
     }
@@ -79,7 +69,7 @@ public class Bitmask extends NativeType {
 
         if (res == 0) {
             // The passed in object is also a bitmask, compare the number of bits.
-            Bitmask that = (Bitmask)o;
+            BitmaskNativeType that = (BitmaskNativeType)o;
 
             return Integer.compare(bits, that.bits);
         }
@@ -89,6 +79,6 @@ public class Bitmask extends NativeType {
 
     /** {@inheritDoc} */
     @Override public String toString() {
-        return S.toString(Bitmask.class.getSimpleName(), "bits", bits, "typeSpec", spec(), "len", length());
+        return S.toString(BitmaskNativeType.class.getSimpleName(), "bits", bits, "typeSpec", spec(), "len", sizeInBytes());
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Column.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Column.java
index 12eaa9c..19284e0 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Column.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Column.java
@@ -17,7 +17,9 @@
 
 package org.apache.ignite.internal.schema;
 
+import java.util.function.Supplier;
 import org.apache.ignite.internal.tostring.S;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Column description for a type schema. Column contains a column name, a column type and a nullability flag.
@@ -26,6 +28,9 @@ import org.apache.ignite.internal.tostring.S;
  * flag is not taken into account when columns are compared.
  */
 public class Column implements Comparable<Column> {
+    /** {@code Null} value supplier. */
+    private static final Supplier<Object> NULL_DEFAULT_SUPPLIER = () -> null;
+
     /** Absolute index in schema descriptor. */
     private final int schemaIndex;
 
@@ -45,6 +50,11 @@ public class Column implements Comparable<Column> {
     private final boolean nullable;
 
     /**
+     * Default value supplier.
+     */
+    private final Supplier<Object> defValSup;
+
+    /**
      * @param name Column name.
      * @param type An instance of column data type.
      * @param nullable If {@code false}, null values will not be allowed for this column.
@@ -54,7 +64,22 @@ public class Column implements Comparable<Column> {
         NativeType type,
         boolean nullable
     ) {
-        this(-1, name, type, nullable);
+        this(-1, name, type, nullable, NULL_DEFAULT_SUPPLIER);
+    }
+
+    /**
+     * @param name Column name.
+     * @param type An instance of column data type.
+     * @param nullable If {@code false}, null values will not be allowed for this column.
+     * @param defValSup Default value supplier.
+     */
+    public Column(
+        String name,
+        NativeType type,
+        boolean nullable,
+        @NotNull Supplier<Object> defValSup
+    ) {
+        this(-1, name, type, nullable, defValSup);
     }
 
     /**
@@ -67,12 +92,14 @@ public class Column implements Comparable<Column> {
         int schemaIndex,
         String name,
         NativeType type,
-        boolean nullable
+        boolean nullable,
+        @NotNull Supplier<Object> defValSup
     ) {
         this.schemaIndex = schemaIndex;
         this.name = name;
         this.type = type;
         this.nullable = nullable;
+        this.defValSup = defValSup;
     }
 
     /**
@@ -103,6 +130,19 @@ public class Column implements Comparable<Column> {
         return nullable;
     }
 
+    /**
+     * Get default value for the column.
+     *
+     * @return Default value.
+     */
+    public Object defaultValue() {
+        Object val = defValSup.get();
+
+        assert nullable || val != null : "Null value is not accepted for not nullable column: [col=" + this + ']';
+
+        return val;
+    }
+
     /** {@inheritDoc} */
     @Override public boolean equals(Object o) {
         if (this == o)
@@ -132,6 +172,36 @@ public class Column implements Comparable<Column> {
         return name.compareTo(o.name);
     }
 
+    /**
+     * Validate the object by column's constraint.
+     */
+    public void validate(Object val) {
+        if (val == null && !nullable) {
+            throw new IllegalArgumentException("Failed to set column (null was passed, but column is not nullable): " +
+                "[col=" + this + ']');
+        }
+
+        NativeType objType = NativeTypes.fromObject(val);
+
+        if (objType != null && type.mismatch(objType)) {
+            throw new InvalidTypeException("Column's type mismatch [" +
+                "column=" + this +
+                ", expectedType=" + type +
+                ", actualType=" + objType +
+                ", val=" + val + ']');
+        }
+    }
+
+    /**
+     * Copy column with new schema index.
+     *
+     * @param schemaIndex Column index in the schema.
+     * @return Column.
+     */
+    public Column copy(int schemaIndex) {
+        return new Column(schemaIndex, name, type, nullable, defValSup);
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(Column.class, this);
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java
index 38b62e5..0d65f46 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java
@@ -195,7 +195,7 @@ public class Columns {
         for (int i = 0; i < cp.length; i++) {
             Column c = cp[i];
 
-            cp[i] = new Column(schemaBaseIdx + i, c.name(), c.type(), c.nullable());
+            cp[i] = c.copy(schemaBaseIdx + i);
         }
 
         return cp;
@@ -287,7 +287,7 @@ public class Columns {
                     ", mask=" + mask +
                     ", cols" + Arrays.toString(cols) + ']';
 
-                size += cols[idx].type().length();
+                size += cols[idx].type().sizeInBytes();
             }
         }
 
@@ -310,6 +310,24 @@ public class Columns {
     }
 
     /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        Columns columns = (Columns)o;
+
+        return Arrays.equals(cols, columns.cols);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        return Arrays.hashCode(cols);
+    }
+
+    /** {@inheritDoc} */
     @Override public String toString() {
        return S.arrayToString(cols);
     }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeType.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeType.java
index d8d956a..d22526c 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeType.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeType.java
@@ -18,59 +18,33 @@
 package org.apache.ignite.internal.schema;
 
 import org.apache.ignite.internal.tostring.S;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * A thin wrapper over {@link NativeTypeSpec} to instantiate parameterized constrained types.
  */
 public class NativeType implements Comparable<NativeType> {
     /** */
-    public static final NativeType BYTE = new NativeType(NativeTypeSpec.BYTE, 1);
-
-    /** */
-    public static final NativeType SHORT = new NativeType(NativeTypeSpec.SHORT, 2);
-
-    /** */
-    public static final NativeType INTEGER = new NativeType(NativeTypeSpec.INTEGER, 4);
-
-    /** */
-    public static final NativeType LONG = new NativeType(NativeTypeSpec.LONG, 8);
-
-    /** */
-    public static final NativeType FLOAT = new NativeType(NativeTypeSpec.FLOAT, 4);
-
-    /** */
-    public static final NativeType DOUBLE = new NativeType(NativeTypeSpec.DOUBLE, 8);
-
-    /** */
-    public static final NativeType UUID = new NativeType(NativeTypeSpec.UUID, 16);
-
-    /** */
-    public static final NativeType STRING = new NativeType(NativeTypeSpec.STRING);
-
-    /** */
-    public static final NativeType BYTES = new NativeType(NativeTypeSpec.BYTES);
-
-    /** */
     private final NativeTypeSpec typeSpec;
 
-    /** Type length. */
-    private final int len;
+    /** Type size in bytes. */
+    private final int size;
 
     /**
      * Constructor for fixed-length types.
      *
      * @param typeSpec Type spec.
-     * @param len Type length.
+     * @param size Type size in bytes.
      */
-    protected NativeType(NativeTypeSpec typeSpec, int len) {
+    protected NativeType(NativeTypeSpec typeSpec, int size) {
         if (!typeSpec.fixedLength())
             throw new IllegalArgumentException("Size must be provided only for fixed-length types: " + typeSpec);
 
-        if (len <= 0)
-            throw new IllegalArgumentException("Size must be positive [typeSpec=" + typeSpec + ", size=" + len + ']');
+        if (size <= 0)
+            throw new IllegalArgumentException("Size must be positive [typeSpec=" + typeSpec + ", size=" + size + ']');
 
         this.typeSpec = typeSpec;
-        this.len = len;
+        this.size = size;
     }
 
     /**
@@ -84,17 +58,17 @@ public class NativeType implements Comparable<NativeType> {
                 "length-aware constructor: " + typeSpec);
 
         this.typeSpec = typeSpec;
-        this.len = 0;
+        this.size = 0;
     }
 
     /**
-     * @return Length of the type if it is a fixlen type. For varlen types the return value is undefined, so the user
+     * @return Size in bytes of the type if it is a fixlen type. For varlen types the return value is undefined, so the user
      * should explicitly check {@code spec().fixedLength()} before using this method.
      *
      * @see NativeTypeSpec#fixedLength()
      */
-    public int length() {
-        return len;
+    public int sizeInBytes() {
+        return size;
     }
 
     /**
@@ -104,6 +78,11 @@ public class NativeType implements Comparable<NativeType> {
         return typeSpec;
     }
 
+    /** */
+    public boolean mismatch(@NotNull NativeType type) {
+        return this != type && typeSpec != type.typeSpec;
+    }
+
     /** {@inheritDoc} */
     @Override public boolean equals(Object o) {
         if (this == o)
@@ -114,14 +93,14 @@ public class NativeType implements Comparable<NativeType> {
 
         NativeType that = (NativeType)o;
 
-        return len == that.len && typeSpec == that.typeSpec;
+        return size == that.size && typeSpec == that.typeSpec;
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
         int res = typeSpec.hashCode();
 
-        res = 31 * res + len;
+        res = 31 * res + size;
 
         return res;
     }
@@ -129,14 +108,14 @@ public class NativeType implements Comparable<NativeType> {
     /** {@inheritDoc} */
     @Override public int compareTo(NativeType o) {
         // Fixed-sized types go first.
-        if (len <= 0 && o.len > 0)
+        if (size <= 0 && o.size > 0)
             return 1;
 
-        if (len > 0 && o.len <= 0)
+        if (size > 0 && o.size <= 0)
             return -1;
 
         // Either size is -1 for both, or positive for both. Compare sizes, then description.
-        int cmp = Integer.compare(len, o.len);
+        int cmp = Integer.compare(size, o.size);
 
         if (cmp != 0)
             return cmp;
@@ -148,7 +127,8 @@ public class NativeType implements Comparable<NativeType> {
     @Override public String toString() {
         return S.toString(NativeType.class.getSimpleName(),
             "name", typeSpec.name(),
-            "len", len,
+            "sizeInBytes", size,
             "fixed", typeSpec.fixedLength());
     }
+
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypeSpec.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypeSpec.java
index cc470aa..dd9299c 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypeSpec.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypeSpec.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.schema;
 
+import java.util.BitSet;
 import org.apache.ignite.internal.tostring.S;
 
 /**
@@ -89,6 +90,16 @@ public enum NativeTypeSpec {
     },
 
     /**
+     * Native type representing an eight-bytes floating-point value.
+     */
+    DECIMAL("decimal", false) {
+        /** {@inheritDoc} */
+        @Override public Object objectValue(Row tup, int colIdx) {
+            return tup.decimalValue(colIdx);
+        }
+    },
+
+    /**
      * Native type representing a UUID.
      */
     UUID("uuid", true) {
@@ -173,6 +184,56 @@ public enum NativeTypeSpec {
      */
     public abstract Object objectValue(Row row, int colIdx) throws InvalidTypeException;
 
+    /** */
+    public static NativeTypeSpec fromClass(Class<?> cls) {
+        assert cls != null;
+
+        // Primitives.
+        if (cls == byte.class)
+            return NativeTypeSpec.BYTE;
+        else if (cls == short.class)
+            return NativeTypeSpec.SHORT;
+        else if (cls == int.class)
+            return NativeTypeSpec.INTEGER;
+        else if (cls == long.class)
+            return NativeTypeSpec.LONG;
+        else if (cls == float.class)
+            return NativeTypeSpec.FLOAT;
+        else if (cls == double.class)
+            return NativeTypeSpec.DOUBLE;
+
+        // Boxed primitives.
+        else if (cls == Byte.class)
+            return NativeTypeSpec.BYTE;
+        else if (cls == Short.class)
+            return NativeTypeSpec.SHORT;
+        else if (cls == Integer.class)
+            return NativeTypeSpec.INTEGER;
+        else if (cls == Long.class)
+            return NativeTypeSpec.LONG;
+        else if (cls == Float.class)
+            return NativeTypeSpec.FLOAT;
+        else if (cls == Double.class)
+            return NativeTypeSpec.DOUBLE;
+
+        // Other types
+        else if (cls == byte[].class)
+            return NativeTypeSpec.BYTES;
+        else if (cls == String.class)
+            return NativeTypeSpec.STRING;
+        else if (cls == java.util.UUID.class)
+            return NativeTypeSpec.UUID;
+        else if (cls == BitSet.class)
+            return NativeTypeSpec.BITMASK;
+
+        return null;
+    }
+
+    /** */
+    public static NativeTypeSpec fromObject(Object val) {
+        return val != null ? fromClass(val.getClass()) : null;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(NativeTypeSpec.class.getSimpleName(),
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java
new file mode 100644
index 0000000..e605748
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java
@@ -0,0 +1,189 @@
+/*
+ * 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.schema;
+
+import java.util.BitSet;
+import org.apache.ignite.schema.ColumnType;
+
+/**
+ * A thin wrapper over {@link NativeTypeSpec} to instantiate parameterized constrained types.
+ */
+public class NativeTypes {
+    /** */
+    public static final NativeType BYTE = new NativeType(NativeTypeSpec.BYTE, 1);
+
+    /** */
+    public static final NativeType SHORT = new NativeType(NativeTypeSpec.SHORT, 2);
+
+    /** */
+    public static final NativeType INTEGER = new NativeType(NativeTypeSpec.INTEGER, 4);
+
+    /** */
+    public static final NativeType LONG = new NativeType(NativeTypeSpec.LONG, 8);
+
+    /** */
+    public static final NativeType FLOAT = new NativeType(NativeTypeSpec.FLOAT, 4);
+
+    /** */
+    public static final NativeType DOUBLE = new NativeType(NativeTypeSpec.DOUBLE, 8);
+
+    /** */
+    public static final NativeType UUID = new NativeType(NativeTypeSpec.UUID, 16);
+
+    /** */
+    public static final NativeType STRING = new VarlenNativeType(NativeTypeSpec.STRING, Integer.MAX_VALUE);
+
+    /** */
+    public static final NativeType BYTES = new VarlenNativeType(NativeTypeSpec.BYTES, Integer.MAX_VALUE);
+
+    /** Don't allow to create an instance. */
+    private NativeTypes() {
+    }
+
+    /**
+     * Creates a bitmask type of size <code>bits</code>. In row will round up to the closest full byte.
+     *
+     * @param bits The number of bits in the bitmask.
+     */
+    public static NativeType bitmaskOf(int bits) {
+        return new BitmaskNativeType(bits);
+    }
+
+    /**
+     * Creates a STRING type with maximal length is <code>len</code>.
+     *
+     * @param len Maximum length of the string.
+     */
+    public static NativeType stringOf(int len) {
+        return new VarlenNativeType(NativeTypeSpec.STRING, len);
+    }
+
+    /**
+     * Creates a BYTES type with maximal length is <code>len</code>.
+     *
+     * @param len Maximum length of the byte array.
+     */
+    public static NativeType blobOf(int len) {
+        return new VarlenNativeType(NativeTypeSpec.BYTES, len);
+    }
+
+    /**
+     * Return the native type for specified object.
+     *
+     * @return {@code null} for {@code null} value. Otherwise returns NativeType according to the value's type.
+     */
+    public static NativeType fromObject(Object val) {
+        NativeTypeSpec spec = NativeTypeSpec.fromObject(val);
+
+        if (spec == null)
+            return null;
+
+        switch (spec) {
+            case BYTE:
+                return BYTE;
+
+            case SHORT:
+                return SHORT;
+
+            case INTEGER:
+                return INTEGER;
+
+            case LONG:
+                return LONG;
+
+            case FLOAT:
+                return FLOAT;
+
+            case DOUBLE:
+                return DOUBLE;
+
+            case UUID:
+                return UUID;
+
+            case STRING:
+                return NativeTypes.stringOf(((CharSequence)val).length());
+
+            case BYTES:
+                return NativeTypes.blobOf(((byte[])val).length);
+
+            case BITMASK:
+                return NativeTypes.bitmaskOf(((BitSet)val).length());
+
+            default:
+                assert false : "Unexpected type: " + spec;
+
+                return null;
+        }
+    }
+
+    /** */
+    public static NativeType from(ColumnType type) {
+        switch (type.typeSpec()) {
+            case INT8:
+                return BYTE;
+
+            case INT16:
+                return SHORT;
+
+            case INT32:
+                return INTEGER;
+
+            case INT64:
+                return LONG;
+
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+                throw new UnsupportedOperationException("Unsigned types are not supported yet.");
+
+            case FLOAT:
+                return FLOAT;
+
+            case DOUBLE:
+                return DOUBLE;
+
+            case DECIMAL:
+                ColumnType.NumericColumnType numType = (ColumnType.NumericColumnType)type;
+                return new NumericNativeType(numType.precision(), numType.scale());
+
+            case UUID:
+                return UUID;
+
+            case BITMASK:
+                return new BitmaskNativeType(((ColumnType.VarLenColumnType)type).length());
+
+            case STRING:
+                return new VarlenNativeType(
+                    NativeTypeSpec.STRING,
+                    ((ColumnType.VarLenColumnType)type).length() > 0 ?
+                        ((ColumnType.VarLenColumnType)type).length() : Integer.MAX_VALUE
+                );
+
+            case BLOB:
+                return new VarlenNativeType(
+                    NativeTypeSpec.BYTES,
+                    ((ColumnType.VarLenColumnType)type).length() > 0 ?
+                        ((ColumnType.VarLenColumnType)type).length() : Integer.MAX_VALUE
+                );
+
+            default:
+                throw new InvalidTypeException("Unexpected type " + type);
+        }
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NumericNativeType.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NumericNativeType.java
new file mode 100644
index 0000000..97ccc97
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NumericNativeType.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.schema;
+
+import java.util.Objects;
+import org.apache.ignite.internal.tostring.S;
+
+/**
+ * Numeric column type.
+ */
+public class NumericNativeType extends NativeType {
+    /** Precision. */
+    private final int precision;
+
+    /** Scale. */
+    private final int scale;
+
+    /** Constructor. */
+    NumericNativeType(int precision, int scale) {
+        super(NativeTypeSpec.DECIMAL);
+
+        this.precision = precision;
+        this.scale = scale;
+    }
+
+    /**
+     * @return Precision.
+     */
+    public int precision() {
+        return precision;
+    }
+
+    /**
+     * @return Scale.
+     */
+    public int scale() {
+        return scale;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean mismatch(NativeType type) {
+        return super.mismatch(type)
+            || precision < ((NumericNativeType)type).precision
+            || scale < ((NumericNativeType)type).scale;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        if (!super.equals(o))
+            return false;
+
+        NumericNativeType type = (NumericNativeType)o;
+
+        return precision == type.precision &&
+            scale == type.scale;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        return Objects.hash(super.hashCode(), precision, scale);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(NumericNativeType.class.getSimpleName(), "name", spec(), "precision", precision, "scale", scale);
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
index ce51467..9d967d3 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.schema;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.math.BigDecimal;
 import java.nio.ByteBuffer;
 import java.util.BitSet;
 import java.util.UUID;
@@ -228,6 +229,11 @@ public class Row implements BinaryRow {
         return off < 0 ? null : readDouble(offset(off));
     }
 
+    public BigDecimal decimalValue(int idx) {
+        // TODO: IGNITE-13668 decimal support
+        return null;
+    }
+
     /**
      * Reads value for specified column.
      *
@@ -372,7 +378,7 @@ public class Row implements BinaryRow {
     private int columnLength(int colIdx) {
         Column col = schema.column(colIdx);
 
-        return col.type().length();
+        return col.type().sizeInBytes();
     }
 
     /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java
index 9325566..367d8d0 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java
@@ -145,7 +145,7 @@ public class RowAssembler {
             varlenTableChunkSize(nonNullVarlenCols);
 
         for (int i = 0; i < cols.numberOfFixsizeColumns(); i++)
-            size += cols.column(i).type().length();
+            size += cols.column(i).type().sizeInBytes();
 
         return size + nonNullVarlenSize;
     }
@@ -209,11 +209,11 @@ public class RowAssembler {
      * @param val Column value.
      */
     public void appendByte(byte val) {
-        checkType(NativeType.BYTE);
+        checkType(NativeTypes.BYTE);
 
         buf.put(curOff, val);
 
-        shiftColumn(NativeType.BYTE);
+        shiftColumn(NativeTypes.BYTE);
     }
 
     /**
@@ -222,11 +222,11 @@ public class RowAssembler {
      * @param val Column value.
      */
     public void appendShort(short val) {
-        checkType(NativeType.SHORT);
+        checkType(NativeTypes.SHORT);
 
         buf.putShort(curOff, val);
 
-        shiftColumn(NativeType.SHORT);
+        shiftColumn(NativeTypes.SHORT);
     }
 
     /**
@@ -235,11 +235,11 @@ public class RowAssembler {
      * @param val Column value.
      */
     public void appendInt(int val) {
-        checkType(NativeType.INTEGER);
+        checkType(NativeTypes.INTEGER);
 
         buf.putInt(curOff, val);
 
-        shiftColumn(NativeType.INTEGER);
+        shiftColumn(NativeTypes.INTEGER);
     }
 
     /**
@@ -248,11 +248,11 @@ public class RowAssembler {
      * @param val Column value.
      */
     public void appendLong(long val) {
-        checkType(NativeType.LONG);
+        checkType(NativeTypes.LONG);
 
         buf.putLong(curOff, val);
 
-        shiftColumn(NativeType.LONG);
+        shiftColumn(NativeTypes.LONG);
     }
 
     /**
@@ -261,11 +261,11 @@ public class RowAssembler {
      * @param val Column value.
      */
     public void appendFloat(float val) {
-        checkType(NativeType.FLOAT);
+        checkType(NativeTypes.FLOAT);
 
         buf.putFloat(curOff, val);
 
-        shiftColumn(NativeType.FLOAT);
+        shiftColumn(NativeTypes.FLOAT);
     }
 
     /**
@@ -274,11 +274,11 @@ public class RowAssembler {
      * @param val Column value.
      */
     public void appendDouble(double val) {
-        checkType(NativeType.DOUBLE);
+        checkType(NativeTypes.DOUBLE);
 
         buf.putDouble(curOff, val);
 
-        shiftColumn(NativeType.DOUBLE);
+        shiftColumn(NativeTypes.DOUBLE);
     }
 
     /**
@@ -287,12 +287,12 @@ public class RowAssembler {
      * @param uuid Column value.
      */
     public void appendUuid(UUID uuid) {
-        checkType(NativeType.UUID);
+        checkType(NativeTypes.UUID);
 
         buf.putLong(curOff, uuid.getLeastSignificantBits());
         buf.putLong(curOff + 8, uuid.getMostSignificantBits());
 
-        shiftColumn(NativeType.UUID);
+        shiftColumn(NativeTypes.UUID);
     }
 
     /**
@@ -301,7 +301,7 @@ public class RowAssembler {
      * @param val Column value.
      */
     public void appendString(String val) {
-        checkType(NativeType.STRING);
+        checkType(NativeTypes.STRING);
 
         try {
             int written = buf.putString(curOff, val, encoder());
@@ -321,7 +321,7 @@ public class RowAssembler {
      * @param val Column value.
      */
     public void appendBytes(byte[] val) {
-        checkType(NativeType.BYTES);
+        checkType(NativeTypes.BYTES);
 
         buf.putBytes(curOff, val);
 
@@ -340,7 +340,7 @@ public class RowAssembler {
 
         checkType(NativeTypeSpec.BITMASK);
 
-        Bitmask maskType = (Bitmask)col.type();
+        BitmaskNativeType maskType = (BitmaskNativeType)col.type();
 
         if (bitSet.length() > maskType.bits())
             throw new IllegalArgumentException("Failed to set bitmask for column '" + col.name() + "' " +
@@ -350,7 +350,7 @@ public class RowAssembler {
 
         buf.putBytes(curOff, arr);
 
-        for (int i = 0; i < maskType.length() - arr.length; i++)
+        for (int i = 0; i < maskType.sizeInBytes() - arr.length; i++)
             buf.put(curOff + arr.length + i, (byte)0);
 
         shiftColumn(maskType);
@@ -442,7 +442,7 @@ public class RowAssembler {
     private void shiftColumn(NativeType type) {
         assert type.spec().fixedLength() : "Varlen types should provide field length to shift column: " + type;
 
-        shiftColumn(type.length(), false);
+        shiftColumn(type.sizeInBytes(), false);
     }
 
     /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaDescriptor.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaDescriptor.java
index 8e1e91d..fe1a881 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaDescriptor.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaDescriptor.java
@@ -18,8 +18,10 @@
 package org.apache.ignite.internal.schema;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.UUID;
 import org.apache.ignite.internal.tostring.S;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -28,6 +30,9 @@ import org.jetbrains.annotations.Nullable;
  * Full schema descriptor containing key columns chunk, value columns chunk, and schema version.
  */
 public class SchemaDescriptor {
+    /** Table identifier.*/
+    private final UUID tableId;
+
     /** Schema version. Incremented on each schema modification. */
     private final int ver;
 
@@ -45,8 +50,8 @@ public class SchemaDescriptor {
      * @param keyCols Key columns.
      * @param valCols Value columns.
      */
-    public SchemaDescriptor(int ver, Column[] keyCols, Column[] valCols) {
-        this(ver, keyCols, null, valCols);
+    public SchemaDescriptor(UUID tableId, int ver, Column[] keyCols, Column[] valCols) {
+        this(tableId, ver, keyCols, null, valCols);
     }
 
     /**
@@ -55,10 +60,11 @@ public class SchemaDescriptor {
      * @param affCols Affinity column names.
      * @param valCols Value columns.
      */
-    public SchemaDescriptor(int ver, Column[] keyCols, @Nullable String[] affCols, Column[] valCols) {
+    public SchemaDescriptor(UUID tableId, int ver, Column[] keyCols, @Nullable String[] affCols, Column[] valCols) {
         assert keyCols.length > 0 : "No key columns are conigured.";
         assert valCols.length > 0 : "No value columns are conigured.";
 
+        this.tableId = tableId;
         this.ver = ver;
         this.keyCols = new Columns(0, keyCols);
         this.valCols = new Columns(keyCols.length, valCols);
@@ -72,6 +78,13 @@ public class SchemaDescriptor {
     }
 
     /**
+     * @return Table identifier.
+     */
+    public UUID tableId() {
+        return tableId;
+    }
+
+    /**
      * @return Schema version.
      */
     public int version() {
@@ -95,6 +108,15 @@ public class SchemaDescriptor {
     }
 
     /**
+     * Gets columns names.
+     *
+     * @return Columns names.
+     */
+    public Collection<String> columnNames() {
+        return colMap.keySet();
+    }
+
+    /**
      * @return Key columns chunk.
      */
     public Columns keyColumns() {
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java
index c4d84fb..58361d3 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaManager.java
@@ -88,7 +88,7 @@ public class SchemaManager extends Producer<SchemaEvent, SchemaEventParameters>
     /** Vault manager. */
     private final VaultManager vaultMgr;
 
-    /** Schema registries. */
+    /** Schema registries (tableId -> SchemaRegistry). */
     private final Map<UUID, SchemaRegistryImpl> schemaRegs = new ConcurrentHashMap<>();
 
     /**
@@ -180,7 +180,7 @@ public class SchemaManager extends Producer<SchemaEvent, SchemaEventParameters>
                 final ByteArray lastVerKey = new ByteArray(INTERNAL_PREFIX + tblId);
                 final ByteArray schemaKey = new ByteArray(INTERNAL_PREFIX + tblId + INTERNAL_VER_SUFFIX + schemaVer);
 
-                final SchemaDescriptor desc = createSchemaDescriptor(schemaVer, tblConfig);
+                final SchemaDescriptor desc = createSchemaDescriptor(tblId, schemaVer, tblConfig);
 
                 return metaStorageMgr.invoke(
                     Conditions.value(lastVerKey).eq(entry.value()), // Won't to rewrite if the version goes ahead.
@@ -213,11 +213,12 @@ public class SchemaManager extends Producer<SchemaEvent, SchemaEventParameters>
     /**
      * Creates schema descriptor from configuration.
      *
+     * @param tblId Table ID.
      * @param ver Schema version.
      * @param tblConfig Table config.
      * @return Schema descriptor.
      */
-    private SchemaDescriptor createSchemaDescriptor(int ver, TableConfiguration tblConfig) {
+    private SchemaDescriptor createSchemaDescriptor(UUID tblId, int ver, TableConfiguration tblConfig) {
         final TableIndexConfiguration pkCfg = tblConfig.indices().get(PrimaryIndex.PRIMARY_KEY_INDEX_NAME);
 
         assert pkCfg != null;
@@ -235,6 +236,7 @@ public class SchemaManager extends Producer<SchemaEvent, SchemaEventParameters>
             .forEach(c -> (keyColNames.contains(c.name()) ? keyCols : valCols).add(c));
 
         return new SchemaDescriptor(
+            tblId,
             ver,
             keyCols.toArray(Column[]::new),
             pkCfg.affinityColumns().value(),
@@ -253,25 +255,25 @@ public class SchemaManager extends Producer<SchemaEvent, SchemaEventParameters>
     private NativeType createType(ColumnTypeView type) {
         switch (type.type().toLowerCase()) {
             case "byte":
-                return NativeType.BYTE;
+                return NativeTypes.BYTE;
             case "short":
-                return NativeType.SHORT;
+                return NativeTypes.SHORT;
             case "int":
-                return NativeType.INTEGER;
+                return NativeTypes.INTEGER;
             case "long":
-                return NativeType.LONG;
+                return NativeTypes.LONG;
             case "float":
-                return NativeType.FLOAT;
+                return NativeTypes.FLOAT;
             case "double":
-                return NativeType.DOUBLE;
+                return NativeTypes.DOUBLE;
             case "uuid":
-                return NativeType.UUID;
+                return NativeTypes.UUID;
             case "bitmask":
-                return Bitmask.of(type.length());
+                return NativeTypes.bitmaskOf(type.length());
             case "string":
-                return NativeType.STRING;
+                return NativeTypes.stringOf(type.length());
             case "bytes":
-                return NativeType.BYTES;
+                return NativeTypes.blobOf(type.length());
 
             default:
                 throw new IllegalStateException("Unsupported column type: " + type.type());
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/VarlenNativeType.java
similarity index 55%
copy from modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
copy to modules/schema/src/main/java/org/apache/ignite/internal/schema/VarlenNativeType.java
index ddc5b74..867ec04 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/VarlenNativeType.java
@@ -17,32 +17,32 @@
 
 package org.apache.ignite.internal.schema;
 
-import java.util.Arrays;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.apache.ignite.internal.tostring.S;
 
 /**
- *
+ * Variable-length native type.
  */
-public class ColumnTest {
+public class VarlenNativeType extends NativeType {
+    /** Length of the type. */
+    private final int len;
+
     /**
-     *
+     * @param typeSpec Type spec.
+     * @param len Type length.
      */
-    @Test
-    public void testCompareColumns() {
-        Column[] cols = new Column[] {
-            new Column("C", NativeType.BYTES, false),
-            new Column("B", NativeType.INTEGER, false),
-            new Column("AD", NativeType.STRING, false),
-            new Column("AA", NativeType.STRING, false),
-        };
+    protected VarlenNativeType(NativeTypeSpec typeSpec, int len) {
+        super(typeSpec);
 
-        Arrays.sort(cols);
+        this.len = len;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean mismatch(NativeType type) {
+        return super.mismatch(type) || len < ((VarlenNativeType)type).len;
+    }
 
-        assertEquals("B", cols[0].name());
-        assertEquals("C", cols[1].name());
-        assertEquals("AA", cols[2].name());
-        assertEquals("AD", cols[3].name());
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(VarlenNativeType.class.getSimpleName(), "name", spec(), "len", len);
     }
 }
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java
index b043c3a..0085fba 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.benchmarks;
 import java.lang.reflect.Field;
 import java.util.EnumSet;
 import java.util.Random;
+import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 import javax.annotation.processing.Generated;
 import com.facebook.presto.bytecode.Access;
@@ -53,7 +54,7 @@ import org.openjdk.jmh.runner.RunnerException;
 import org.openjdk.jmh.runner.options.Options;
 import org.openjdk.jmh.runner.options.OptionsBuilder;
 
-import static org.apache.ignite.internal.schema.NativeType.LONG;
+import static org.apache.ignite.internal.schema.NativeTypes.LONG;
 
 /**
  * Serializer benchmark.
@@ -115,7 +116,7 @@ public class SerializerBenchmarkTest {
 
         Column[] keyCols = new Column[] {new Column("key", LONG, true)};
         Column[] valCols = mapFieldsToColumns(valClass);
-        final SchemaDescriptor schema = new SchemaDescriptor(1, keyCols, valCols);
+        final SchemaDescriptor schema = new SchemaDescriptor(UUID.randomUUID(), 1, keyCols, valCols);
 
         if ("Java".equals(serializerName))
             serializer = SerializerFactory.createJavaSerializerFactory().create(schema, Long.class, valClass);
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
index ddc5b74..3208a90 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
@@ -20,6 +20,9 @@ package org.apache.ignite.internal.schema;
 import java.util.Arrays;
 import org.junit.jupiter.api.Test;
 
+import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
+import static org.apache.ignite.internal.schema.NativeTypes.INTEGER;
+import static org.apache.ignite.internal.schema.NativeTypes.STRING;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
@@ -30,12 +33,12 @@ public class ColumnTest {
      *
      */
     @Test
-    public void testCompareColumns() {
+    public void compareColumns() {
         Column[] cols = new Column[] {
-            new Column("C", NativeType.BYTES, false),
-            new Column("B", NativeType.INTEGER, false),
-            new Column("AD", NativeType.STRING, false),
-            new Column("AA", NativeType.STRING, false),
+            new Column("C", BYTES, false),
+            new Column("B", INTEGER, false),
+            new Column("AD", STRING, false),
+            new Column("AA", STRING, false),
         };
 
         Arrays.sort(cols);
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnsTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnsTest.java
index 90ed675..d0d087b 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnsTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnsTest.java
@@ -19,6 +19,12 @@ package org.apache.ignite.internal.schema;
 
 import org.junit.jupiter.api.Test;
 
+import static org.apache.ignite.internal.schema.NativeTypes.INTEGER;
+import static org.apache.ignite.internal.schema.NativeTypes.LONG;
+import static org.apache.ignite.internal.schema.NativeTypes.SHORT;
+import static org.apache.ignite.internal.schema.NativeTypes.UUID;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
+import static org.apache.ignite.internal.schema.NativeTypes.STRING;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -31,12 +37,12 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFixSizedColumnsIndex() {
+    public void fixSizedColumnsIndex() {
         Columns cols = new Columns(
             0,
-            new Column("intCol2", NativeType.INTEGER, false),
-            new Column("intCol1", NativeType.INTEGER, false),
-            new Column("uuidCol", NativeType.UUID, false)
+            new Column("intCol2", INTEGER, false),
+            new Column("intCol1", INTEGER, false),
+            new Column("uuidCol", UUID, false)
         );
 
         assertEquals(3, cols.length());
@@ -53,12 +59,12 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testVarlenColumnsIndex() {
+    public void varlenColumnsIndex() {
         Columns cols = new Columns(
             0,
-            new Column("stringCol3", NativeType.STRING, false),
-            new Column("stringCol2", NativeType.STRING, false),
-            new Column("stringCol1", NativeType.STRING, false)
+            new Column("stringCol3", STRING, false),
+            new Column("stringCol2", STRING, false),
+            new Column("stringCol1", STRING, false)
         );
 
         assertEquals(3, cols.length());
@@ -75,13 +81,13 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testMixedColumnsIndex() {
+    public void mixedColumnsIndex() {
         Columns cols = new Columns(
             0,
-            new Column("stringCol", NativeType.STRING, false),
-            new Column("intCol2", NativeType.INTEGER, false),
-            new Column("intCol1", NativeType.INTEGER, false),
-            new Column("uuidCol", NativeType.UUID, false)
+            new Column("stringCol", STRING, false),
+            new Column("intCol2", INTEGER, false),
+            new Column("intCol1", INTEGER, false),
+            new Column("uuidCol", UUID, false)
         );
 
         assertEquals(4, cols.length());
@@ -102,7 +108,7 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testNullMapSize() {
+    public void nullMapSize() {
         assertEquals(1, new Columns(0, columns(1)).nullMapSize());
         assertEquals(1, new Columns(0, columns(7)).nullMapSize());
         assertEquals(1, new Columns(0, columns(8)).nullMapSize());
@@ -122,13 +128,13 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testColumnSchemaIndex() {
+    public void columnSchemaIndex() {
         {
             Columns cols = new Columns(
                 0,
-                new Column("uuidCol", NativeType.UUID, false),
-                new Column("intCol2", NativeType.INTEGER, false),
-                new Column("intCol1", NativeType.INTEGER, false)
+                new Column("uuidCol", UUID, false),
+                new Column("intCol2", INTEGER, false),
+                new Column("intCol1", INTEGER, false)
             );
 
             assertEquals("intCol1", cols.column(0).name());
@@ -143,9 +149,9 @@ public class ColumnsTest {
         {
             Columns cols = new Columns(
                 3,
-                new Column("uuidCol", NativeType.UUID, false),
-                new Column("intCol2", NativeType.INTEGER, false),
-                new Column("intCol1", NativeType.INTEGER, false)
+                new Column("uuidCol", UUID, false),
+                new Column("intCol2", INTEGER, false),
+                new Column("intCol1", INTEGER, false)
             );
 
             assertEquals("intCol1", cols.column(0).name());
@@ -163,15 +169,15 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFoldSizeNoVarlenIncomplete1Byte() {
+    public void foldSizeNoVarlenIncomplete1Byte() {
         Column[] colDef = {
-            new Column("a", NativeType.SHORT, false),   // 2
-            new Column("b", NativeType.INTEGER, false), // 4
-            new Column("c", NativeType.INTEGER, false), // 4
-            new Column("d", NativeType.LONG, false),    // 8
-            new Column("e", NativeType.LONG, false),    // 8
-            new Column("f", NativeType.LONG, false),    // 8
-            new Column("g", NativeType.UUID, false)     // 16
+            new Column("a", SHORT, false),   // 2
+            new Column("b", INTEGER, false), // 4
+            new Column("c", INTEGER, false), // 4
+            new Column("d", LONG, false),    // 8
+            new Column("e", LONG, false),    // 8
+            new Column("f", LONG, false),    // 8
+            new Column("g", UUID, false)     // 16
         };
 
         checkColumnFolding(colDef);
@@ -181,16 +187,16 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFoldSizeNoVarlenFull1Byte() {
+    public void foldSizeNoVarlenFull1Byte() {
         Column[] colDef = {
-            new Column("a", NativeType.SHORT, false),   // 2
-            new Column("b", NativeType.INTEGER, false), // 4
-            new Column("c", NativeType.INTEGER, false), // 4
-            new Column("d", NativeType.INTEGER, false), // 4
-            new Column("e", NativeType.LONG, false),    // 8
-            new Column("f", NativeType.LONG, false),    // 8
-            new Column("g", NativeType.UUID, false),    // 16
-            new Column("h", NativeType.UUID, false)     // 16
+            new Column("a", SHORT, false),   // 2
+            new Column("b", INTEGER, false), // 4
+            new Column("c", INTEGER, false), // 4
+            new Column("d", INTEGER, false), // 4
+            new Column("e", LONG, false),    // 8
+            new Column("f", LONG, false),    // 8
+            new Column("g", UUID, false),    // 16
+            new Column("h", UUID, false)     // 16
         };
 
         checkColumnFolding(colDef);
@@ -200,18 +206,18 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFoldSizeNoVarlenIncomplete2Bytes() {
+    public void foldSizeNoVarlenIncomplete2Bytes() {
         Column[] colDef = {
-            new Column("a", NativeType.SHORT, false),   // 2
-            new Column("b", NativeType.SHORT, false),   // 2
-            new Column("c", NativeType.INTEGER, false), // 4
-            new Column("d", NativeType.INTEGER, false), // 4
-            new Column("e", NativeType.INTEGER, false), // 4
-            new Column("f", NativeType.INTEGER, false), // 4
-            new Column("g", NativeType.LONG, false),    // 8
-            new Column("h", NativeType.LONG, false),    // 8
-            new Column("i", NativeType.UUID, false),    // 16
-            new Column("j", NativeType.UUID, false)     // 16
+            new Column("a", SHORT, false),   // 2
+            new Column("b", SHORT, false),   // 2
+            new Column("c", INTEGER, false), // 4
+            new Column("d", INTEGER, false), // 4
+            new Column("e", INTEGER, false), // 4
+            new Column("f", INTEGER, false), // 4
+            new Column("g", LONG, false),    // 8
+            new Column("h", LONG, false),    // 8
+            new Column("i", UUID, false),    // 16
+            new Column("j", UUID, false)     // 16
         };
 
         checkColumnFolding(colDef);
@@ -221,24 +227,24 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFoldSizeNoVarlenFull2Bytes() {
+    public void foldSizeNoVarlenFull2Bytes() {
         Column[] colDef = {
-            new Column("a", NativeType.SHORT, false),   // 2
-            new Column("b", NativeType.SHORT, false),   // 2
-            new Column("c", NativeType.SHORT, false),   // 2
-            new Column("d", NativeType.SHORT, false),   // 2
-            new Column("e", NativeType.INTEGER, false), // 4
-            new Column("f", NativeType.INTEGER, false), // 4
-            new Column("g", NativeType.INTEGER, false), // 4
-            new Column("h", NativeType.INTEGER, false), // 4
-            new Column("i", NativeType.INTEGER, false), // 4
-            new Column("j", NativeType.INTEGER, false), // 4
-            new Column("k", NativeType.LONG, false),    // 8
-            new Column("l", NativeType.LONG, false),    // 8
-            new Column("m", NativeType.LONG, false),    // 8
-            new Column("n", NativeType.UUID, false),    // 16
-            new Column("o", NativeType.UUID, false),    // 16
-            new Column("p", NativeType.UUID, false)     // 16
+            new Column("a", SHORT, false),   // 2
+            new Column("b", SHORT, false),   // 2
+            new Column("c", SHORT, false),   // 2
+            new Column("d", SHORT, false),   // 2
+            new Column("e", INTEGER, false), // 4
+            new Column("f", INTEGER, false), // 4
+            new Column("g", INTEGER, false), // 4
+            new Column("h", INTEGER, false), // 4
+            new Column("i", INTEGER, false), // 4
+            new Column("j", INTEGER, false), // 4
+            new Column("k", LONG, false),    // 8
+            new Column("l", LONG, false),    // 8
+            new Column("m", LONG, false),    // 8
+            new Column("n", UUID, false),    // 16
+            new Column("o", UUID, false),    // 16
+            new Column("p", UUID, false)     // 16
         };
 
         checkColumnFolding(colDef);
@@ -248,15 +254,15 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFoldSizeVarlenIncomplete1Byte() {
+    public void foldSizeVarlenIncomplete1Byte() {
         Column[] colDef = {
-            new Column("a", NativeType.SHORT, false),   // 2
-            new Column("b", NativeType.INTEGER, false), // 4
-            new Column("c", NativeType.INTEGER, false), // 4
-            new Column("d", NativeType.INTEGER, false), // 4
-            new Column("e", NativeType.LONG, false),    // 8
-            new Column("f", NativeType.STRING, false),
-            new Column("g", NativeType.BYTES, false)
+            new Column("a", SHORT, false),   // 2
+            new Column("b", INTEGER, false), // 4
+            new Column("c", INTEGER, false), // 4
+            new Column("d", INTEGER, false), // 4
+            new Column("e", LONG, false),    // 8
+            new Column("f", STRING, false),
+            new Column("g", BYTES, false)
         };
 
         checkColumnFolding(colDef);
@@ -266,16 +272,16 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFoldSizeVarlenFull1Byte() {
+    public void foldSizeVarlenFull1Byte() {
         Column[] colDef = {
-            new Column("a", NativeType.SHORT, false),   // 2
-            new Column("b", NativeType.INTEGER, false), // 4
-            new Column("c", NativeType.INTEGER, false), // 4
-            new Column("d", NativeType.INTEGER, false), // 4
-            new Column("e", NativeType.LONG, false),    // 8
-            new Column("f", NativeType.STRING, false),
-            new Column("g", NativeType.STRING, false),
-            new Column("h", NativeType.BYTES, false)
+            new Column("a", SHORT, false),   // 2
+            new Column("b", INTEGER, false), // 4
+            new Column("c", INTEGER, false), // 4
+            new Column("d", INTEGER, false), // 4
+            new Column("e", LONG, false),    // 8
+            new Column("f", STRING, false),
+            new Column("g", STRING, false),
+            new Column("h", BYTES, false)
         };
 
         checkColumnFolding(colDef);
@@ -285,17 +291,17 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFoldSizeVarlenIncomplete2Bytes1() {
+    public void foldSizeVarlenIncomplete2Bytes1() {
         Column[] colDef = {
-            new Column("a", NativeType.SHORT, false),   // 2
-            new Column("b", NativeType.INTEGER, false), // 4
-            new Column("c", NativeType.INTEGER, false), // 4
-            new Column("d", NativeType.INTEGER, false), // 4
-            new Column("e", NativeType.INTEGER, false), // 4
-            new Column("f", NativeType.LONG, false),    // 8
-            new Column("g", NativeType.STRING, false),
-            new Column("h", NativeType.STRING, false),
-            new Column("i", NativeType.BYTES, false)
+            new Column("a", SHORT, false),   // 2
+            new Column("b", INTEGER, false), // 4
+            new Column("c", INTEGER, false), // 4
+            new Column("d", INTEGER, false), // 4
+            new Column("e", INTEGER, false), // 4
+            new Column("f", LONG, false),    // 8
+            new Column("g", STRING, false),
+            new Column("h", STRING, false),
+            new Column("i", BYTES, false)
         };
 
         checkColumnFolding(colDef);
@@ -305,19 +311,19 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFoldSizeVarlenIncomplete2Bytes2() {
+    public void foldSizeVarlenIncomplete2Bytes2() {
         Column[] colDef = {
-            new Column("a", NativeType.SHORT, false),   // 2
-            new Column("b", NativeType.INTEGER, false), // 4
-            new Column("c", NativeType.INTEGER, false), // 4
-            new Column("d", NativeType.INTEGER, false), // 4
-            new Column("e", NativeType.INTEGER, false), // 4
-            new Column("f", NativeType.INTEGER, false), // 4
-            new Column("g", NativeType.INTEGER, false), // 4
-            new Column("h", NativeType.LONG, false),    // 8
-            new Column("i", NativeType.STRING, false),
-            new Column("j", NativeType.STRING, false),
-            new Column("k", NativeType.BYTES, false)
+            new Column("a", SHORT, false),   // 2
+            new Column("b", INTEGER, false), // 4
+            new Column("c", INTEGER, false), // 4
+            new Column("d", INTEGER, false), // 4
+            new Column("e", INTEGER, false), // 4
+            new Column("f", INTEGER, false), // 4
+            new Column("g", INTEGER, false), // 4
+            new Column("h", LONG, false),    // 8
+            new Column("i", STRING, false),
+            new Column("j", STRING, false),
+            new Column("k", BYTES, false)
         };
 
         checkColumnFolding(colDef);
@@ -327,19 +333,19 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFoldSizeVarlenIncomplete2Bytes3() {
+    public void foldSizeVarlenIncomplete2Bytes3() {
         Column[] colDef = {
-            new Column("a", NativeType.SHORT, false),   // 2
-            new Column("b", NativeType.INTEGER, false), // 4
-            new Column("c", NativeType.INTEGER, false), // 4
-            new Column("d", NativeType.INTEGER, false), // 4
-            new Column("e", NativeType.INTEGER, false), // 4
-            new Column("f", NativeType.INTEGER, false), // 4
-            new Column("g", NativeType.INTEGER, false), // 4
-            new Column("h", NativeType.LONG, false),    // 8
-            new Column("i", NativeType.LONG, false),    // 8
-            new Column("j", NativeType.STRING, false),
-            new Column("k", NativeType.BYTES, false)
+            new Column("a", SHORT, false),   // 2
+            new Column("b", INTEGER, false), // 4
+            new Column("c", INTEGER, false), // 4
+            new Column("d", INTEGER, false), // 4
+            new Column("e", INTEGER, false), // 4
+            new Column("f", INTEGER, false), // 4
+            new Column("g", INTEGER, false), // 4
+            new Column("h", LONG, false),    // 8
+            new Column("i", LONG, false),    // 8
+            new Column("j", STRING, false),
+            new Column("k", BYTES, false)
         };
 
         checkColumnFolding(colDef);
@@ -349,24 +355,24 @@ public class ColumnsTest {
      *
      */
     @Test
-    public void testFoldSizeVarlenFull2Bytes() {
+    public void foldSizeVarlenFull2Bytes() {
         Column[] colDef = {
-            new Column("a", NativeType.SHORT, false),   // 2
-            new Column("b", NativeType.INTEGER, false), // 4
-            new Column("c", NativeType.INTEGER, false), // 4
-            new Column("d", NativeType.INTEGER, false), // 4
-            new Column("e", NativeType.INTEGER, false), // 4
-            new Column("f", NativeType.INTEGER, false), // 4
-            new Column("g", NativeType.INTEGER, false), // 4
-            new Column("h", NativeType.INTEGER, false), // 4
-            new Column("i", NativeType.LONG, false),    // 8
-            new Column("j", NativeType.STRING, false),
-            new Column("k", NativeType.BYTES, false),
-            new Column("l", NativeType.BYTES, false),
-            new Column("m", NativeType.BYTES, false),
-            new Column("n", NativeType.BYTES, false),
-            new Column("o", NativeType.BYTES, false),
-            new Column("p", NativeType.BYTES, false)
+            new Column("a", SHORT, false),   // 2
+            new Column("b", INTEGER, false), // 4
+            new Column("c", INTEGER, false), // 4
+            new Column("d", INTEGER, false), // 4
+            new Column("e", INTEGER, false), // 4
+            new Column("f", INTEGER, false), // 4
+            new Column("g", INTEGER, false), // 4
+            new Column("h", INTEGER, false), // 4
+            new Column("i", LONG, false),    // 8
+            new Column("j", STRING, false),
+            new Column("k", BYTES, false),
+            new Column("l", BYTES, false),
+            new Column("m", BYTES, false),
+            new Column("n", BYTES, false),
+            new Column("o", BYTES, false),
+            new Column("p", BYTES, false)
         };
 
         checkColumnFolding(colDef);
@@ -422,7 +428,7 @@ public class ColumnsTest {
                     mask |= (1 << bit);
                 else
                     // non-null, sum the size.
-                    size += colDef[idx].type().length();
+                    size += colDef[idx].type().sizeInBytes();
             }
 
             assertEquals(size, cols.foldFixedLength(b, mask), "Failed [b=" + b + ", mask=" + mask + ']');
@@ -437,9 +443,9 @@ public class ColumnsTest {
 
         for (int i = 0; i < ret.length; i++) {
             if (i % 3 == 0)
-                ret[i] = new Column("column-" + i, NativeType.LONG, true);
+                ret[i] = new Column("column-" + i, LONG, true);
             else
-                ret[i] = new Column("column-" + i, NativeType.STRING, true);
+                ret[i] = new Column("column-" + i, STRING, true);
         }
 
         return ret;
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java
index ca918b6..0ae3081 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java
@@ -17,8 +17,18 @@
 
 package org.apache.ignite.internal.schema;
 
+import org.apache.ignite.schema.ColumnType;
 import org.junit.jupiter.api.Test;
 
+import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
+import static org.apache.ignite.internal.schema.NativeTypes.DOUBLE;
+import static org.apache.ignite.internal.schema.NativeTypes.FLOAT;
+import static org.apache.ignite.internal.schema.NativeTypes.INTEGER;
+import static org.apache.ignite.internal.schema.NativeTypes.LONG;
+import static org.apache.ignite.internal.schema.NativeTypes.SHORT;
+import static org.apache.ignite.internal.schema.NativeTypes.STRING;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
@@ -29,43 +39,64 @@ public class NativeTypeTest {
      *
      */
     @Test
-    public void testCompareFixlenTypesVsVarlenTypes() {
-        assertTrue(NativeType.BYTE.compareTo(NativeType.STRING) < 0);
-        assertTrue(NativeType.BYTE.compareTo(NativeType.BYTES) < 0);
+    public void compareFixlenTypesVsVarlenTypes() {
+        assertTrue(BYTE.compareTo(STRING) < 0);
+        assertTrue(BYTE.compareTo(BYTES) < 0);
 
-        assertTrue(NativeType.INTEGER.compareTo(NativeType.STRING) < 0);
-        assertTrue(NativeType.INTEGER.compareTo(NativeType.BYTES) < 0);
+        assertTrue(NativeTypes.INTEGER.compareTo(STRING) < 0);
+        assertTrue(NativeTypes.INTEGER.compareTo(BYTES) < 0);
 
-        assertTrue(NativeType.LONG.compareTo(NativeType.STRING) < 0);
-        assertTrue(NativeType.LONG.compareTo(NativeType.BYTES) < 0);
+        assertTrue(NativeTypes.LONG.compareTo(STRING) < 0);
+        assertTrue(NativeTypes.LONG.compareTo(BYTES) < 0);
 
-        assertTrue(NativeType.UUID.compareTo(NativeType.STRING) < 0);
-        assertTrue(NativeType.UUID.compareTo(NativeType.BYTES) < 0);
+        assertTrue(NativeTypes.UUID.compareTo(STRING) < 0);
+        assertTrue(NativeTypes.UUID.compareTo(BYTES) < 0);
     }
 
     /**
      *
      */
     @Test
-    public void testCompareFixlenTypesBySize() {
-        assertTrue(NativeType.SHORT.compareTo(NativeType.INTEGER) < 0);
-        assertTrue(NativeType.INTEGER.compareTo(NativeType.LONG) < 0);
-        assertTrue(NativeType.LONG.compareTo(NativeType.UUID) < 0);
+    public void compareFixlenTypesBySize() {
+        assertTrue(NativeTypes.SHORT.compareTo(NativeTypes.INTEGER) < 0);
+        assertTrue(NativeTypes.INTEGER.compareTo(NativeTypes.LONG) < 0);
+        assertTrue(NativeTypes.LONG.compareTo(NativeTypes.UUID) < 0);
     }
 
     /**
      *
      */
     @Test
-    public void testCompareFixlenTypesByDesc() {
-        assertTrue(NativeType.FLOAT.compareTo(NativeType.INTEGER) < 0);
+    public void compareFixlenTypesByDesc() {
+        assertTrue(NativeTypes.FLOAT.compareTo(NativeTypes.INTEGER) < 0);
     }
 
     /**
      *
      */
     @Test
-    public void testCompareVarlenTypesByDesc() {
-        assertTrue(NativeType.BYTES.compareTo(NativeType.STRING) < 0);
+    public void compareVarlenTypesByDesc() {
+        assertTrue(BYTES.compareTo(STRING) < 0);
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void createNativeTypeFromColumnType() {
+        assertEquals(BYTE, NativeTypes.from(ColumnType.INT8));
+        assertEquals(SHORT, NativeTypes.from(ColumnType.INT16));
+        assertEquals(INTEGER, NativeTypes.from(ColumnType.INT32));
+        assertEquals(LONG, NativeTypes.from(ColumnType.INT64));
+        assertEquals(FLOAT, NativeTypes.from(ColumnType.FLOAT));
+        assertEquals(DOUBLE, NativeTypes.from(ColumnType.DOUBLE));
+        assertEquals(BYTES, NativeTypes.from(ColumnType.blobOf()));
+        assertEquals(STRING, NativeTypes.from(ColumnType.string()));
+
+        for (int i = 1; i < 800; i += 100) {
+            assertEquals(NativeTypes.blobOf(i), NativeTypes.from(ColumnType.blobOf(i)));
+            assertEquals(NativeTypes.stringOf(i), NativeTypes.from(ColumnType.stringOf(i)));
+            assertEquals(NativeTypes.bitmaskOf(i), NativeTypes.from(ColumnType.bitmaskOf(i)));
+        }
     }
 }
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
index b2c56d5..5f042d4 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
@@ -21,12 +21,12 @@ import java.util.Arrays;
 import java.util.UUID;
 import org.junit.jupiter.api.Test;
 
-import static org.apache.ignite.internal.schema.NativeType.BYTE;
-import static org.apache.ignite.internal.schema.NativeType.BYTES;
-import static org.apache.ignite.internal.schema.NativeType.INTEGER;
-import static org.apache.ignite.internal.schema.NativeType.SHORT;
-import static org.apache.ignite.internal.schema.NativeType.STRING;
-import static org.apache.ignite.internal.schema.NativeType.UUID;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
+import static org.apache.ignite.internal.schema.NativeTypes.INTEGER;
+import static org.apache.ignite.internal.schema.NativeTypes.SHORT;
+import static org.apache.ignite.internal.schema.NativeTypes.STRING;
+import static org.apache.ignite.internal.schema.NativeTypes.UUID;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 
 /**
@@ -36,12 +36,15 @@ public class RowAssemblerTest {
     /** Uuid test value. */
     public final java.util.UUID uuidVal = new UUID(-5204230847775358097L, 4916207022290092939L);
 
+    /** Table ID test value. */
+    public final java.util.UUID tableId = java.util.UUID.randomUUID();
+
     @Test
-    public void testFixedKeyFixedNullableValue() {
+    public void fixedKeyFixedNullableValue() {
         Column[] keyCols = new Column[] {new Column("keyIntCol", INTEGER, false)};
         Column[] valCols = new Column[] {new Column("valIntCol", INTEGER, true)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
@@ -71,11 +74,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testFixedKeyFixedValue() {
+    public void fixedKeyFixedValue() {
         Column[] keyCols = new Column[] {new Column("keyShortCol", SHORT, false)};
         Column[] valCols = new Column[] {new Column("valShortCol", SHORT, false)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         { // With value.
             RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
@@ -96,11 +99,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testFixedKeyVarlenNullableValue() {
+    public void fixedKeyVarlenNullableValue() {
         Column[] keyCols = new Column[] {new Column("keyShortCol", SHORT, false)};
         Column[] valCols = new Column[] {new Column("valStrCol", STRING, true)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
@@ -130,11 +133,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testFixedKeyVarlenValue() {
+    public void fixedKeyVarlenValue() {
         Column[] keyCols = new Column[] {new Column("keyShortCol", SHORT, false)};
         Column[] valCols = new Column[] {new Column("valStrCol", STRING, false)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
@@ -155,11 +158,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testFixedNullableKeyFixedValue() {
+    public void fixedNullableKeyFixedValue() {
         Column[] keyCols = new Column[] {new Column("keyShortCol", SHORT, true)};
         Column[] valCols = new Column[] {new Column("valByteCol", BYTE, false)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
@@ -189,11 +192,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testFixedNullableKeyFixedNullableValue() {
+    public void fixedNullableKeyFixedNullableValue() {
         Column[] keyCols = new Column[] {new Column("keyShortCol", SHORT, true)};
         Column[] valCols = new Column[] {new Column("valShortCol", SHORT, true)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
@@ -241,11 +244,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testFixedNullableKeyVarlenNullableValue() {
+    public void fixedNullableKeyVarlenNullableValue() {
         Column[] keyCols = new Column[] {new Column("keyIntCol", INTEGER, true)};
         Column[] valCols = new Column[] {new Column("valStrCol", STRING, true)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
@@ -293,11 +296,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testFixedNullableKeyVarlenValue() {
+    public void fixedNullableKeyVarlenValue() {
         Column[] keyCols = new Column[] {new Column("keyByteCol", BYTE, true)};
         Column[] valCols = new Column[] {new Column("valStrCol", STRING, false)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
@@ -327,11 +330,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testVarlenKeyFixedNullableValue() {
+    public void varlenKeyFixedNullableValue() {
         Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, false)};
         Column[] valCols = new Column[] {new Column("valUuidCol", UUID, true)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
@@ -363,11 +366,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testVarlenKeyFixedValue() {
+    public void varlenKeyFixedValue() {
         Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, false)};
         Column[] valCols = new Column[] {new Column("valUuidCol", UUID, false)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
@@ -390,11 +393,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testVarlenKeyVarlenNullableValue() {
+    public void varlenKeyVarlenNullableValue() {
         Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, false)};
         Column[] valCols = new Column[] {new Column("valBytesCol", BYTES, true)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 1, 1);
@@ -424,11 +427,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testVarlenKeyVarlenValue() {
+    public void varlenKeyVarlenValue() {
         Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, false)};
         Column[] valCols = new Column[] {new Column("valBytesCol", BYTES, false)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 1, 1);
@@ -449,11 +452,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testVarlenNullableKeyFixedNullableValue() {
+    public void varlenNullableKeyFixedNullableValue() {
         Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, true)};
         Column[] valCols = new Column[] {new Column("valShortCol", SHORT, true)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
@@ -501,11 +504,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testVarlenNullableKeyFixedValue() {
+    public void varlenNullableKeyFixedValue() {
         Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, true)};
         Column[] valCols = new Column[] {new Column("valShortCol", SHORT, false)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
@@ -535,11 +538,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testVarlenNullableKeyVarlenNullableValue() {
+    public void varlenNullableKeyVarlenNullableValue() {
         Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, true)};
         Column[] valCols = new Column[] {new Column("valBytesCol", BYTES, true)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 1, 1);
@@ -587,11 +590,11 @@ public class RowAssemblerTest {
     }
 
     @Test
-    public void testVarlenNullableKeyVarlenValue() {
+    public void varlenNullableKeyVarlenValue() {
         Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, true)};
         Column[] valCols = new Column[] {new Column("valBytesCol", BYTES, false)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
             RowAssembler asm = new RowAssembler(schema, 0, 1, 1);
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
index cd36776..cdb1d31 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
@@ -24,15 +24,15 @@ import java.util.Random;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-import static org.apache.ignite.internal.schema.NativeType.BYTE;
-import static org.apache.ignite.internal.schema.NativeType.BYTES;
-import static org.apache.ignite.internal.schema.NativeType.DOUBLE;
-import static org.apache.ignite.internal.schema.NativeType.FLOAT;
-import static org.apache.ignite.internal.schema.NativeType.INTEGER;
-import static org.apache.ignite.internal.schema.NativeType.LONG;
-import static org.apache.ignite.internal.schema.NativeType.SHORT;
-import static org.apache.ignite.internal.schema.NativeType.STRING;
-import static org.apache.ignite.internal.schema.NativeType.UUID;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
+import static org.apache.ignite.internal.schema.NativeTypes.DOUBLE;
+import static org.apache.ignite.internal.schema.NativeTypes.FLOAT;
+import static org.apache.ignite.internal.schema.NativeTypes.INTEGER;
+import static org.apache.ignite.internal.schema.NativeTypes.LONG;
+import static org.apache.ignite.internal.schema.NativeTypes.SHORT;
+import static org.apache.ignite.internal.schema.NativeTypes.UUID;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
+import static org.apache.ignite.internal.schema.NativeTypes.STRING;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
@@ -59,7 +59,7 @@ public class RowTest {
      *
      */
     @Test
-    public void testFixedSizes() {
+    public void fixedSizes() {
         Column[] keyCols = new Column[] {
             new Column("keyByteCol", BYTE, true),
             new Column("keyShortCol", SHORT, true),
@@ -68,8 +68,8 @@ public class RowTest {
             new Column("keyFloatCol", FLOAT, true),
             new Column("keyDoubleCol", DOUBLE, true),
             new Column("keyUuidCol", UUID, true),
-            new Column("keyBitmask1Col", Bitmask.of(4), true),
-            new Column("keyBitmask2Col", Bitmask.of(22), true)
+            new Column("keyBitmask1Col", NativeTypes.bitmaskOf(4), true),
+            new Column("keyBitmask2Col", NativeTypes.bitmaskOf(22), true)
         };
 
         Column[] valCols = new Column[] {
@@ -80,8 +80,8 @@ public class RowTest {
             new Column("valFloatCol", FLOAT, true),
             new Column("valDoubleCol", DOUBLE, true),
             new Column("valUuidCol", UUID, true),
-            new Column("valBitmask1Col", Bitmask.of(4), true),
-            new Column("valBitmask2Col", Bitmask.of(22), true)
+            new Column("valBitmask1Col", NativeTypes.bitmaskOf(4), true),
+            new Column("valBitmask2Col", NativeTypes.bitmaskOf(22), true)
         };
 
         checkSchema(keyCols, valCols);
@@ -91,7 +91,7 @@ public class RowTest {
      *
      */
     @Test
-    public void testVariableSizes() {
+    public void variableSizes() {
         Column[] keyCols = new Column[] {
             new Column("keyByteCol", BYTE, true),
             new Column("keyShortCol", SHORT, true),
@@ -117,7 +117,7 @@ public class RowTest {
      *
      */
     @Test
-    public void testMixedSizes() {
+    public void mixedSizes() {
         Column[] keyCols = new Column[] {
             new Column("keyBytesCol", BYTES, true),
             new Column("keyStringCol", STRING, true),
@@ -147,7 +147,7 @@ public class RowTest {
      *
      */
     private void checkSchemaShuffled(Column[] keyCols, Column[] valCols) {
-        SchemaDescriptor sch = new SchemaDescriptor(1, keyCols, valCols);
+        SchemaDescriptor sch = new SchemaDescriptor(java.util.UUID.randomUUID(), 1, keyCols, valCols);
 
         Object[] checkArr = sequence(sch);
 
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaDescriptorTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaDescriptorTest.java
index 2185554..da25ae6 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaDescriptorTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaDescriptorTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.schema;
 
+import java.util.UUID;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -29,17 +30,17 @@ public class SchemaDescriptorTest {
      *
      */
     @Test
-    public void testColumnIndexedAccess() {
-        SchemaDescriptor desc = new SchemaDescriptor(1,
+    public void columnIndexedAccess() {
+        SchemaDescriptor desc = new SchemaDescriptor(UUID.randomUUID(), 1,
             new Column[] {
-                new Column("columnA", NativeType.BYTE, false),
-                new Column("columnB", NativeType.UUID, false),
-                new Column("columnC", NativeType.INTEGER, false),
+                new Column("columnA", NativeTypes.BYTE, false),
+                new Column("columnB", NativeTypes.UUID, false),
+                new Column("columnC", NativeTypes.INTEGER, false),
             },
             new Column[] {
-                new Column("columnD", NativeType.BYTE, false),
-                new Column("columnE", NativeType.UUID, false),
-                new Column("columnF", NativeType.INTEGER, false),
+                new Column("columnD", NativeTypes.BYTE, false),
+                new Column("columnE", NativeTypes.UUID, false),
+                new Column("columnF", NativeTypes.INTEGER, false),
             }
         );
 
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaRegistryImplTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaRegistryImplTest.java
index fb20183..2d28989 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaRegistryImplTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaRegistryImplTest.java
@@ -19,15 +19,16 @@ package org.apache.ignite.internal.schema;
 
 import java.util.Arrays;
 import java.util.Map;
+import java.util.UUID;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.schema.registry.SchemaRegistrationConflictException;
 import org.apache.ignite.internal.schema.registry.SchemaRegistryException;
 import org.apache.ignite.internal.schema.registry.SchemaRegistryImpl;
 import org.junit.jupiter.api.Test;
 
-import static org.apache.ignite.internal.schema.NativeType.BYTES;
-import static org.apache.ignite.internal.schema.NativeType.LONG;
-import static org.apache.ignite.internal.schema.NativeType.STRING;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
+import static org.apache.ignite.internal.schema.NativeTypes.LONG;
+import static org.apache.ignite.internal.schema.NativeTypes.STRING;
 import static org.apache.ignite.internal.schema.registry.SchemaRegistryImpl.INITIAL_SCHEMA_VERSION;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -44,15 +45,17 @@ public class SchemaRegistryImplTest {
      */
     @Test
     public void testWrongSchemaVersionRegistration() {
-        final SchemaDescriptor schemaV0 = new SchemaDescriptor(INITIAL_SCHEMA_VERSION,
+        UUID tableId = UUID.randomUUID();
+
+        final SchemaDescriptor schemaV0 = new SchemaDescriptor(tableId, INITIAL_SCHEMA_VERSION,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
-        final SchemaDescriptor schemaV1 = new SchemaDescriptor(0,
+        final SchemaDescriptor schemaV1 = new SchemaDescriptor(tableId, 0,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
-        final SchemaDescriptor schemaV2 = new SchemaDescriptor(2,
+        final SchemaDescriptor schemaV2 = new SchemaDescriptor(tableId, 2,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
@@ -90,18 +93,20 @@ public class SchemaRegistryImplTest {
      */
     @Test
     public void testSchemaRegistration() {
-        final SchemaDescriptor schemaV1 = new SchemaDescriptor(1,
+        UUID tableId = UUID.randomUUID();
+
+        final SchemaDescriptor schemaV1 = new SchemaDescriptor(tableId, 1,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
-        final SchemaDescriptor schemaV2 = new SchemaDescriptor(2,
+        final SchemaDescriptor schemaV2 = new SchemaDescriptor(tableId, 2,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
                 new Column("valStringCol", STRING, true)
             });
 
-        final SchemaDescriptor schemaV4 = new SchemaDescriptor(4,
+        final SchemaDescriptor schemaV4 = new SchemaDescriptor(tableId, 4,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
@@ -143,19 +148,21 @@ public class SchemaRegistryImplTest {
      * Check schema registration.
      */
     @Test
-    public void testDuplucateSchemaRegistration() {
-        final SchemaDescriptor schemaV1 = new SchemaDescriptor(1,
+    public void testDuplicateSchemaRegistration() {
+        UUID tableId = UUID.randomUUID();
+
+        final SchemaDescriptor schemaV1 = new SchemaDescriptor(tableId, 1,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
-        final SchemaDescriptor wrongSchema = new SchemaDescriptor(1,
+        final SchemaDescriptor wrongSchema = new SchemaDescriptor(tableId, 1,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
                 new Column("valStringCol", STRING, true)
             });
 
-        final SchemaDescriptor schemaV2 = new SchemaDescriptor(2,
+        final SchemaDescriptor schemaV2 = new SchemaDescriptor(tableId, 2,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
@@ -206,24 +213,26 @@ public class SchemaRegistryImplTest {
      */
     @Test
     public void testSchemaCleanup() {
-        final SchemaDescriptor schemaV1 = new SchemaDescriptor(1,
+        UUID tableId = UUID.randomUUID();
+
+        final SchemaDescriptor schemaV1 = new SchemaDescriptor(tableId, 1,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
-        final SchemaDescriptor schemaV2 = new SchemaDescriptor(2,
+        final SchemaDescriptor schemaV2 = new SchemaDescriptor(tableId, 2,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
                 new Column("valStringCol", STRING, true)
             });
 
-        final SchemaDescriptor schemaV3 = new SchemaDescriptor(3,
+        final SchemaDescriptor schemaV3 = new SchemaDescriptor(tableId, 3,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valStringCol", STRING, true)
             });
 
-        final SchemaDescriptor schemaV4 = new SchemaDescriptor(4,
+        final SchemaDescriptor schemaV4 = new SchemaDescriptor(tableId, 4,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
@@ -320,24 +329,26 @@ public class SchemaRegistryImplTest {
      */
     @Test
     public void testInitialSchemaWithFullHistory() {
-        final SchemaDescriptor schemaV1 = new SchemaDescriptor(1,
+        UUID tableId = UUID.randomUUID();
+
+        final SchemaDescriptor schemaV1 = new SchemaDescriptor(tableId, 1,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
-        final SchemaDescriptor schemaV2 = new SchemaDescriptor(2,
+        final SchemaDescriptor schemaV2 = new SchemaDescriptor(tableId, 2,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
                 new Column("valStringCol", STRING, true)
             });
 
-        final SchemaDescriptor schemaV3 = new SchemaDescriptor(3,
+        final SchemaDescriptor schemaV3 = new SchemaDescriptor(tableId, 3,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valStringCol", STRING, true)
             });
 
-        final SchemaDescriptor schemaV4 = new SchemaDescriptor(4,
+        final SchemaDescriptor schemaV4 = new SchemaDescriptor(tableId, 4,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
@@ -384,29 +395,31 @@ public class SchemaRegistryImplTest {
      */
     @Test
     public void testInitialSchemaWithTailHistory() {
-        final SchemaDescriptor schemaV1 = new SchemaDescriptor(1,
+        UUID tableId = UUID.randomUUID();
+
+        final SchemaDescriptor schemaV1 = new SchemaDescriptor(tableId, 1,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
-        final SchemaDescriptor schemaV2 = new SchemaDescriptor(2,
+        final SchemaDescriptor schemaV2 = new SchemaDescriptor(tableId, 2,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
                 new Column("valStringCol", STRING, true)
             });
 
-        final SchemaDescriptor schemaV3 = new SchemaDescriptor(3,
+        final SchemaDescriptor schemaV3 = new SchemaDescriptor(tableId, 3,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {new Column("valStringCol", STRING, true)});
 
-        final SchemaDescriptor schemaV4 = new SchemaDescriptor(4,
+        final SchemaDescriptor schemaV4 = new SchemaDescriptor(tableId, 4,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
                 new Column("valStringCol", STRING, true)
             });
 
-        final SchemaDescriptor schemaV5 = new SchemaDescriptor(5,
+        final SchemaDescriptor schemaV5 = new SchemaDescriptor(tableId, 5,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {new Column("valStringCol", STRING, true)});
 
@@ -456,20 +469,22 @@ public class SchemaRegistryImplTest {
      */
     @Test
     public void testSchemaWithHistoryCleanup() {
-        final SchemaDescriptor schemaV2 = new SchemaDescriptor(2,
+        UUID tableId = UUID.randomUUID();
+
+        final SchemaDescriptor schemaV2 = new SchemaDescriptor(tableId, 2,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
                 new Column("valStringCol", STRING, true)
             });
 
-        final SchemaDescriptor schemaV3 = new SchemaDescriptor(3,
+        final SchemaDescriptor schemaV3 = new SchemaDescriptor(tableId, 3,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valStringCol", STRING, true)
             });
 
-        final SchemaDescriptor schemaV4 = new SchemaDescriptor(4,
+        final SchemaDescriptor schemaV4 = new SchemaDescriptor(tableId, 4,
             new Column[] {new Column("keyLongCol", LONG, true)},
             new Column[] {
                 new Column("valBytesCol", BYTES, true),
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/TestUtils.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/TestUtils.java
index 9a84e71..58da944 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/TestUtils.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/TestUtils.java
@@ -61,7 +61,7 @@ public final class TestUtils {
                 return randomBytes(rnd, rnd.nextInt(255));
 
             case BITMASK: {
-                Bitmask maskType = (Bitmask)type;
+                BitmaskNativeType maskType = (BitmaskNativeType)type;
 
                 return randomBitSet(rnd, maskType.bits());
             }
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java
index 1f39361..a7977a5 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java
@@ -35,10 +35,10 @@ import java.util.Random;
 import java.util.UUID;
 import java.util.stream.Stream;
 import javax.annotation.processing.Generated;
-import org.apache.ignite.internal.schema.Bitmask;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.NativeType;
 import org.apache.ignite.internal.schema.NativeTypeSpec;
+import org.apache.ignite.internal.schema.NativeTypes;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.TestUtils;
 import org.apache.ignite.internal.schema.marshaller.asm.AsmSerializerGenerator;
@@ -51,15 +51,15 @@ import org.junit.jupiter.api.TestFactory;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
 
-import static org.apache.ignite.internal.schema.NativeType.BYTE;
-import static org.apache.ignite.internal.schema.NativeType.BYTES;
-import static org.apache.ignite.internal.schema.NativeType.DOUBLE;
-import static org.apache.ignite.internal.schema.NativeType.FLOAT;
-import static org.apache.ignite.internal.schema.NativeType.INTEGER;
-import static org.apache.ignite.internal.schema.NativeType.LONG;
-import static org.apache.ignite.internal.schema.NativeType.SHORT;
-import static org.apache.ignite.internal.schema.NativeType.STRING;
-import static org.apache.ignite.internal.schema.NativeType.UUID;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
+import static org.apache.ignite.internal.schema.NativeTypes.DOUBLE;
+import static org.apache.ignite.internal.schema.NativeTypes.FLOAT;
+import static org.apache.ignite.internal.schema.NativeTypes.INTEGER;
+import static org.apache.ignite.internal.schema.NativeTypes.LONG;
+import static org.apache.ignite.internal.schema.NativeTypes.SHORT;
+import static org.apache.ignite.internal.schema.NativeTypes.UUID;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
+import static org.apache.ignite.internal.schema.NativeTypes.STRING;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -71,6 +71,9 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest;
  * Serializer test.
  */
 public class JavaSerializerTest {
+    /** Table ID test value. */
+    public final java.util.UUID tableId = java.util.UUID.randomUUID();
+
     /**
      * @return List of serializers for test.
      */
@@ -101,7 +104,7 @@ public class JavaSerializerTest {
      */
     @TestFactory
     public Stream<DynamicNode> testBasicTypes() {
-        NativeType[] types = new NativeType[] {BYTE, SHORT, INTEGER, LONG, FLOAT, DOUBLE, UUID, STRING, BYTES, Bitmask.of(5)};
+        NativeType[] types = new NativeType[] {BYTE, SHORT, INTEGER, LONG, FLOAT, DOUBLE, UUID, STRING, BYTES, NativeTypes.bitmaskOf(5)};
 
         return serializerFactoryProvider().stream().map(factory ->
             dynamicContainer(
@@ -118,7 +121,7 @@ public class JavaSerializerTest {
                         dynamicTest("testMixTypes 1", () -> checkBasicType(factory, FLOAT, DOUBLE)),
                         dynamicTest("testMixTypes 1", () -> checkBasicType(factory, INTEGER, BYTES)),
                         dynamicTest("testMixTypes 1", () -> checkBasicType(factory, STRING, LONG)),
-                        dynamicTest("testMixTypes 1", () -> checkBasicType(factory, Bitmask.of(9), BYTES))
+                        dynamicTest("testMixTypes 1", () -> checkBasicType(factory, NativeTypes.bitmaskOf(9), BYTES))
                     )
                 )
             ));
@@ -129,7 +132,7 @@ public class JavaSerializerTest {
      */
     @ParameterizedTest
     @MethodSource("serializerFactoryProvider")
-    public void testComplexType(SerializerFactory factory) throws SerializationException {
+    public void complexType(SerializerFactory factory) throws SerializationException {
         Column[] cols = new Column[] {
             new Column("pByteCol", BYTE, false),
             new Column("pShortCol", SHORT, false),
@@ -147,13 +150,13 @@ public class JavaSerializerTest {
             new Column("doubleCol", DOUBLE, true),
 
             new Column("uuidCol", UUID, true),
-            new Column("bitmaskCol", Bitmask.of(42), true),
+            new Column("bitmaskCol", NativeTypes.bitmaskOf(42), true),
             new Column("stringCol", STRING, true),
             new Column("nullBytesCol", BYTES, true),
             new Column("bytesCol", BYTES, true),
         };
 
-        SchemaDescriptor schema = new SchemaDescriptor(1, cols, cols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 1, cols, cols);
 
         final Object key = TestObject.randomObject(rnd);
         final Object val = TestObject.randomObject(rnd);
@@ -178,13 +181,13 @@ public class JavaSerializerTest {
      */
     @ParameterizedTest
     @MethodSource("serializerFactoryProvider")
-    public void testClassWithIncorrectBitmaskSize(SerializerFactory factory) {
+    public void classWithWrongFieldType(SerializerFactory factory) {
         Column[] cols = new Column[] {
-            new Column("pLongCol", LONG, false),
-            new Column("bitmaskCol", Bitmask.of(9), true),
+            new Column("bitmaskCol", NativeTypes.bitmaskOf(42), true),
+            new Column("shortCol", UUID, true)
         };
 
-        SchemaDescriptor schema = new SchemaDescriptor(1, cols, cols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 1, cols, cols);
 
         final Object key = TestObject.randomObject(rnd);
         final Object val = TestObject.randomObject(rnd);
@@ -194,7 +197,7 @@ public class JavaSerializerTest {
         assertThrows(
             SerializationException.class,
             () -> serializer.serialize(key, val),
-            "Failed to write field [name=bitmaskCol]"
+            "Failed to write field [name=shortCol]"
         );
     }
 
@@ -203,13 +206,13 @@ public class JavaSerializerTest {
      */
     @ParameterizedTest
     @MethodSource("serializerFactoryProvider")
-    public void testClassWithWrongFieldType(SerializerFactory factory) {
+    public void classWithIncorrectBitmaskSize(SerializerFactory factory) {
         Column[] cols = new Column[] {
-            new Column("bitmaskCol", Bitmask.of(42), true),
-            new Column("shortCol", UUID, true)
+            new Column("pLongCol", LONG, false),
+            new Column("bitmaskCol", NativeTypes.bitmaskOf(9), true),
         };
 
-        SchemaDescriptor schema = new SchemaDescriptor(1, cols, cols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 1, cols, cols);
 
         final Object key = TestObject.randomObject(rnd);
         final Object val = TestObject.randomObject(rnd);
@@ -219,7 +222,7 @@ public class JavaSerializerTest {
         assertThrows(
             SerializationException.class,
             () -> serializer.serialize(key, val),
-            "Failed to write field [name=shortCol]"
+            "Failed to write field [name=bitmaskCol]"
         );
     }
 
@@ -228,12 +231,12 @@ public class JavaSerializerTest {
      */
     @ParameterizedTest
     @MethodSource("serializerFactoryProvider")
-    public void testClassWithPrivateConstructor(SerializerFactory factory) throws SerializationException {
+    public void classWithPrivateConstructor(SerializerFactory factory) throws SerializationException {
         Column[] cols = new Column[] {
             new Column("pLongCol", LONG, false),
         };
 
-        SchemaDescriptor schema = new SchemaDescriptor(1, cols, cols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 1, cols, cols);
 
         final Object key = TestObjectWithPrivateConstructor.randomObject(rnd);
         final Object val = TestObjectWithPrivateConstructor.randomObject(rnd);
@@ -257,12 +260,12 @@ public class JavaSerializerTest {
      */
     @ParameterizedTest
     @MethodSource("serializerFactoryProvider")
-    public void testClassWithNoDefaultConstructor(SerializerFactory factory) {
+    public void classWithNoDefaultConstructor(SerializerFactory factory) {
         Column[] cols = new Column[] {
             new Column("pLongCol", LONG, false),
         };
 
-        SchemaDescriptor schema = new SchemaDescriptor(1, cols, cols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 1, cols, cols);
 
         final Object key = WrongTestObject.randomObject(rnd);
         final Object val = WrongTestObject.randomObject(rnd);
@@ -275,12 +278,12 @@ public class JavaSerializerTest {
      */
     @ParameterizedTest
     @MethodSource("serializerFactoryProvider")
-    public void testPrivateClass(SerializerFactory factory) throws SerializationException {
+    public void privateClass(SerializerFactory factory) throws SerializationException {
         Column[] cols = new Column[] {
             new Column("pLongCol", LONG, false),
         };
 
-        SchemaDescriptor schema = new SchemaDescriptor(1, cols, cols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 1, cols, cols);
 
         final Object key = PrivateTestObject.randomObject(rnd);
         final Object val = PrivateTestObject.randomObject(rnd);
@@ -301,7 +304,7 @@ public class JavaSerializerTest {
      */
     @ParameterizedTest
     @MethodSource("serializerFactoryProvider")
-    public void testClassLoader(SerializerFactory factory) throws SerializationException {
+    public void classLoader(SerializerFactory factory) throws SerializationException {
         final ClassLoader loader = Thread.currentThread().getContextClassLoader();
         try {
             Thread.currentThread().setContextClassLoader(new DynamicClassLoader(getClass().getClassLoader()));
@@ -316,7 +319,7 @@ public class JavaSerializerTest {
                 new Column("col2", LONG, false),
             };
 
-            SchemaDescriptor schema = new SchemaDescriptor(1, keyCols, valCols);
+            SchemaDescriptor schema = new SchemaDescriptor(tableId, 1, keyCols, valCols);
 
             final Class<?> valClass = createGeneratedObjectClass(long.class);
             final ObjectFactory<?> objFactory = new ObjectFactory<>(valClass);
@@ -355,7 +358,7 @@ public class JavaSerializerTest {
         Column[] keyCols = new Column[] {new Column("key", keyType, false)};
         Column[] valCols = new Column[] {new Column("val", valType, false)};
 
-        SchemaDescriptor schema = new SchemaDescriptor(1, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 1, keyCols, valCols);
 
         Serializer serializer = factory.create(schema, key.getClass(), val.getClass());
 
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java
index db9a9fd..01bda07 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java
@@ -23,8 +23,8 @@ import java.util.BitSet;
 import java.util.Objects;
 import java.util.Random;
 import java.util.UUID;
-import org.apache.ignite.internal.schema.Bitmask;
 import org.apache.ignite.internal.schema.Column;
+import org.apache.ignite.internal.schema.NativeTypes;
 import org.apache.ignite.internal.schema.Row;
 import org.apache.ignite.internal.schema.RowAssembler;
 import org.apache.ignite.internal.schema.TestUtils;
@@ -37,15 +37,15 @@ import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
-import static org.apache.ignite.internal.schema.NativeType.BYTE;
-import static org.apache.ignite.internal.schema.NativeType.BYTES;
-import static org.apache.ignite.internal.schema.NativeType.DOUBLE;
-import static org.apache.ignite.internal.schema.NativeType.FLOAT;
-import static org.apache.ignite.internal.schema.NativeType.INTEGER;
-import static org.apache.ignite.internal.schema.NativeType.LONG;
-import static org.apache.ignite.internal.schema.NativeType.SHORT;
-import static org.apache.ignite.internal.schema.NativeType.STRING;
-import static org.apache.ignite.internal.schema.NativeType.UUID;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
+import static org.apache.ignite.internal.schema.NativeTypes.DOUBLE;
+import static org.apache.ignite.internal.schema.NativeTypes.FLOAT;
+import static org.apache.ignite.internal.schema.NativeTypes.INTEGER;
+import static org.apache.ignite.internal.schema.NativeTypes.LONG;
+import static org.apache.ignite.internal.schema.NativeTypes.SHORT;
+import static org.apache.ignite.internal.schema.NativeTypes.UUID;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
+import static org.apache.ignite.internal.schema.NativeTypes.STRING;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -73,7 +73,7 @@ public class FieldAccessorTest {
      * @throws Exception If failed.
      */
     @Test
-    public void testFieldAccessor() throws Exception {
+    public void fieldAccessor() throws Exception {
         Column[] cols = new Column[] {
             new Column("pByteCol", BYTE, false),
             new Column("pShortCol", SHORT, false),
@@ -90,7 +90,7 @@ public class FieldAccessorTest {
             new Column("doubleCol", DOUBLE, false),
 
             new Column("uuidCol", UUID, false),
-            new Column("bitmaskCol", Bitmask.of(9), false),
+            new Column("bitmaskCol", NativeTypes.bitmaskOf(9), false),
             new Column("stringCol", STRING, false),
             new Column("bytesCol", BYTES, false),
         };
@@ -140,7 +140,7 @@ public class FieldAccessorTest {
      * @throws Exception If failed.
      */
     @Test
-    public void testNullableFieldsAccessor() throws Exception {
+    public void nullableFieldsAccessor() throws Exception {
         Column[] cols = new Column[] {
             new Column("intCol", INTEGER, true),
             new Column("longCol", LONG, true),
@@ -183,7 +183,7 @@ public class FieldAccessorTest {
      * @throws Exception If failed.
      */
     @Test
-    public void testIdentityAccessor() throws Exception {
+    public void identityAccessor() throws Exception {
         final FieldAccessor accessor = FieldAccessor.createIdentityAccessor(
             new Column("col0", STRING, true),
             0,
@@ -201,7 +201,7 @@ public class FieldAccessorTest {
      *
      */
     @Test
-    public void testWrongIdentityAccessor() {
+    public void wrongIdentityAccessor() {
         final FieldAccessor accessor = FieldAccessor.createIdentityAccessor(
             new Column("col0", STRING, true),
             42,
diff --git a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ITDistributedTableTest.java b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ITDistributedTableTest.java
index 7881e1b..a1c69c4 100644
--- a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ITDistributedTableTest.java
+++ b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ITDistributedTableTest.java
@@ -28,7 +28,7 @@ import java.util.stream.IntStream;
 import org.apache.ignite.internal.affinity.RendezvousAffinityFunction;
 import org.apache.ignite.internal.schema.ByteBufferRow;
 import org.apache.ignite.internal.schema.Column;
-import org.apache.ignite.internal.schema.NativeType;
+import org.apache.ignite.internal.schema.NativeTypes;
 import org.apache.ignite.internal.schema.Row;
 import org.apache.ignite.internal.schema.RowAssembler;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
@@ -97,11 +97,11 @@ public class ITDistributedTableTest {
     private ClusterService client;
 
     /** Schema. */
-    public static SchemaDescriptor SCHEMA = new SchemaDescriptor(1, new Column[] {
-        new Column("key", NativeType.LONG, false)
-    }, new Column[] {
-        new Column("value", NativeType.LONG, false)
-    });
+    public static SchemaDescriptor SCHEMA = new SchemaDescriptor(UUID.randomUUID(),
+        1,
+        new Column[] {new Column("key", NativeTypes.LONG, false)},
+        new Column[] {new Column("value", NativeTypes.LONG, false)}
+    );
 
     /** Cluster. */
     private ArrayList<ClusterService> cluster = new ArrayList<>();
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/AbstractTableView.java b/modules/table/src/main/java/org/apache/ignite/internal/table/AbstractTableView.java
index cf23e08..c5fe733 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/AbstractTableView.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/AbstractTableView.java
@@ -29,7 +29,7 @@ abstract class AbstractTableView {
     /** Internal table. */
     protected final InternalTable tbl;
 
-    /** Schema manager. */
+    /** Schema registry. */
     protected final SchemaRegistry schemaReg;
 
     /**
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java b/modules/table/src/main/java/org/apache/ignite/internal/table/ColumnNotFoundException.java
similarity index 52%
copy from modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
copy to modules/table/src/main/java/org/apache/ignite/internal/table/ColumnNotFoundException.java
index ddc5b74..1fed0f0 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/ColumnNotFoundException.java
@@ -15,34 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
-
-import java.util.Arrays;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
+package org.apache.ignite.internal.table;
 
 /**
- *
+ * Invalid tuple invocation exception is thrown when tuple doesn't match the table schema.
  */
-public class ColumnTest {
-    /**
-     *
-     */
-    @Test
-    public void testCompareColumns() {
-        Column[] cols = new Column[] {
-            new Column("C", NativeType.BYTES, false),
-            new Column("B", NativeType.INTEGER, false),
-            new Column("AD", NativeType.STRING, false),
-            new Column("AA", NativeType.STRING, false),
-        };
-
-        Arrays.sort(cols);
-
-        assertEquals("B", cols[0].name());
-        assertEquals("C", cols[1].name());
-        assertEquals("AA", cols[2].name());
-        assertEquals("AD", cols[3].name());
+public class ColumnNotFoundException extends SchemaMismatchException {
+    /** */
+    public ColumnNotFoundException(String msg) {
+        super(msg);
     }
 }
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/KVBinaryViewImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/KVBinaryViewImpl.java
index 474f049..31a578e 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/KVBinaryViewImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/KVBinaryViewImpl.java
@@ -40,7 +40,6 @@ import org.jetbrains.annotations.NotNull;
  * regarding the binary object concept.
  */
 public class KVBinaryViewImpl extends AbstractTableView implements KeyValueBinaryView {
-
     /** Marshaller. */
     private final TupleMarshallerImpl marsh;
 
@@ -268,7 +267,7 @@ public class KVBinaryViewImpl extends AbstractTableView implements KeyValueBinar
 
     /** {@inheritDoc} */
     @Override public TupleBuilder tupleBuilder() {
-        return new TupleBuilderImpl();
+        return new TupleBuilderImpl(schemaReg.schema());
     }
 
     /**
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java b/modules/table/src/main/java/org/apache/ignite/internal/table/SchemaMismatchException.java
similarity index 52%
copy from modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
copy to modules/table/src/main/java/org/apache/ignite/internal/table/SchemaMismatchException.java
index ddc5b74..6c04e80 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/SchemaMismatchException.java
@@ -15,34 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
+package org.apache.ignite.internal.table;
 
-import java.util.Arrays;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.apache.ignite.lang.IgniteException;
 
 /**
- *
+ * Invalid tuple invocation exception is thrown when tuple doesn't match the table schema.
  */
-public class ColumnTest {
-    /**
-     *
-     */
-    @Test
-    public void testCompareColumns() {
-        Column[] cols = new Column[] {
-            new Column("C", NativeType.BYTES, false),
-            new Column("B", NativeType.INTEGER, false),
-            new Column("AD", NativeType.STRING, false),
-            new Column("AA", NativeType.STRING, false),
-        };
-
-        Arrays.sort(cols);
-
-        assertEquals("B", cols[0].name());
-        assertEquals("C", cols[1].name());
-        assertEquals("AA", cols[2].name());
-        assertEquals("AD", cols[3].name());
+public class SchemaMismatchException extends IgniteException {
+    /** */
+    public SchemaMismatchException(String msg) {
+        super(msg);
     }
 }
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java
index 284be44..58ba9cc 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java
@@ -310,7 +310,7 @@ public class TableImpl extends AbstractTableView implements Table {
 
     /** {@inheritDoc} */
     @Override public TupleBuilder tupleBuilder() {
-        return new TupleBuilderImpl();
+        return new TupleBuilderImpl(schemaReg.schema());
     }
 
     /**
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TableRow.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TableRow.java
index b9955fc..74ed57a 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TableRow.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TableRow.java
@@ -81,6 +81,11 @@ public class TableRow extends RowChunkAdapter {
         return row;
     }
 
+    /** */
+    @Override public boolean contains(String colName) {
+        return schema.column(colName) != null;
+    }
+
     /** Key column chunk. */
     private class KeyRowChunk extends RowChunkAdapter {
         /** {@inheritDoc} */
@@ -99,6 +104,11 @@ public class TableRow extends RowChunkAdapter {
 
             return col;
         }
+
+        /** */
+        @Override public boolean contains(String colName) {
+            return schema.column(colName) != null;
+        }
     }
 
     /** Value column chunk. */
@@ -119,5 +129,10 @@ public class TableRow extends RowChunkAdapter {
 
             return col;
         }
+
+        /** */
+        @Override public boolean contains(String colName) {
+            return schema.column(colName) != null;
+        }
     }
 }
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java
index d457077..c1be439 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java
@@ -21,8 +21,11 @@ import java.util.BitSet;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
+import java.util.Objects;
 import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjects;
+import org.apache.ignite.internal.schema.Column;
+import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.table.Tuple;
 import org.apache.ignite.table.TupleBuilder;
 
@@ -33,15 +36,28 @@ public class TupleBuilderImpl implements TupleBuilder, Tuple {
     /** Columns values. */
     private final Map<String, Object> map;
 
+    /** Current schema descriptor. */
+    private final SchemaDescriptor schemaDesc;
+
     /**
      * Constructor.
      */
-    public TupleBuilderImpl() {
+    public TupleBuilderImpl(SchemaDescriptor schemaDesc) {
+        Objects.requireNonNull(schemaDesc);
+
+        this.schemaDesc = schemaDesc;
         map = new HashMap<>();
     }
 
     /** {@inheritDoc} */
     @Override public TupleBuilder set(String colName, Object value) {
+        Column col = schemaDesc.column(colName);
+
+        if (col == null)
+            throw new ColumnNotFoundException("Column not found [col=" + colName + "schema=" + schemaDesc + ']');
+
+        col.validate(value);
+
         map.put(colName, value);
 
         return this;
@@ -52,6 +68,11 @@ public class TupleBuilderImpl implements TupleBuilder, Tuple {
         return this;
     }
 
+    /** {@inheritDoc} */
+    @Override public boolean contains(String colName) {
+        return map.containsKey(colName);
+    }
+
     @Override public <T> T value(String colName) {
         return (T)map.get(colName);
     }
@@ -107,4 +128,13 @@ public class TupleBuilderImpl implements TupleBuilder, Tuple {
     @Override public BitSet bitmaskValue(String colName) {
         return value(colName);
     }
+
+    /**
+     * Get schema descriptor.
+     *
+     * @return Schema descriptor.
+     */
+    public SchemaDescriptor schema() {
+        return schemaDesc;
+    }
 }
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
index f418f3c..c944c3c 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
@@ -17,6 +17,10 @@
 
 package org.apache.ignite.internal.table;
 
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Objects;
+import java.util.UUID;
 import org.apache.ignite.internal.schema.ByteBufferRow;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.Columns;
@@ -27,6 +31,7 @@ import org.apache.ignite.internal.schema.marshaller.TupleMarshaller;
 import org.apache.ignite.internal.schema.SchemaRegistry;
 import org.apache.ignite.table.Tuple;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import static org.apache.ignite.internal.schema.marshaller.MarshallerUtil.getValueSize;
 
@@ -52,10 +57,10 @@ public class TupleMarshallerImpl implements TupleMarshaller {
     }
 
     /** {@inheritDoc} */
-    @Override public Row marshal(Tuple keyTuple, Tuple valTuple) {
+    @Override public Row marshal(@NotNull Tuple keyTuple, @Nullable Tuple valTuple) {
         final SchemaDescriptor schema = schemaReg.schema();
 
-        assert keyTuple instanceof TupleBuilderImpl;
+        validate(keyTuple, schema.keyColumns());
 
         final RowAssembler rowBuilder = createAssembler(schema, keyTuple, valTuple);
 
@@ -66,6 +71,8 @@ public class TupleMarshallerImpl implements TupleMarshaller {
         }
 
         if (valTuple != null) {
+            validate(valTuple, schema.valueColumns());
+
             for (int i = 0; i < schema.valueColumns().length(); i++) {
                 final Column col = schema.valueColumns().column(i);
 
@@ -76,6 +83,21 @@ public class TupleMarshallerImpl implements TupleMarshaller {
         return new Row(schema, new ByteBufferRow(rowBuilder.build()));
     }
 
+    /** */
+    private void validate(Tuple tuple, Columns columns) {
+        if (tuple instanceof TupleBuilderImpl) {
+            TupleBuilderImpl t0 = (TupleBuilderImpl)tuple;
+
+            SchemaDescriptor expSchema = schemaReg.schema(t0.schema().version());
+
+            if (!Objects.equals(t0.schema(), expSchema))
+                throw new SchemaMismatchException("Unexpected schema: [expected=" + expSchema + ", actual=" + t0.schema() + ']');
+        }
+        else {
+            Arrays.stream(columns.columns()).forEach(c -> c.validate(tuple.value(c.name())));
+        }
+    }
+
     /**
      * Creates {@link RowAssembler} for key-value tuples.
      *
@@ -85,7 +107,7 @@ public class TupleMarshallerImpl implements TupleMarshaller {
      */
     private RowAssembler createAssembler(SchemaDescriptor schema, Tuple keyTuple, Tuple valTuple) {
         final ObjectStatistic keyStat = collectObjectStats(schema.keyColumns(), keyTuple);
-        final ObjectStatistic valStat = collectObjectStats(schema.keyColumns(), valTuple);
+        final ObjectStatistic valStat = collectObjectStats(schema.valueColumns(), valTuple);
 
         int size = RowAssembler.rowSize(
             schema.keyColumns(), keyStat.nonNullCols, keyStat.nonNullColsSize,
@@ -100,7 +122,15 @@ public class TupleMarshallerImpl implements TupleMarshaller {
      * @param rowAsm Row assembler.
      */
     private void writeColumn(Tuple tup, Column col, RowAssembler rowAsm) {
-        if (tup.value(col.name()) == null) {
+        Object val;
+
+        if (!tup.contains(col.name()))
+            val = col.defaultValue();
+        else {
+            val = tup.value(col.name());
+        }
+
+        if (val == null) {
             rowAsm.appendNull();
 
             return;
@@ -108,52 +138,52 @@ public class TupleMarshallerImpl implements TupleMarshaller {
 
         switch (col.type().spec()) {
             case BYTE: {
-                rowAsm.appendByte(tup.byteValue(col.name()));
+                rowAsm.appendByte((byte)val);
 
                 break;
             }
             case SHORT: {
-                rowAsm.appendShort(tup.shortValue(col.name()));
+                rowAsm.appendShort((short)val);
 
                 break;
             }
             case INTEGER: {
-                rowAsm.appendInt(tup.intValue(col.name()));
+                rowAsm.appendInt((int)val);
 
                 break;
             }
             case LONG: {
-                rowAsm.appendLong(tup.longValue(col.name()));
+                rowAsm.appendLong((long)val);
 
                 break;
             }
             case FLOAT: {
-                rowAsm.appendFloat(tup.floatValue(col.name()));
+                rowAsm.appendFloat((float)val);
 
                 break;
             }
             case DOUBLE: {
-                rowAsm.appendDouble(tup.doubleValue(col.name()));
+                rowAsm.appendDouble((double)val);
 
                 break;
             }
             case UUID: {
-                rowAsm.appendUuid(tup.value(col.name()));
+                rowAsm.appendUuid((UUID)val);
 
                 break;
             }
             case STRING: {
-                rowAsm.appendString(tup.stringValue(col.name()));
+                rowAsm.appendString((String)val);
 
                 break;
             }
             case BYTES: {
-                rowAsm.appendBytes(tup.value(col.name()));
+                rowAsm.appendBytes((byte[])val);
 
                 break;
             }
             case BITMASK: {
-                rowAsm.appendBitmask(tup.value(col.name()));
+                rowAsm.appendBitmask((BitSet)val);
 
                 break;
             }
@@ -177,7 +207,9 @@ public class TupleMarshallerImpl implements TupleMarshaller {
         int size = 0;
 
         for (int i = cols.firstVarlengthColumn(); i < cols.length(); i++) {
-            final Object val = tup.value(cols.column(i).name());
+            Column col = cols.column(i);
+
+            final Object val = tup.contains(col.name()) ? tup.value(col.name()) : col.defaultValue();
 
             if (val == null || cols.column(i).type().spec().fixedLength())
                 continue;
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/KVViewOperationsTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/KVViewOperationsTest.java
index 0c63515..016931f 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/KVViewOperationsTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/KVViewOperationsTest.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.internal.table;
 
 import org.apache.ignite.internal.schema.Column;
-import org.apache.ignite.internal.schema.NativeType;
+import org.apache.ignite.internal.schema.NativeTypes;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.table.impl.DummyInternalTableImpl;
 import org.apache.ignite.internal.table.impl.DummySchemaManagerImpl;
@@ -41,15 +41,19 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
  * TODO: IGNITE-14487 Check key fields in Tuple is ignored for value or exception is thrown?
  */
 public class KVViewOperationsTest {
+    /** Table ID test value. */
+    public final java.util.UUID tableId = java.util.UUID.randomUUID();
+
     /**
      *
      */
     @Test
-    public void testPut() {
+    public void put() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         KeyValueBinaryView tbl = new KVBinaryViewImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -87,11 +91,12 @@ public class KVViewOperationsTest {
      *
      */
     @Test
-    public void testPutIfAbsent() {
+    public void putIfAbsent() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         KeyValueBinaryView tbl = new KVBinaryViewImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -119,11 +124,12 @@ public class KVViewOperationsTest {
      *
      */
     @Test
-    public void testGetAndPut() {
+    public void getAndPut() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         KeyValueBinaryView tbl = new KVBinaryViewImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -153,11 +159,12 @@ public class KVViewOperationsTest {
      *
      */
     @Test
-    public void testRemove() {
+    public void remove() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         KeyValueBinaryView tbl = new KVBinaryViewImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -195,11 +202,12 @@ public class KVViewOperationsTest {
      *
      */
     @Test
-    public void testRemoveExact() {
+    public void removeExact() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         KeyValueBinaryView tbl = new KVBinaryViewImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -251,11 +259,12 @@ public class KVViewOperationsTest {
      *
      */
     @Test
-    public void testReplace() {
+    public void replace() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         KeyValueBinaryView tbl = new KVBinaryViewImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -296,11 +305,12 @@ public class KVViewOperationsTest {
      *
      */
     @Test
-    public void testReplaceExact() {
+    public void replaceExact() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         KeyValueBinaryView tbl = new KVBinaryViewImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/StrictSchemaOperationsTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/StrictSchemaOperationsTest.java
new file mode 100644
index 0000000..8d919ab
--- /dev/null
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/StrictSchemaOperationsTest.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.table;
+
+import org.apache.ignite.internal.schema.Column;
+import org.apache.ignite.internal.schema.InvalidTypeException;
+import org.apache.ignite.internal.schema.NativeTypes;
+import org.apache.ignite.internal.schema.SchemaDescriptor;
+import org.apache.ignite.internal.table.impl.DummyInternalTableImpl;
+import org.apache.ignite.internal.table.impl.DummySchemaManagerImpl;
+import org.apache.ignite.table.Table;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * Check data by strict schema.
+ */
+public class StrictSchemaOperationsTest {
+    /** Table ID test value. */
+    public final java.util.UUID tableId = java.util.UUID.randomUUID();
+
+    /**
+     *
+     */
+    @Test
+    public void columnNotExist() {
+        SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
+            1,
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
+        );
+
+        Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
+
+        assertThrows(ColumnNotFoundException.class, () -> tbl.tupleBuilder().set("invalidCol", 0));
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void typeMismatch() {
+        SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
+            1,
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {
+                new Column("valString", NativeTypes.stringOf(3), true),
+                new Column("valBytes", NativeTypes.blobOf(3), true)
+            }
+        );
+
+        Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
+
+        // Check not-nullable column.
+        assertThrows(IllegalArgumentException.class, () -> tbl.tupleBuilder().set("id", null));
+
+        // Check length of the string column
+        assertThrows(InvalidTypeException.class, () -> tbl.tupleBuilder().set("valString", "qweqwe"));
+
+        // Check length of the string column
+        assertThrows(InvalidTypeException.class, () -> tbl.tupleBuilder().set("valBytes", new byte[] {0, 1, 2, 3}));
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void stringTypeMatch() {
+        SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
+            1,
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {
+                new Column("valString", NativeTypes.stringOf(3), true),
+                new Column("valBytes", NativeTypes.blobOf(3), true)
+            }
+        );
+
+        Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
+
+        tbl.tupleBuilder().set("valString", "qwe");
+        tbl.tupleBuilder().set("valString", "qw");
+        tbl.tupleBuilder().set("valString", "q");
+        tbl.tupleBuilder().set("valString", "");
+        tbl.tupleBuilder().set("valString", null);
+
+        // Chek string 3 char length and 9 bytes.
+        tbl.tupleBuilder().set("valString", "我是谁");
+    }
+}
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/TableBinaryViewOperationsTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/TableBinaryViewOperationsTest.java
index 9c38102..f9eea5b 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/TableBinaryViewOperationsTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/TableBinaryViewOperationsTest.java
@@ -18,10 +18,12 @@
 package org.apache.ignite.internal.table;
 
 import org.apache.ignite.internal.schema.Column;
-import org.apache.ignite.internal.schema.NativeType;
+import org.apache.ignite.internal.schema.InvalidTypeException;
+import org.apache.ignite.internal.schema.NativeTypes;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.table.impl.DummyInternalTableImpl;
 import org.apache.ignite.internal.table.impl.DummySchemaManagerImpl;
+import org.apache.ignite.internal.table.impl.TestTupleBuilder;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.table.Tuple;
 import org.junit.jupiter.api.Assertions;
@@ -29,6 +31,7 @@ import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
@@ -39,15 +42,19 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
  * TODO: IGNITE-14486 Add tests for async operations.
  */
 public class TableBinaryViewOperationsTest {
+    /** Table ID test value. */
+    public final java.util.UUID tableId = java.util.UUID.randomUUID();
+
     /**
      *
      */
     @Test
-    public void testInsert() {
+    public void insert() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -62,13 +69,13 @@ public class TableBinaryViewOperationsTest {
         assertTrue(tbl.insert(tuple));
 
         assertEqualsRows(schema, tuple, tbl.get(tuple));
-        assertEqualsRows(schema, tuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1).build()));
+        assertEqualsRows(schema, tuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1L).build()));
 
         // Ignore insert operation for exited row.
         assertFalse(tbl.insert(newTuple));
 
         assertEqualsRows(schema, tuple, tbl.get(newTuple));
-        assertEqualsRows(schema, tuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1).build()));
+        assertEqualsRows(schema, tuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1L).build()));
 
         assertNull(tbl.get(nonExistedTuple));
     }
@@ -77,11 +84,12 @@ public class TableBinaryViewOperationsTest {
      *
      */
     @Test
-    public void testUpsert() {
+    public void upsert() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -97,13 +105,13 @@ public class TableBinaryViewOperationsTest {
         tbl.upsert(tuple);
 
         assertEqualsRows(schema, tuple, tbl.get(tuple));
-        assertEqualsRows(schema, tuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1).build()));
+        assertEqualsRows(schema, tuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1L).build()));
 
         // Update exited row.
         tbl.upsert(newTuple);
 
         assertEqualsRows(schema, newTuple, tbl.get(tuple));
-        assertEqualsRows(schema, newTuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1).build()));
+        assertEqualsRows(schema, newTuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1L).build()));
 
         assertNull(tbl.get(nonExistedTuple));
     }
@@ -112,11 +120,12 @@ public class TableBinaryViewOperationsTest {
      *
      */
     @Test
-    public void testGetAndUpsert() {
+    public void getAndUpsert() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -131,24 +140,25 @@ public class TableBinaryViewOperationsTest {
         assertNull(tbl.getAndUpsert(tuple));
 
         assertEqualsRows(schema, tuple, tbl.get(tuple));
-        assertEqualsRows(schema, tuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1).build()));
+        assertEqualsRows(schema, tuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1L).build()));
 
         // Update exited row.
         assertEqualsRows(schema, tuple, tbl.getAndUpsert(newTuple));
 
         assertEqualsRows(schema, newTuple, tbl.get(tuple));
-        assertEqualsRows(schema, newTuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1).build()));
+        assertEqualsRows(schema, newTuple, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1L).build()));
     }
 
     /**
      *
      */
     @Test
-    public void testRemove() {
+    public void remove() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -174,11 +184,12 @@ public class TableBinaryViewOperationsTest {
      *
      */
     @Test
-    public void testRemoveExact() {
+    public void removeExact() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -225,11 +236,12 @@ public class TableBinaryViewOperationsTest {
      *
      */
     @Test
-    public void testReplace() {
+    public void replace() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -244,7 +256,7 @@ public class TableBinaryViewOperationsTest {
         assertFalse(tbl.replace(tuple));
 
         assertNull(tbl.get(keyTuple));
-        assertNull(tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1).build()));
+        assertNull(tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1L).build()));
 
         // Insert row.
         tbl.insert(tuple);
@@ -253,18 +265,19 @@ public class TableBinaryViewOperationsTest {
         assertTrue(tbl.replace(tuple2));
 
         assertEqualsRows(schema, tuple2, tbl.get(keyTuple));
-        assertEqualsRows(schema, tuple2, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1).build()));
+        assertEqualsRows(schema, tuple2, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1L).build()));
     }
 
     /**
      *
      */
     @Test
-    public void testReplaceExact() {
+    public void replaceExact() {
         SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
             1,
-            new Column[] {new Column("id", NativeType.LONG, false)},
-            new Column[] {new Column("val", NativeType.LONG, false)}
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {new Column("val", NativeTypes.LONG, false)}
         );
 
         Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
@@ -289,7 +302,75 @@ public class TableBinaryViewOperationsTest {
         assertTrue(tbl.replace(tuple, tuple2));
 
         assertEqualsRows(schema, tuple2, tbl.get(keyTuple));
-        assertEqualsRows(schema, tuple2, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1).build()));
+        assertEqualsRows(schema, tuple2, tbl.get(tbl.tupleBuilder().set("id", 1L).set("val", -1L).build()));
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void validateSchema() {
+        SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
+            1,
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {
+                new Column("val", NativeTypes.LONG, true),
+                new Column("str", NativeTypes.stringOf(3), true),
+                new Column("blob", NativeTypes.blobOf(3), true)
+            }
+        );
+
+        Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
+
+        final Tuple keyTuple0 = new TestTupleBuilder().set("id", 0).set("id1", 0).build();
+        final Tuple keyTuple1 = new TestTupleBuilder().set("id1", 0).build();
+        final Tuple tuple0 = new TestTupleBuilder().set("id", 1L).set("str", "qweqweqwe").set("val", 11L).build();
+        final Tuple tuple1 = new TestTupleBuilder().set("id", 1L).set("blob", new byte[] {0, 1, 2, 3}).set("val", 22L).build();
+
+        assertThrows(InvalidTypeException.class, () -> tbl.get(keyTuple0));
+        assertThrows(IllegalArgumentException.class, () -> tbl.get(keyTuple1));
+
+        assertThrows(InvalidTypeException.class, () -> tbl.replace(tuple0));
+        assertThrows(InvalidTypeException.class, () -> tbl.replace(tuple1));
+
+        assertThrows(InvalidTypeException.class, () -> tbl.insert(tuple0));
+        assertThrows(InvalidTypeException.class, () -> tbl.insert(tuple1));
+
+        assertThrows(InvalidTypeException.class, () -> tbl.replace(tuple0));
+        assertThrows(InvalidTypeException.class, () -> tbl.replace(tuple1));
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void defaultValues() {
+        SchemaDescriptor schema = new SchemaDescriptor(
+            tableId,
+            1,
+            new Column[] {new Column("id", NativeTypes.LONG, false)},
+            new Column[] {
+                new Column("val", NativeTypes.LONG, true, () -> 28L),
+                new Column("str", NativeTypes.stringOf(3), true, () -> "ABC"),
+                new Column("blob", NativeTypes.blobOf(3), true, () -> new byte[] {0, 1, 2})
+            }
+        );
+
+        Table tbl = new TableImpl(new DummyInternalTableImpl(), new DummySchemaManagerImpl(schema));
+
+        final Tuple keyTuple0 = tbl.tupleBuilder().set("id", 0L).build();
+        final Tuple keyTuple1 = tbl.tupleBuilder().set("id", 1L).build();
+
+        final Tuple tuple0 = tbl.tupleBuilder().set("id", 0L).build();
+        final Tuple tupleExpected0 = tbl.tupleBuilder().set("id", 0L).set("val", 28L).set("str", "ABC").set("blob", new byte[] {0, 1, 2}).build();
+        final Tuple tuple1 = tbl.tupleBuilder().set("id", 1L).set("val", null).set("str", null).set("blob", null).build();
+
+        tbl.insert(tuple0);
+        tbl.insert(tuple1);
+
+        assertEqualsRows(schema, tupleExpected0, tbl.get(keyTuple0));
+        assertEqualsRows(schema, tuple1, tbl.get(keyTuple1));
     }
 
     /**
@@ -343,7 +424,10 @@ public class TableBinaryViewOperationsTest {
             final Object val1 = expected.value(col.name());
             final Object val2 = actual.value(col.name());
 
-            Assertions.assertEquals(val1, val2, "Key columns equality check failed: colIdx=" + col.schemaIndex());
+            if (val1 instanceof byte[] && val2 instanceof byte[])
+                Assertions.assertArrayEquals((byte[])val1, (byte[])val2, "Equality check failed: colIdx=" + col.schemaIndex());
+            else
+               Assertions.assertEquals(val1, val2, "Equality check failed: colIdx=" + col.schemaIndex());
         }
     }
 }
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java b/modules/table/src/test/java/org/apache/ignite/internal/table/impl/TestTupleBuilder.java
similarity index 85%
copy from modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java
copy to modules/table/src/test/java/org/apache/ignite/internal/table/impl/TestTupleBuilder.java
index d457077..00450cf 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/impl/TestTupleBuilder.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.table;
+package org.apache.ignite.internal.table.impl;
 
 import java.util.BitSet;
 import java.util.HashMap;
@@ -24,34 +24,37 @@ import java.util.UUID;
 import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjects;
 import org.apache.ignite.table.Tuple;
-import org.apache.ignite.table.TupleBuilder;
 
 /**
- * Buildable tuple.
+ * Dummy table storage implementation.
  */
-public class TupleBuilderImpl implements TupleBuilder, Tuple {
+public class TestTupleBuilder implements Tuple {
     /** Columns values. */
-    private final Map<String, Object> map;
+    private final Map<String, Object> map = new HashMap<>();
 
     /**
      * Constructor.
      */
-    public TupleBuilderImpl() {
-        map = new HashMap<>();
+    public TestTupleBuilder() {
     }
 
-    /** {@inheritDoc} */
-    @Override public TupleBuilder set(String colName, Object value) {
+    public TestTupleBuilder set(String colName, Object value) {
         map.put(colName, value);
 
         return this;
     }
 
-    /** {@inheritDoc} */
-    @Override public Tuple build() {
+    /** */
+    public Tuple build() {
         return this;
     }
 
+    /** {@inheritDoc} */
+    @Override public boolean contains(String colName) {
+        return map.containsKey(colName);
+    }
+
+    /** {@inheritDoc} */
     @Override public <T> T value(String colName) {
         return (T)map.get(colName);
     }