You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2021/06/09 19:36:27 UTC

[ignite-3] 15/15: WIP. Styles.

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

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

commit e5d6b43683d0ccc87543467aca7e0ce6e6c909bf
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Wed Jun 9 14:18:40 2021 +0300

    WIP. Styles.
---
 .../apache/ignite/internal/schema/BinaryRow.java   |  22 +-
 .../ignite/internal/schema/ByteBufferRow.java      |   2 -
 .../org/apache/ignite/internal/schema/Columns.java |   3 +
 .../asm/IdentityMarshallerCodeGenerator.java       |   2 +-
 .../asm/ObjectMarshallerCodeGenerator.java         |   2 +-
 .../marshaller/reflection/JavaSerializer.java      |  10 +-
 .../ignite/internal/schema/row/ChunkFormat.java    | 231 ++++---
 .../ignite/internal/schema/row/ChunkReader.java    | 128 ++--
 .../ignite/internal/schema/row/ChunkWriter.java    |  87 +--
 .../internal/schema/row/ExpandableByteBuf.java     |   6 +-
 .../org/apache/ignite/internal/schema/row/Row.java |  12 +-
 .../ignite/internal/schema/row/RowAssembler.java   |  75 ++-
 .../schema/RowAssemblerAdvancedSchemaTest.java     | 118 ++--
 .../schema/RowAssemblerSimpleSchemaTest.java       | 218 +++---
 .../ignite/internal/schema/RowAssemblerTest.java   | 738 ---------------------
 .../org/apache/ignite/internal/schema/RowTest.java |  26 +-
 .../ignite/internal/table/TupleMarshallerImpl.java |  10 +-
 17 files changed, 538 insertions(+), 1152 deletions(-)

diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
index 1826684..8619449 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
@@ -26,30 +26,21 @@ import java.nio.ByteBuffer;
  * The class contains low-level methods to read row data.
  */
 public interface BinaryRow {
-    /** */
+    /** Row schema version field offset. */
     int SCHEMA_VERSION_OFFSET = 0;
 
-    /** */
+    /** Row flags field offset. */
     int FLAGS_FIELD_OFFSET = SCHEMA_VERSION_OFFSET + 2 /* version length */;
 
-    /** */
+    /** Key hash field offset. */
     int KEY_HASH_FIELD_OFFSET = FLAGS_FIELD_OFFSET + 2 /* flags length */;
 
-    /** */
+    /** Key chunk field offset. */
     int KEY_CHUNK_OFFSET = KEY_HASH_FIELD_OFFSET + 4 /* hash length */;
 
-    /** */
+    /** Row header size. */
     int HEADER_SIZE = KEY_CHUNK_OFFSET;
 
-    /** */
-    int CHUNK_LEN_FIELD_SIZE = 4;
-
-    /** */
-    int VARLEN_TABLE_SIZE_FIELD_SIZE = 2;
-
-    /** */
-    int VARLEN_COLUMN_OFFSET_FIELD_SIZE = 2;
-
     /**
      * @return Row schema version.
      */
@@ -60,9 +51,6 @@ public interface BinaryRow {
      */
     boolean hasValue();
 
-    // TODO: IGNITE-14199. Add row version.
-    //GridRowVersion version();
-
     /**
      * Row hash code is a result of hash function applied to the row affinity columns values.
      *
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
index 170028e..6ae8889 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
@@ -129,8 +129,6 @@ public class ByteBufferRow implements BinaryRow {
 
     /** {@inheritDoc} */
     @Override public ByteBuffer keySlice() {
-        final short flags = readShort(FLAGS_FIELD_OFFSET);
-
         final int off = KEY_CHUNK_OFFSET;
         final int len = readInteger(off);
 
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 72ca1ae..d5259bc 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
@@ -188,6 +188,9 @@ public class Columns implements Serializable {
         return firstVarlenColIdx != -1;
     }
 
+    /**
+     * @return Fixsize columns size upper bound.
+     */
     public int fixsizeMaxLen() {
         return fixsizeMaxLen;
     }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java
index 3e7f05d..991c4fb 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java
@@ -21,7 +21,7 @@ import com.facebook.presto.bytecode.BytecodeNode;
 import com.facebook.presto.bytecode.ParameterizedType;
 import com.facebook.presto.bytecode.Variable;
 import com.facebook.presto.bytecode.expression.BytecodeExpressions;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.marshaller.Serializer;
 
 /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java
index 8f47eda..fe55ca0 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java
@@ -34,7 +34,7 @@ import java.lang.reflect.Field;
 import java.util.Collections;
 import java.util.EnumSet;
 import org.apache.ignite.internal.schema.Columns;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.marshaller.MarshallerUtil;
 import org.apache.ignite.internal.schema.marshaller.Serializer;
 import org.apache.ignite.lang.IgniteInternalException;
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
index 9e98d30..57b5bdd 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
@@ -85,7 +85,7 @@ public class JavaSerializer extends AbstractSerializer {
         ObjectStatistic keyStat = collectObjectStats(schema.keyColumns(), keyMarsh, key);
         ObjectStatistic valStat = collectObjectStats(schema.valueColumns(), valMarsh, val);
 
-        return new RowAssembler(schema, keyStat.nonNullCols, valStat.nonNullCols);
+        return new RowAssembler(schema, keyStat.maxChunkDataSize, keyStat.nonNullCols, valStat.maxChunkDataSize, valStat.nonNullCols);
     }
 
     /**
@@ -101,7 +101,7 @@ public class JavaSerializer extends AbstractSerializer {
             return new ObjectStatistic(0, 0);
 
         int cnt = 0;
-        int size = 0;
+        int size = cols.fixsizeMaxLen();
 
         for (int i = cols.firstVarlengthColumn(); i < cols.length(); i++) {
             final Object val = marsh.value(obj, i);
@@ -142,12 +142,12 @@ public class JavaSerializer extends AbstractSerializer {
         int nonNullCols;
 
         /** Length of all non-null columns of varlen types. */
-        int nonNullColsSize;
+        int maxChunkDataSize;
 
         /** Constructor. */
-        ObjectStatistic(int nonNullCols, int nonNullColsSize) {
+        ObjectStatistic(int nonNullCols, int maxRowSize) {
             this.nonNullCols = nonNullCols;
-            this.nonNullColsSize = nonNullColsSize;
+            this.maxChunkDataSize = maxRowSize;
         }
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
index 270420f..ba2588c 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
@@ -20,13 +20,13 @@ package org.apache.ignite.internal.schema.row;
 import org.apache.ignite.internal.schema.BinaryRow;
 
 /**
- * Chunk writers factory.
+ * Chunk format.
  */
 abstract class ChunkFormat {
-    /** First 2 bits in chunk flags. */
+    /** First two flag bits reserved for format code. */
     public static final int FORMAT_CODE_MASK = 0x03;
 
-    /** Flag indicates key chunk omits varlen table. */
+    /** Flag indicates key chunk omits vartable. */
     public static final int OMIT_NULL_MAP_FLAG = 1 << 2;
 
     /** Flag indicates value chunk omits null map. */
@@ -34,80 +34,83 @@ abstract class ChunkFormat {
 
     /** Writer factory for tiny-sized chunks. */
     private static final ChunkFormat TINY = new ChunkFormat(Byte.BYTES, Byte.BYTES, (byte)1) {
-        @Override void writeOffset(ExpandableByteBuf buf, int itemOff, int off) {
+        /** {@inheritDoc} */
+        @Override void writeVarlenOffset(ExpandableByteBuf buf, int vartblOff, int entryIdx, int off) {
             assert off < (1 << 8) && off >= 0 : "Varlen offset overflow: offset=" + off;
 
-            buf.put(itemOff, (byte)off);
+            buf.put(vartblOff + vartableEntryOffset(entryIdx), (byte)off);
         }
 
-        @Override int readOffset(BinaryRow row, int itemOff) {
-            return row.readByte(itemOff) & 0xFF;
+        /** {@inheritDoc} */
+        @Override int readVarlenOffset(BinaryRow row, int vartblOff, int entryIdx) {
+            return row.readByte(vartblOff + vartableEntryOffset(entryIdx)) & 0xFF;
         }
 
-        @Override void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size) {
+        /** {@inheritDoc} */
+        @Override void writeVartableSize(ExpandableByteBuf buf, int vartblOff, int size) {
             assert size < (1 << 8) && size >= 0 : "Vartable size overflow: size=" + size;
 
-            buf.put(vartblOff, (byte)vartblOff);
+            buf.put(vartblOff, (byte)size);
         }
 
-        @Override int readVartblSize(BinaryRow row, int vartblOff) {
+        /** {@inheritDoc} */
+        @Override int readVartableSize(BinaryRow row, int vartblOff) {
             return row.readByte(vartblOff) & 0xFF;
         }
     };
 
     /** Writer factory for med-sized chunks. */
     private static final ChunkFormat MEDIUM = new ChunkFormat(Short.BYTES, Short.BYTES, (byte)2) {
-        @Override void writeOffset(ExpandableByteBuf buf, int itemOff, int off) {
+        /** {@inheritDoc} */
+        @Override void writeVarlenOffset(ExpandableByteBuf buf, int vartblOff, int entryIdx, int off) {
             assert off < (1 << 16) && off >= 0 : "Varlen offset overflow: offset=" + off;
 
-            buf.putShort(itemOff, (short)off);
+            buf.putShort(vartblOff + vartableEntryOffset(entryIdx), (short)off);
         }
 
-        @Override int readOffset(BinaryRow row, int itemOff) {
-            return row.readShort(itemOff) & 0xFFFF;
+        /** {@inheritDoc} */
+        @Override int readVarlenOffset(BinaryRow row, int vartblOff, int entryIdx) {
+            return row.readShort(vartblOff + vartableEntryOffset(entryIdx)) & 0xFFFF;
         }
 
-        @Override void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size) {
+        /** {@inheritDoc} */
+        @Override void writeVartableSize(ExpandableByteBuf buf, int vartblOff, int size) {
             assert size < (1 << 16) && size >= 0 : "Vartable size overflow: size=" + size;
 
-            buf.putShort(vartblOff, (short)vartblOff);
+            buf.putShort(vartblOff, (short)size);
         }
 
-        @Override int readVartblSize(BinaryRow row, int vartblOff) {
+        /** {@inheritDoc} */
+        @Override int readVartableSize(BinaryRow row, int vartblOff) {
             return row.readShort(vartblOff) & 0xFFFF;
         }
     };
 
     /** Writer factory for large-sized chunks. */
     private static final ChunkFormat LARGE = new ChunkFormat(Short.BYTES, Integer.BYTES, (byte)0) {
-        @Override void writeOffset(ExpandableByteBuf buf, int itemOff, int off) {
-            buf.putInt(itemOff, off);
+        /** {@inheritDoc} */
+        @Override void writeVarlenOffset(ExpandableByteBuf buf, int vartblOff, int entryIdx, int off) {
+            buf.putInt(vartblOff + vartableEntryOffset(entryIdx), off);
         }
 
-        @Override int readOffset(BinaryRow row, int itemOff) {
-            return row.readInteger(itemOff);
+        /** {@inheritDoc} */
+        @Override int readVarlenOffset(BinaryRow row, int vartblOff, int entryIdx) {
+            return row.readInteger(vartblOff + vartableEntryOffset(entryIdx));
         }
 
-        @Override void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size) {
+        /** {@inheritDoc} */
+        @Override void writeVartableSize(ExpandableByteBuf buf, int vartblOff, int size) {
             assert size < (1 << 16) && size >= 0 : "Vartable size overflow: size=" + size;
 
-            buf.putShort(vartblOff, (short)vartblOff);
+            buf.putShort(vartblOff, (short)size);
         }
 
-        @Override int readVartblSize(BinaryRow row, int vartblOff) {
+        /** {@inheritDoc} */
+        @Override int readVartableSize(BinaryRow row, int vartblOff) {
             return row.readShort(vartblOff) & 0xFFFF;
         }
     };
 
-    /** Chunk length field size. */
-    public static final int CHUNK_LEN_FLD_SIZE = Integer.BYTES;
-
-    private final int vartableItemSize;
-
-    private final int vartableSizeFieldLen;
-
-    private final byte modeFlags;
-
     /**
      * Return chunk formatter.
      *
@@ -115,33 +118,35 @@ abstract class ChunkFormat {
      * @return Chunk formatter.
      */
     static ChunkFormat formatter(int payloadLen) {
-        if (payloadLen < 256)
-            return TINY;
+        if (payloadLen > 0) {
+            if (payloadLen < 256)
+                return TINY;
 
-        if (payloadLen < 64 * 1024)
-            return MEDIUM;
+            if (payloadLen < 64 * 1024)
+                return MEDIUM;
+        }
 
         return LARGE;
     }
 
     /**
+     * Creates chunk reader.
+     *
      * @param row Binary row.
-     * @param offset Offset.
-     * @param nullMapSize Default null-map size.
-     * @param chunkFlags Chunk flags.
-     * @return Reader.
+     * @param offset Chunk offset.
+     * @param nullMapSize Default chunk null-map size.
+     * @param chunkFlags Chunk flags. First 4-bits are meaningful.
+     * @return Chunk reader.
      */
     static ChunkReader createReader(BinaryRow row, int offset, int nullMapSize, byte chunkFlags) {
-        return fromFlags(chunkFlags).reader(row, offset,
-            (chunkFlags & OMIT_NULL_MAP_FLAG) == 0 ? nullMapSize : 0,
-            (chunkFlags & OMIT_VARTBL_FLAG) == 0);
+        return fromFlags(chunkFlags).reader(row, offset, nullMapSize, chunkFlags);
     }
 
     /**
-     * Chunk formatter from given flags.
+     * Chunk format factory method.
      *
-     * @param chunkFlags Chunk specific flags.
-     * @return Chunk formatter.
+     * @param chunkFlags Chunk specific flags. Only first 4-bits are meaningful.
+     * @return Chunk formatter regarding the provided flags.
      */
     private static ChunkFormat fromFlags(byte chunkFlags) {
         final int mode = chunkFlags & FORMAT_CODE_MASK;
@@ -156,65 +161,105 @@ abstract class ChunkFormat {
         }
     }
 
-    /**
-     * @param vartableSizeFieldLen Vartalble size field length.
-     * @param vartableItemSize Vartable item size.
-     */
-    public ChunkFormat(int vartableSizeFieldLen, int vartableItemSize, byte modeFlags) {
-        this.vartableItemSize = vartableItemSize;
-        this.vartableSizeFieldLen = vartableSizeFieldLen;
-        this.modeFlags = modeFlags;
-    }
+    /** Size of chunk length field. */
+    public static final int CHUNK_LEN_FLD_SIZE = Integer.BYTES;
 
-    int vartableSizeFieldLen() {
-        return vartableSizeFieldLen;
-    }
+    /** Size of vartable entry. */
+    private final int vartblEntrySize;
+
+    /** Size of cartable size field. */
+    private final int vartblSizeFieldSize;
 
-    int vartableItemSize() {
-        return vartableItemSize;
+    /** Format flags. */
+    private final byte flags;
+
+    /**
+     * @param vartblSizeFieldSize Size of vartalble size field (in bytes).
+     * @param vartblEntrySize Size of vartable entry (in bytes).
+     * @param flags Format specific flags.
+     */
+    ChunkFormat(int vartblSizeFieldSize, int vartblEntrySize, byte flags) {
+        this.vartblEntrySize = vartblEntrySize;
+        this.vartblSizeFieldSize = vartblSizeFieldSize;
+        this.flags = flags;
     }
 
-    public byte modeFlags() {
-        return modeFlags;
+    /**
+     * @return Format specific flags for a chunk.
+     */
+    public byte formatFlags() {
+        return flags;
     }
 
     /**
+     * Calculates chunk size for the format.
+     *
      * @param payloadLen Row payload length in bytes.
      * @param nullMapLen Null-map length in bytes.
-     * @param vartblItems Number of vartable items.
-     * @return Chunk size.
+     * @param vartblEntries Number of vartable entries.
+     * @return Total chunk size.
      */
-    int chunkSize(int payloadLen, int nullMapLen, int vartblItems) {
-        return CHUNK_LEN_FLD_SIZE /* Chunk len. */ + nullMapLen + vartableLength(vartblItems) + payloadLen;
+    int chunkSize(int payloadLen, int nullMapLen, int vartblEntries) {
+        return CHUNK_LEN_FLD_SIZE /* Chunk len. */ + nullMapLen + vartableLength(vartblEntries - 1) + payloadLen;
     }
 
     /**
-     * Calculates vartable length (in bytes).
+     * Calculates vartable size in bytes.
      *
-     * @param items Vartable items.
+     * @param entries Vartable entries.
      * @return Vartable size in bytes.
      */
-    protected int vartableLength(int items) {
-        return items == 0 ? 0 : vartableSizeFieldLen /* Table size */ + items * vartableItemSize;
+    int vartableLength(int entries) {
+        return entries <= 0 ? 0 : vartblSizeFieldSize /* Table size */ + entries * vartblEntrySize;
     }
 
     /**
-     * Calculates vartable item offset.
+     * Calculates vartable entry offset.
      *
-     * @param idx Vartable item idx.
-     * @return Vartable item offset.
+     * @param idx Vartable entry idx.
+     * @return Vartable entry offset.
      */
-    int vartblItemOff(int idx) {
-        return vartableSizeFieldLen /* Table size */ + idx * vartableItemSize;
+    int vartableEntryOffset(int idx) {
+        return vartblSizeFieldSize /* Table size */ + idx * vartblEntrySize;
     }
 
-    abstract void writeOffset(ExpandableByteBuf buf, int vartblItemOff, int off);
+    /**
+     * Writes varlen offset to vartable.
+     *
+     * @param buf Row buffer.
+     * @param vartblOff Vartable offset.
+     * @param entryIdx Vartable entry index.
+     * @param off Varlen offset to be written.
+     */
+    abstract void writeVarlenOffset(ExpandableByteBuf buf, int vartblOff, int entryIdx, int off);
 
-    abstract int readOffset(BinaryRow row, int vartblOff);
+    /**
+     * Readss varlen offset from vartable.
+     *
+     * @param row Row.
+     * @param vartblOff Vartable offset.
+     * @param entryIdx Vartable entry index.
+     * @return Varlen offset.
+     */
+    abstract int readVarlenOffset(BinaryRow row, int vartblOff, int entryIdx);
 
-    abstract void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size);
+    /**
+     * Writes vartable size.
+     *
+     * @param buf Row buffer.
+     * @param vartblOff Vartable offset.
+     * @param size Number of entries in the vartable.
+     */
+    abstract void writeVartableSize(ExpandableByteBuf buf, int vartblOff, int size);
 
-    abstract int readVartblSize(BinaryRow row, int vartblOff);
+    /**
+     * Reads vartable size.
+     *
+     * @param row Row.
+     * @param vartblOff Vartable offset.
+     * @return Number of entries in the vartable.
+     */
+    abstract int readVartableSize(BinaryRow row, int vartblOff);
 
     /**
      * Chunk writer factory method.
@@ -222,11 +267,16 @@ abstract class ChunkFormat {
      * @param buf Row buffer.
      * @param baseOff Chunk base offset.
      * @param nullMapLen Null-map length.
-     * @param vartblItems Vartable items.
+     * @param nonNullVarlens Number of entries in vartable.
      * @return Chunk writer.
      */
-    ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblItems) {
-        return new ChunkWriter(buf, baseOff, nullMapLen, vartblItems, this);
+    ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int nonNullVarlens) {
+        return new ChunkWriter(
+            buf,
+            baseOff,
+            nullMapLen,
+            vartableLength(nonNullVarlens - 1),
+            this);
     }
 
     /**
@@ -234,11 +284,16 @@ abstract class ChunkFormat {
      *
      * @param row Row buffer.
      * @param baseOff Chunk base offset.
-     * @param nullMapLen Null-map length.
-     * @param hasVarTable Has vartable flag.
+     * @param nullMapSize Default chunk null-map size.
+     * @param chunkFlags Chunk flags.
      * @return Chunk reader.
      */
-    ChunkReader reader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable) {
-        return new ChunkReader(row, baseOff, nullMapLen, hasVarTable, this);
+    ChunkReader reader(BinaryRow row, int baseOff, int nullMapSize, byte chunkFlags) {
+        return new ChunkReader(
+            row,
+            baseOff,
+            (chunkFlags & OMIT_NULL_MAP_FLAG) == 0 ? nullMapSize : 0,
+            (chunkFlags & OMIT_VARTBL_FLAG) == 0,
+            this);
     }
-}
\ No newline at end of file
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
index c0e0177..6a1bc10 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
@@ -21,7 +21,7 @@ import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.schema.Columns;
 
 /**
- * Abstract chunk reader.
+ * Chunk reader.
  */
 class ChunkReader {
     /** Row. */
@@ -34,48 +34,41 @@ class ChunkReader {
     private final ChunkFormat format;
 
     /** Vartable offset. */
-    protected int varTableOff;
+    protected int varTblOff;
 
-    /** Payload offset. */
+    /** Data offset. */
     protected int dataOff;
 
     /**
-     * @param row
-     * @param baseOff
-     * @param nullMapLen
-     * @param hasVarTable
-     * @param format
+     * @param row Row.
+     * @param baseOff Chunk base offset.
+     * @param nullMapLen Null-map size in bytes.
+     * @param hasVarTable {@code true} if chunk has vartable, {@code false} otherwise.
+     * @param format Chunk format.
      */
     ChunkReader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable, ChunkFormat format) {
         this.row = row;
         this.baseOff = baseOff;
         this.format = format;
-        varTableOff = nullmapOff() + nullMapLen;
-        dataOff = varTableOff + (hasVarTable ? format.vartableLength(format.readVartblSize(row, varTableOff)) : 0);
+        varTblOff = nullmapOff() + nullMapLen;
+        dataOff = varTblOff + (hasVarTable ? format.vartableLength(format.readVartableSize(row, varTblOff)) : 0);
     }
 
     /**
+     * Reads chunk total length.
+     *
      * @return Chunk length in bytes
      */
-    /** {@inheritDoc} */
     int chunkLength() {
         return row.readInteger(baseOff);
     }
 
     /**
-     * @return Number of items in vartable.
-     */
-    int vartableItems() {
-       return format.readVartblSize(row, varTableOff);
-    }
-
-    /**
-     * Checks the row's null map for the given column index in the chunk.
+     * Checks the row's null-map for the given column index in the chunk.
      *
      * @param idx Offset of the column in the chunk.
-     * @return {@code true} if the column value is {@code null}.
+     * @return {@code true} if the column value is {@code null}, {@code false} otherwise.
      */
-    /** {@inheritDoc} */
     protected boolean isNull(int idx) {
         if (!hasNullmap())
             return false;
@@ -88,38 +81,29 @@ class ChunkReader {
         return (map & (1 << posInByte)) != 0;
     }
 
+    /**
+     * @return Null-map offset
+     */
     private int nullmapOff() {
         return baseOff + Integer.BYTES;
     }
 
     /**
-     * @return {@code True} if chunk has vartable.
+     * @return {@code True} if chunk has vartable, {@code false} otherwise.
      */
     protected boolean hasVartable() {
-        return dataOff > varTableOff;
+        return dataOff > varTblOff;
     }
 
     /**
-     * @return {@code True} if chunk has nullmap.
+     * @return {@code True} if chunk has null-map, {@code false} otherwise.
      */
     protected boolean hasNullmap() {
-        return varTableOff > nullmapOff();
+        return varTblOff > nullmapOff();
     }
 
     /**
-     * @param itemIdx Varlen table item index.
-     * @return Varlen item offset.
-     */
-    protected int varlenItemOffset(int itemIdx) {
-        assert hasVartable() : "Vartable is ommited.";
-
-        final int off = format.vartblItemOff(itemIdx);
-
-        return format.readOffset(row, off);
-    }
-
-    /**
-     * Calculates the offset of the fixlen column with the given index in the row. It essentially folds the null map
+     * Calculates the offset of the fixlen column with the given index in the row. It essentially folds the null-map
      * with the column lengths to calculate the size of non-null columns preceding the requested column.
      *
      * @param cols Columns chunk.
@@ -130,27 +114,25 @@ class ChunkReader {
         int colOff = 0;
 
         // Calculate fixlen column offset.
-        {
-            int colByteIdx = idx / 8;
+        int colByteIdx = idx / 8;
 
-            // Set bits starting from posInByte, inclusive, up to either the end of the byte or the last column index, inclusive
-            int startBit = idx % 8;
-            int endBit = colByteIdx == (cols.length() + 7) / 8 - 1 ? ((cols.numberOfFixsizeColumns() - 1) % 8) : 7;
-            int mask = (0xFF >> (7 - endBit)) & (0xFF << startBit);
+        // Set bits starting from posInByte, inclusive, up to either the end of the byte or the last column index, inclusive
+        int startBit = idx % 8;
+        int endBit = colByteIdx == (cols.length() + 7) / 8 - 1 ? ((cols.numberOfFixsizeColumns() - 1) % 8) : 7;
+        int mask = (0xFF >> (7 - endBit)) & (0xFF << startBit);
 
-            if (hasNullmap()) {
-                // Fold offset based on the whole map bytes in the schema
-                for (int i = 0; i < colByteIdx; i++)
-                    colOff += cols.foldFixedLength(i, row.readByte(nullmapOff() + i));
+        if (hasNullmap()) {
+            // Fold offset based on the whole map bytes in the schema
+            for (int i = 0; i < colByteIdx; i++)
+                colOff += cols.foldFixedLength(i, row.readByte(nullmapOff() + i));
 
-                colOff += cols.foldFixedLength(colByteIdx, row.readByte(nullmapOff() + colByteIdx) | mask);
-            }
-            else {
-                for (int i = 0; i < colByteIdx; i++)
-                    colOff += cols.foldFixedLength(i, 0);
+            colOff += cols.foldFixedLength(colByteIdx, row.readByte(nullmapOff() + colByteIdx) | mask);
+        }
+        else {
+            for (int i = 0; i < colByteIdx; i++)
+                colOff += cols.foldFixedLength(i, 0);
 
-                colOff += cols.foldFixedLength(colByteIdx, mask);
-            }
+            colOff += cols.foldFixedLength(colByteIdx, mask);
         }
 
         return dataOff + colOff;
@@ -158,19 +140,21 @@ class ChunkReader {
 
     /**
      * Calculates the offset and length of varlen column. First, it calculates the number of non-null columns
-     * preceding the requested column by folding the null map bits. This number is used to adjust the column index
+     * preceding the requested column by folding the null-map bits. This number is used to adjust the column index
      * and find the corresponding entry in the varlen table. The length of the column is calculated either by
      * subtracting two adjacent varlen table offsets, or by subtracting the last varlen table offset from the chunk
      * length.
+     * <p>
+     * Note: Offset for the very fisrt varlen is skipped in vartable and calculated from fixlen columns sizes.
      *
      * @param cols Columns chunk.
      * @param idx Column index in the chunk.
      * @return Encoded offset (from the row start) and length of the column with the given index.
      */
     long varlenColumnOffsetAndLength(Columns cols, int idx) {
-        assert hasVartable() : "Chunk has no vartable: colId=" + idx;
+        assert cols.hasVarlengthColumns() && cols.firstVarlengthColumn() <= idx : "Invalid varlen column index: colId=" + idx;
 
-        if (hasNullmap()) {
+        if (hasNullmap()) { // Calculates fixlen columns chunk size regarding the 'null' flags.
             int nullStartByte = cols.firstVarlengthColumn() / 8;
             int startBitInByte = cols.firstVarlengthColumn() % 8;
 
@@ -198,29 +182,31 @@ class ChunkReader {
 
         idx -= cols.numberOfFixsizeColumns();
 
-        if (idx == 0) { // Very first non-null varlen column.
-            int off = cols.numberOfFixsizeColumns() == 0 ?
-                 varTableOff + varlenItemOffset(readShort(vartableOff)) : vartableOff) :
-                fixlenColumnOffset(cols, baseOff, cols.numberOfFixsizeColumns(), hasVarTbl, hasNullMap);
+        // Calculate length and offset for very first (non-null) varlen column
+        // as vartable don't store the offset for the first varlen.
+        if (idx == 0) {
+            int off = cols.numberOfFixsizeColumns() == 0 ? dataOff : fixlenColumnOffset(cols, cols.numberOfFixsizeColumns());
 
-            long len = hasVarTbl ?
-                readShort(vartableOff + varlenItemOffset(0)) - (off - baseOff) :
-                readInteger(baseOff) - (off - baseOff);
+            long len = hasVartable() ? // Length is either diff between current offset and next varlen offset or end-of-chunk.
+                format.readVarlenOffset(row, varTblOff, 0) - (off - dataOff) :
+                (baseOff + chunkLength()) - off;
 
             return (len << 32) | off;
         }
 
-        int vartableSize = readShort(vartableOff);
+        final int vartblSize = format.readVartableSize(row, varTblOff);
+
+        assert idx > 0 && vartblSize >= idx : "Vartable index is out of bound: colId=" + idx;
 
         // Offset of idx-th column is from base offset.
-        int resOff = readShort(vartableOff + varlenItemOffset(idx - 1));
+        int resOff = format.readVarlenOffset(row, varTblOff, idx - 1);
 
-        long len = (idx == vartableSize) ?
+        long len = (vartblSize == idx) ?
             // totalLength - columnStartOffset
-            readInteger(baseOff) - resOff :
+            (baseOff + chunkLength()) - (dataOff + resOff) :
             // nextColumnStartOffset - columnStartOffset
-            readShort(vartableOff + varlenItemOffset(idx)) - resOff;
+            format.readVarlenOffset(row, varTblOff, idx) - resOff;
 
-        return (len << 32) | (resOff + baseOff);
+        return (len << 32) | (dataOff + resOff);
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
index dc65302..dbe5f9e 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
@@ -40,8 +40,11 @@ class ChunkWriter {
     /** Offset of data for the chunk. */
     protected final int dataOff;
 
+    /** Chunk format. */
+    private final ChunkFormat format;
+
     /** Index of the current varlen table entry. Incremented each time non-null varlen column is appended. */
-    protected int curVartblItem;
+    protected int curVartblEntry;
 
     /** Current offset for the next column to be appended. */
     protected int curOff;
@@ -49,31 +52,30 @@ class ChunkWriter {
     /** Chunk flags. */
     private byte flags;
 
-    /** Chunk format. */
-    ChunkFormat format;
 
     /**
      * @param buf Row buffer.
      * @param baseOff Chunk base offset.
      * @param nullMapLen Null-map length in bytes.
-     * @param vartblItems Vartable length in bytes.
+     * @param vartblLen Vartable length in bytes.
+     * @param format Chunk format.
      */
-    protected ChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblItems, ChunkFormat format) {
+    protected ChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblLen, ChunkFormat format) {
         this.buf = buf;
         this.baseOff = baseOff;
         this.format = format;
-        this.flags = format.modeFlags();
 
+        flags = format.formatFlags();
         varTblOff = nullmapOff() + nullMapLen;
-        dataOff = varTblOff + format.vartableLength(vartblItems);
+        dataOff = varTblOff + vartblLen;
         curOff = dataOff;
-        curVartblItem = 0;
+        curVartblEntry = 0;
 
-        if (nullmapOff() == baseOff)
-            this.flags |= ChunkFormat.OMIT_NULL_MAP_FLAG;
+        if (nullMapLen == 0)
+            flags |= ChunkFormat.OMIT_NULL_MAP_FLAG;
 
-        if (dataOff == varTblOff)
-            this.flags |= ChunkFormat.OMIT_VARTBL_FLAG;
+        if (vartblLen == 0)
+            flags |= ChunkFormat.OMIT_VARTBL_FLAG;
     }
 
     /**
@@ -160,15 +162,12 @@ class ChunkWriter {
      * @param val Column value.
      */
     public void appendString(String val, CharsetEncoder encoder) {
-        assert (flags & ChunkFormat.OMIT_VARTBL_FLAG) == 0 :
-            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
-
         try {
             int written = buf.putString(curOff, val, encoder);
 
-            writeOffset(curVartblItem, curOff - dataOff);
+            writeVarlenOffset(curVartblEntry, curOff - dataOff);
 
-            curVartblItem++;
+            curVartblEntry++;
             curOff += written;
         }
         catch (CharacterCodingException e) {
@@ -182,14 +181,11 @@ class ChunkWriter {
      * @param val Column value.
      */
     public void appendBytes(byte[] val) {
-        assert (flags & ChunkFormat.OMIT_VARTBL_FLAG) == 0 :
-            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
-
         buf.putBytes(curOff, val);
 
-        writeOffset(curVartblItem, curOff - dataOff);
+        writeVarlenOffset(curVartblEntry, curOff - dataOff);
 
-        curVartblItem++;
+        curVartblEntry++;
         curOff += val.length;
     }
 
@@ -210,6 +206,20 @@ class ChunkWriter {
     }
 
     /**
+     * @return Null-map offset.
+     */
+    private int nullmapOff() {
+        return baseOff + ChunkFormat.CHUNK_LEN_FLD_SIZE;
+    }
+
+    /**
+     * @return Chunk flags.
+     */
+    public short chunkFlags() {
+        return flags;
+    }
+
+    /**
      * @return Chunk size in bytes.
      */
     public int chunkLength() {
@@ -220,35 +230,38 @@ class ChunkWriter {
      * Post-write action.
      */
     void flush() {
-        final int size = chunkLength();
+        buf.putInt(baseOff,  chunkLength());
 
-        buf.putInt(baseOff, size);
+        if (curVartblEntry > 1) {
+            assert varTblOff + format.vartableLength(curVartblEntry - 1) == dataOff : "Vartable overlow: size=" + curVartblEntry;
 
-        if (curVartblItem > 0)
-            format.writeVartblSize(buf, varTblOff, curVartblItem);
+            format.writeVartableSize(buf, varTblOff, curVartblEntry - 1);
+        }
     }
 
     /**
      * Writes the given offset to the varlen table entry with the given index.
      *
-     * @param tblItemIdx Varlen table entry index.
+     * @param entryIdx Vartable entry index.
      * @param off Offset to write.
      */
-    protected void writeOffset(int tblItemIdx, int off) {
-        final int itemOff = varTblOff + format.vartblItemOff(tblItemIdx);
+    protected void writeVarlenOffset(int entryIdx, int off) {
+        if (entryIdx == 0)
+            return; // Omit offset for very first varlen.
 
-        assert itemOff < dataOff : "Vartable overflow: size=" + itemOff;
+        assert (flags & ChunkFormat.OMIT_VARTBL_FLAG) == 0 :
+            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
 
-        format.writeOffset(buf, itemOff, off);
+        format.writeVarlenOffset(buf, varTblOff, entryIdx - 1, off);
     }
 
     /**
-     * Sets null flag in the null map for the given column.
+     * Sets null flag in the null-map for the given column.
      *
      * @param colIdx Column index.
      */
     protected void setNull(int colIdx) {
-        assert (flags & ChunkFormat.OMIT_NULL_MAP_FLAG) == 0 : "Null map is omitted.";
+        assert (flags & ChunkFormat.OMIT_NULL_MAP_FLAG) == 0 : "Null-map is omitted.";
 
         int byteInMap = colIdx / 8;
         int bitInByte = colIdx % 8;
@@ -257,12 +270,4 @@ class ChunkWriter {
 
         buf.put(nullmapOff() + byteInMap, (byte)(buf.get(nullmapOff() + byteInMap) | (1 << bitInByte)));
     }
-
-    private int nullmapOff() {
-        return baseOff + Integer.BYTES;
-    }
-
-    public short flags() {
-        return flags;
-    }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java
index 96401b3..74f5099 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java
@@ -57,7 +57,9 @@ public class ExpandableByteBuf {
     private int len;
 
     /**
-     * @param size Start buffer size.
+     * Creates expandable row buffer.
+     *
+     * @param size Initial buffer size.
      */
     public ExpandableByteBuf(int size) {
         if (size <= 0)
@@ -282,7 +284,7 @@ public class ExpandableByteBuf {
     /**
      * Unwrap to ByteBuffer.
      *
-     * @return Byte buffer.
+     * @return internal buffer.
      */
     ByteBuffer unwrap() {
         return buf;
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
index 027da41..20d88d2 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
@@ -373,13 +373,14 @@ public class Row implements BinaryRow {
         if (reader.isNull(colIdx))
             return -1;
 
-        assert reader.hasVartable() || type.fixedLength();
-
         return type.fixedLength() ?
-            reader.fixlenColumnOffset(cols, off, colIdx, hasVarTable, hasNullMap) :
+            reader.fixlenColumnOffset(cols, colIdx) :
             reader.varlenColumnOffsetAndLength(cols, colIdx);
     }
 
+    /**
+     * @return Reader for value chunk.
+     */
     private ChunkReader valueReader() {
         if (valReader != null)
             return valReader;
@@ -391,8 +392,8 @@ public class Row implements BinaryRow {
         return (valReader = ChunkFormat.createReader(
             this,
             KEY_CHUNK_OFFSET + keyReader.chunkLength(),
-            schema.keyColumns().nullMapSize(),
-            (byte)(flags >>> RowFlags.VAL_FLAGS_OFFSET)));
+            schema.valueColumns().nullMapSize(),
+            (byte)((flags >>> RowFlags.VAL_FLAGS_OFFSET)& RowFlags.CHUNK_FLAGS_MASK)));
     }
 
     /**
@@ -491,5 +492,4 @@ public class Row implements BinaryRow {
     @Override public byte[] readBytes(int off, int len) {
         return row.readBytes(off, len);
     }
-
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
index c245d9f..6e0f45a 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
@@ -50,11 +50,14 @@ public class RowAssembler {
     /** Schema. */
     private final SchemaDescriptor schema;
 
+    /** Target byte buffer to write to. */
+    private final ExpandableByteBuf buf;
+
     /** The number of non-null varlen columns in values chunk. */
     private final int valVarlenCols;
 
-    /** Target byte buffer to write to. */
-    private final ExpandableByteBuf buf;
+    /** Value write mode. */
+    private final ChunkFormat valWriteMode;
 
     /** Current columns chunk. */
     private Columns curCols;
@@ -74,9 +77,6 @@ public class RowAssembler {
     /** Current chunk writer. */
     private ChunkWriter chunkWriter;
 
-    /** Value write mode. */
-    private ChunkFormat valWriteMode;
-
     /**
      * Calculates encoded string length.
      *
@@ -184,6 +184,7 @@ public class RowAssembler {
         curCols = schema.keyColumns();
         curCol = 0;
         flags = 0;
+        hash = 0;
         strEncoder = null;
 
         final int keyNullMapSize = keyHasNulls ? schema.keyColumns().nullMapSize() : 0;
@@ -204,8 +205,10 @@ public class RowAssembler {
 
     /**
      * Appends {@code null} value for the current column to the chunk.
+     *
+     * @return {@code this} for chaining.
      */
-    public void appendNull() {
+    public RowAssembler appendNull() {
         Column col = curCols.column(curCol);
 
         if (!col.nullable())
@@ -218,14 +221,17 @@ public class RowAssembler {
         chunkWriter.setNull(curCol);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends byte value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendByte(byte val) {
+    public RowAssembler appendByte(byte val) {
         checkType(NativeTypes.BYTE);
 
         if (isKeyColumn())
@@ -234,14 +240,17 @@ public class RowAssembler {
         chunkWriter.appendByte(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends short value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendShort(short val) {
+    public RowAssembler appendShort(short val) {
         checkType(NativeTypes.SHORT);
 
         if (isKeyColumn())
@@ -250,14 +259,17 @@ public class RowAssembler {
         chunkWriter.appendShort(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends int value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendInt(int val) {
+    public RowAssembler appendInt(int val) {
         checkType(NativeTypes.INTEGER);
 
         if (isKeyColumn())
@@ -266,14 +278,17 @@ public class RowAssembler {
         chunkWriter.appendInt(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends long value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendLong(long val) {
+    public RowAssembler appendLong(long val) {
         checkType(NativeTypes.LONG);
 
         if (isKeyColumn())
@@ -282,14 +297,17 @@ public class RowAssembler {
         chunkWriter.appendLong(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends float value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendFloat(float val) {
+    public RowAssembler appendFloat(float val) {
         checkType(NativeTypes.FLOAT);
 
         if (isKeyColumn())
@@ -298,14 +316,17 @@ public class RowAssembler {
         chunkWriter.appendFloat(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends double value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendDouble(double val) {
+    public RowAssembler appendDouble(double val) {
         checkType(NativeTypes.DOUBLE);
 
         if (isKeyColumn())
@@ -314,14 +335,17 @@ public class RowAssembler {
         chunkWriter.appendDouble(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends UUID value for the current column to the chunk.
      *
      * @param uuid Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendUuid(UUID uuid) {
+    public RowAssembler appendUuid(UUID uuid) {
         checkType(NativeTypes.UUID);
 
         if (isKeyColumn())
@@ -330,14 +354,17 @@ public class RowAssembler {
         chunkWriter.appendUuid(uuid);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends String value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendString(String val) {
+    public RowAssembler appendString(String val) {
         checkType(NativeTypes.STRING);
 
         if (isKeyColumn())
@@ -346,14 +373,17 @@ public class RowAssembler {
         chunkWriter.appendString(val, encoder());
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends byte[] value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendBytes(byte[] val) {
+    public RowAssembler appendBytes(byte[] val) {
         checkType(NativeTypes.BYTES);
 
         if (isKeyColumn())
@@ -362,14 +392,17 @@ public class RowAssembler {
         chunkWriter.appendBytes(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends BitSet value for the current column to the chunk.
      *
      * @param bitSet Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendBitmask(BitSet bitSet) {
+    public RowAssembler appendBitmask(BitSet bitSet) {
         Column col = curCols.column(curCol);
 
         checkType(NativeTypeSpec.BITMASK);
@@ -386,6 +419,8 @@ public class RowAssembler {
         chunkWriter.appendBitmask(bitSet, maskType.sizeInBytes());
 
         shiftColumn();
+
+        return this;
     }
 
     /**
@@ -455,7 +490,9 @@ public class RowAssembler {
             chunkWriter.flush();
 
             if (schema.valueColumns() == curCols) {
-                flags |= (chunkWriter.flags() & 0x0F) << VAL_FLAGS_OFFSET;
+                assert (chunkWriter.chunkFlags() & (~0x0F)) == 0 : "Value chunk flags overflow: flags=" + chunkWriter.chunkFlags();
+
+                flags |= (chunkWriter.chunkFlags() & 0x0F) << VAL_FLAGS_OFFSET;
 
                 return; // No more columns.
             }
@@ -464,7 +501,9 @@ public class RowAssembler {
             curCols = schema.valueColumns();
             curCol = 0;
 
-            flags |= (chunkWriter.flags() & 0x0F) << KEY_FLAGS_OFFSET;
+            assert (chunkWriter.chunkFlags() & (~0x0F)) == 0 : "Key chunk flags overflow: flags=" + chunkWriter.chunkFlags();
+
+            flags |= (chunkWriter.chunkFlags() & 0x0F) << KEY_FLAGS_OFFSET;
 
             // Create value chunk writer.
             chunkWriter = valWriteMode.writer(buf,
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerAdvancedSchemaTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerAdvancedSchemaTest.java
index d4f9daf..ec6be58 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerAdvancedSchemaTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerAdvancedSchemaTest.java
@@ -19,6 +19,8 @@ package org.apache.ignite.internal.schema;
 
 import java.util.Arrays;
 import java.util.UUID;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
@@ -27,6 +29,8 @@ 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.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
 
 /**
  * Validate row layout for different schema configurations.
@@ -54,8 +58,8 @@ public class RowAssemblerAdvancedSchemaTest {
 
         // Last col null
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, -11, 43, 0, 0, 8, 0, 0, 0, 4, 11, 22, 0, 8, 0, 0, 0, 4, -44, -66, -1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, -11, 43, 0, 0, 8, 0, 0, 0, 4, 11, 22, 0, 8, 0, 0, 0, 4, -44, -66, -1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendByte((byte)11)
                 .appendShort((short)22)
                 .appendNull()
@@ -66,8 +70,8 @@ public class RowAssemblerAdvancedSchemaTest {
 
         // First col null.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, -53, 2, 0, 0, 11, 0, 0, 0, 1, 22, 0, 33, 0, 0, 0, 11, 0, 0, 0, 1, -55, -1, -66, -1, -1, -1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, -53, 2, 0, 0, 11, 0, 0, 0, 1, 22, 0, 33, 0, 0, 0, 11, 0, 0, 0, 1, -55, -1, -66, -1, -1, -1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendShort((byte)22)
                 .appendInt(33)
@@ -77,8 +81,8 @@ public class RowAssemblerAdvancedSchemaTest {
                 .build());
 
         // Middle col null.
-        assertRowBytesEquals(new byte[] {42, 0, 24, 0, 108, 41, 0, 0, 10, 0, 0, 0, 2, 11, 33, 0, 0, 0, 10, 0, 0, 0, 2, -44, -66, -1, -1, -1},
-            new RowAssembler(schema, 0, 0, 0)
+        assertRowBytesEquals(new byte[] {42, 0, 0, -103, 108, 41, 0, 0, 10, 0, 0, 0, 2, 11, 33, 0, 0, 0, 10, 0, 0, 0, 2, -44, -66, -1, -1, -1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendByte((byte)11)
                 .appendNull()
                 .appendInt(33)
@@ -88,8 +92,8 @@ public class RowAssemblerAdvancedSchemaTest {
                 .build());
 
         // Null both.
-        assertRowBytesEquals(new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 7, 5, 0, 0, 0, 7},
-            new RowAssembler(schema, 0, 0, 0)
+        assertRowBytesEquals(new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 7, 5, 0, 0, 0, 7},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .appendNull()
@@ -99,14 +103,43 @@ public class RowAssemblerAdvancedSchemaTest {
                 .build());
 
         // No value.
-        assertRowBytesEquals(new byte[] {42, 0, 25, 0, 22, 44, 0, 0, 12, 0, 0, 0, 0, 11, 22, 0, 33, 0, 0, 0},
-            new RowAssembler(schema, 0, 0, 0)
+        assertRowBytesEquals(new byte[] {42, 0, 1, 9, 22, 44, 0, 0, 12, 0, 0, 0, 0, 11, 22, 0, 33, 0, 0, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendByte((byte)11)
                 .appendShort((short)22)
                 .appendInt(33)
                 .build());
     }
+    /**
+     * Validate row layout for schema of fix-len nullable key and fix-len nullable value.
+     */
+    @Test
+    public void varlenNullableColumns2() {
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42,
+            new Column[] {
+                new Column("keyCol2", BYTES, true),
+                new Column("keyCol3", STRING, true)
+            },
+            new Column[] {
+                new Column("valCol2", BYTES, true),
+                new Column("valCol3", STRING, true)
+            });
 
+        final byte[] data = new RowAssembler(schema, 128, 1, 128, 1)
+            .appendNull()
+            .appendString("A我愛我愛我愛我愛我愛")
+            .appendNull()
+            .appendString("A我愛我愛我愛我愛我愛")
+            .build();
+
+        final Row row = new Row(schema, new ByteBufferRow(data));
+
+        assertNull(row.bytesValue(0));
+//        assertArrayEquals(new byte[] {33, -77}, row.bytesValue(0));
+        assertEquals("A我愛我愛我愛我愛我愛", row.stringValue(1));
+//        assertArrayEquals(new byte[] {33, -77}, row.bytesValue(2));
+        assertEquals("A我愛我愛我愛我愛我愛", row.stringValue(3));
+    }
     /**
      * Validate row layout for schema of fix-len nullable key and fix-len nullable value.
      */
@@ -127,10 +160,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Last col null
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 0, 0, 47, -30, -119, -81,
-                17, 0, 0, 0, 4, 1, 0, 12, 0, 33, -77, 120, 97, 115, 99, 105, 105,
-                21, 0, 0, 0, 4, 1, 0, 11, 0, 33, -77, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97},
-            new RowAssembler(schema, 25, 2, 2)
+                42, 0, 0, 17, -12, -36, 109, -81,
+                15, 0, 0, 0, 4, 1, 3, 33, -77, 120, 97, 115, 99, 105, 105,
+                19, 0, 0, 0, 4, 1, 2, 33, -77, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97},
+            new RowAssembler(schema, 128, 2, 128, 2)
                 .appendBytes(new byte[] {33, -77, 120})
                 .appendString("ascii")
                 .appendNull()
@@ -142,10 +175,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Fist col null.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 0, 0, -116, -92, 12, 98,
-                24, 0, 0, 0, 1, 1, 0, 14, 0, 97, 115, 99, 105, 105, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
-                24, 0, 0, 0, 1, 1, 0, 19, 0, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97, 97, 115, 99, 105, 105},
-            new RowAssembler(schema, 0, 2, 2)
+                42, 0, 0, 17, 59, -11, 127, 92,
+                22, 0, 0, 0, 1, 1, 5, 97, 115, 99, 105, 105, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
+                22, 0, 0, 0, 1, 1, 10, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97, 97, 115, 99, 105, 105},
+            new RowAssembler(schema, 128, 2, 128, 2)
                 .appendNull()
                 .appendString("ascii")
                 .appendString("我愛Java")
@@ -157,10 +190,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Middle col null.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 0, 0, -52, 97, -9, -77,
-                22, 0, 0, 0, 2, 1, 0, 12, 0, 33, -77, 120, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
-                16, 0, 0, 0, 2, 1, 0, 11, 0, 33, -77, 97, 115, 99, 105, 105},
-            new RowAssembler(schema, 0, 2, 2)
+                42, 0, 0, 17, -111, 92, -37, -77,
+                20, 0, 0, 0, 2, 1, 3, 33, -77, 120, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
+                14, 0, 0, 0, 2, 1, 2, 33, -77, 97, 115, 99, 105, 105},
+            new RowAssembler(schema, 128, 2, 128, 2)
                 .appendBytes(new byte[] {33, -77, 120})
                 .appendNull()
                 .appendString("我愛Java")
@@ -171,8 +204,8 @@ public class RowAssemblerAdvancedSchemaTest {
 
         // Null both.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 7, 5, 0, 0, 0, 7},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 7, 5, 0, 0, 0, 7},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .appendNull()
@@ -184,9 +217,9 @@ public class RowAssemblerAdvancedSchemaTest {
         // No value.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 17, 0, -47, -112, 1, 24,
-                29, 0, 0, 0, 0, 2, 0, 14, 0, 24, 0, 33, -77, 120, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97, 97, 115, 99, 105, 105},
-            new RowAssembler(schema, 0, 3, 0)
+                42, 0, 1, 1, -118, -28, 81, 103,
+                26, 0, 0, 0, 0, 2, 3, 13, 33, -77, 120, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97, 97, 115, 99, 105, 105},
+            new RowAssembler(schema, 128, 3, 128, 0)
                 .appendBytes(new byte[] {33, -77, 120})
                 .appendString("我愛Java")
                 .appendString("ascii")
@@ -215,10 +248,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Check null/non-null all fixlen/varlen.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 0, 0, -85, 82, 5, 0,
-                12, 0, 0, 0, 12, 1, 0, 0, 0, 11, 22, 0,
-                16, 0, 0, 0, 3, 1, 0, 11, 0, 77, -88, 97, 115, 99, 105, 105},
-            new RowAssembler(schema, 0, 2, 2)
+                42, 0, 0, 25, -85, 82, 5, 0,
+                8, 0, 0, 0, 12, 11, 22, 0,
+                14, 0, 0, 0, 3, 1, 2, 77, -88, 97, 115, 99, 105, 105},
+            new RowAssembler(schema, 128, 0, 128, 2)
                 .appendByte((byte)11)
                 .appendShort((short)22)
                 .appendNull()
@@ -232,10 +265,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Check null/non-null fixlen.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 0, 0, -20, 4, 120, -80,
-                23, 0, 0, 0, 1, 1, 0, 13, 0, 22, 0, 33, -44, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
-                17, 0, 0, 0, 2, 1, 0, 12, 0, 55, 77, -88, 97, 115, 99, 105, 105},
-            new RowAssembler(schema, 0, 2, 2)
+                42, 0, 0, 17, -18, -9, 119, -80,
+                21, 0, 0, 0, 1, 1, 4, 22, 0, 33, -44, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
+                15, 0, 0, 0, 2, 1, 3, 55, 77, -88, 97, 115, 99, 105, 105},
+            new RowAssembler(schema, 128, 2, 128, 2)
                 .appendNull()
                 .appendShort((short)22)
                 .appendBytes(new byte[] {33, -44})
@@ -249,10 +282,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Check null/non-null varlen.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 24, 0, 12, 57, 124, -80,
+                42, 0, 0, -120, 23, 13, 124, -80,
                 18, 0, 0, 0, 4, 11, 22, 0, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
                 10, 0, 0, 0, 8, 55, 22, 0, 77, -88},
-            new RowAssembler(schema, 0, 1, 1)
+            new RowAssembler(schema, 1, 1)
                 .appendByte((byte)11)
                 .appendShort((short)22)
                 .appendNull()
@@ -266,10 +299,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Check null/non-null mixed.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 24, 0, -52, -29, 123, -80,
+                42, 0, 0, -120, -127, -70, 123, -80,
                 16, 0, 0, 0, 6, 11, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
                 9, 0, 0, 0, 9, 22, 0, 77, -88},
-            new RowAssembler(schema, 0, 1, 1)
+            new RowAssembler(schema, 1, 1)
                 .appendByte((byte)11)
                 .appendNull()
                 .appendNull()
@@ -282,10 +315,11 @@ public class RowAssemblerAdvancedSchemaTest {
 
         // Check all null/non-null.
         assertRowBytesEquals(
-            new byte[] {42, 0, 16, 0, -20, 88, 125, -80,
-                24, 0, 0, 0, 0, 1, 0, 14, 0, 11, 22, 0, 33, -44, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
+            new byte[] {
+                42, 0, 0, -111, 3, -8, 124, -80,
+                22, 0, 0, 0, 0, 1, 5, 11, 22, 0, 33, -44, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
                 5, 0, 0, 0, 15},
-            new RowAssembler(schema, 0, 2, 0)
+            new RowAssembler(schema, 128, 2, 128, 0)
                 .appendByte((byte)11)
                 .appendShort((short)22)
                 .appendBytes(new byte[] {33, -44})
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerSimpleSchemaTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerSimpleSchemaTest.java
index 7733b5a..aa02135 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerSimpleSchemaTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerSimpleSchemaTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.schema;
 
 import java.util.Arrays;
 import java.util.UUID;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
@@ -49,24 +50,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valIntCol", INTEGER, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0, 9, 0, 0, 0, 0, -71, -1, -1, -1},
-            new RowAssembler(schema, 24, 0, 0)
+            new byte[] {42, 0, 0, -99, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0, 9, 0, 0, 0, 0, -71, -1, -1, -1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendInt(33)
                 .appendInt(-71)
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 21, 0, 0)
+            new byte[] {42, 0, 0, -99, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendInt(33)
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 27, 0, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0},
-            new RowAssembler(schema, 16, 0, 0)
+            new byte[] {42, 0, 1, 13, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendInt(33)
                 .build());
     }
@@ -82,16 +83,16 @@ public class RowAssemblerSimpleSchemaTest {
 
         // With value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 30, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 6, 0, 0, 0, -71, -1},
-            new RowAssembler(schema, 20, 0, 0)
+            new byte[] {42, 0, 0, -35, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 6, 0, 0, 0, -71, -1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .appendShort((short)-71)
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 31, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 14, 0, 0)
+            new byte[] {42, 0, 1, 13, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
     }
@@ -106,24 +107,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valStrCol", STRING, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1, 8, 0, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -99, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1, 8, 0, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendShort((short)-33)
                 .appendString("val")
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -99, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 27, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 13, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
     }
@@ -138,16 +139,16 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valStrCol", STRING, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 30, 0, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1, 7, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -35, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1, 7, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendShort((short)-33)
                 .appendString("val")
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 31, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 13, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
     }
@@ -162,24 +163,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valByteCol", BYTE, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, -33, -1, -1, -1, 7, 0, 0, 0, 0, -33, -1, 5, 0, 0, 0, 71},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -39, -33, -1, -1, -1, 7, 0, 0, 0, 0, -33, -1, 5, 0, 0, 0, 71},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)-33)
                 .appendByte((byte)71)
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, -71},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -39, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, -71},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendByte((byte)-71)
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 29, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 9, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
     }
@@ -195,32 +196,32 @@ public class RowAssemblerSimpleSchemaTest {
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendShort((short)33)
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .appendNull()
                 .build());
 
         // Null both.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 25, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 9, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
 
@@ -236,40 +237,40 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valStrCol", STRING, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 8, 0, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -103, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 8, 0, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendShort((short)33)
                 .appendString("val")
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 8, 0, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 8, 0, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendNull()
                 .appendString("val")
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .appendNull()
                 .build());
 
         // Null both.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 25, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 9, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
     }
@@ -284,22 +285,22 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valStrCol", STRING, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 33, 0, 0, 0, 6, 0, 0, 0, 0, 33, 7, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -39, 33, 0, 0, 0, 6, 0, 0, 0, 0, 33, 7, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendByte((byte)33)
                 .appendString("val").build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -39, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendNull()
                 .appendString("val").build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 29, 0, 33, 0, 0, 0, 6, 0, 0, 0, 0, 33},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 9, 33, 0, 0, 0, 6, 0, 0, 0, 0, 33},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendByte((byte)33)
                 .build());
     }
@@ -315,26 +316,25 @@ public class RowAssemblerSimpleSchemaTest {
 
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 26, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121,
+                42, 0, 0, -99, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121,
                 21, 0, 0, 0, 0, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73},
-            new RowAssembler(schema, 0, 1, 0)
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendUuid(uuidVal)
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 95, -98, 1, 0, 7, 0, 0, 0,107, 101, 121, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 1, 0)
-
+            new byte[] {42, 0, 0, -99, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 27, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 13, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
 
@@ -351,17 +351,17 @@ public class RowAssemblerSimpleSchemaTest {
 
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 30, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121,
+                42, 0, 0, -35, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121,
                 20, 0, 0, 0, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73},
-            new RowAssembler(schema, 0, 1, 0)
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendUuid(uuidVal)
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 31, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 13, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
 
@@ -377,24 +377,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 9, 0, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 1, 1)
+            new byte[] {42, 0, 0, -99, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 9, 0, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 1, 128, 1)
                 .appendString("key")
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 0, -99, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 27, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 13, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
 
@@ -410,16 +410,16 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valBytesCol", BYTES, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 30, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 8, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 1, 1)
+            new byte[] {42, 0, 0, -35, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 8, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 1, 128, 1)
                 .appendString("key")
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 31, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 13, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
     }
@@ -434,40 +434,40 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valShortCol", SHORT, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 7, 0, 0, 0, 0, -71, -1},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 0, -103, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 7, 0, 0, 0, 0, -71, -1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendShort((short)-71)
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 0, 71, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 0, 71, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendShort((short)71)
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 0, -103, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendNull()
                 .build());
 
         // Null both.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 25, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 9, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
 
@@ -483,24 +483,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valShortCol", SHORT, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 6, 0, 0, 0, -71, -1},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 0, -39, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 6, 0, 0, 0, -71, -1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendShort((short)-71L)
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 6, 0, 0, 0, 71, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -39, 0, 0, 0, 0, 5, 0, 0, 0, 1, 6, 0, 0, 0, 71, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendShort((short)71)
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 29, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 9, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
     }
@@ -515,40 +515,40 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 9, 0, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 1, 1)
+            new byte[] {42, 0, 0, -103, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 9, 0, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 1, 128, 1)
                 .appendString("key")
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 9, 0, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 9, 0, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendNull()
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 0, -103, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendNull()
                 .build());
 
         // Null both.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 25, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 9, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
     }
@@ -563,24 +563,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valBytesCol", BYTES, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 8, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 1, 1)
+            new byte[] {42, 0, 0, -39, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 8, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 1, 128, 1)
                 .appendString("key")
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 8, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -39, 0, 0, 0, 0, 5, 0, 0, 0, 1, 8, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendNull()
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 29, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 9, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
     }
@@ -601,10 +601,10 @@ public class RowAssemblerSimpleSchemaTest {
             });
 
         assertRowBytesEquals(new byte[] {
-                42, 0, 26, 0, -110, -109, 94, -68,
+                42, 0, 0, -99, 113, -109, 94, -68,
                 12, 0, 0, 0, 33, 0, 107, 101, 121, 115, 116, 114,
                 15, 0, 0, 0, 0, 73, 0, 0, 0, 118, 97, 108, 115, 116, 114},
-            new RowAssembler(schema, 0, 1, 1)
+            new RowAssembler(schema, 128, 1, 128, 1)
                 .appendShort((short)33)
                 .appendString("keystr")
                 .appendInt(73)
@@ -613,10 +613,10 @@ public class RowAssemblerSimpleSchemaTest {
 
         // Null value.
         assertRowBytesEquals(new byte[] {
-                42, 0, 26, 0, 32, 99, 115, -49,
+                42, 0, 0, -99, -1, 98, 115, -49,
                 13, 0, 0, 0, 33, 0, 107, 101, 121, 115, 116, 114, 50,
                 5, 0, 0, 0, 3},
-            new RowAssembler(schema, 0, 1, 0)
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendShort((short)33)
                 .appendString("keystr2")
                 .appendNull()
@@ -625,9 +625,9 @@ public class RowAssemblerSimpleSchemaTest {
 
         // No value.
         assertRowBytesEquals(new byte[] {
-                42, 0, 27, 0, -110, -109, 94, -68,
+                42, 0, 1, 13, 113, -109, 94, -68,
                 12, 0, 0, 0, 33, 0, 107, 101, 121, 115, 116, 114},
-            new RowAssembler(schema, 0, 1, 0)
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendShort((short)33)
                 .appendString("keystr")
                 .build());
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
deleted file mode 100644
index 6064fa4..0000000
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.schema;
-
-import java.util.Arrays;
-import java.util.UUID;
-import org.apache.ignite.internal.schema.row.RowAssembler;
-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.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;
-
-/**
- * Validate row layout for different schema configurations.
- */
-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();
-
-    /**
-     * Validate row layout for schema of fix-len non-null key and fix-len nullable value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendInt(33);
-            asm.appendInt(-71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 122, 0, -10, 54, 5, 7, 5, 33, 0, 0, 0, 6, 0, -71, -1, -1, -1}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendInt(-33);
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 122, 0, 61, 0, -79, 50, 5, -33, -1, -1, -1, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendInt(-33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 123, 0, 61, 0, -79, 50, 5, -33, -1, -1, -1}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len non-null key and fix-len non-null value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        { // With value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)33);
-            asm.appendShort((short)71L);
-
-            assertRowBytesEquals(new byte[] {42, 0, 126, 0, 1, -101, 57, -89, 3, 33, 0, 3, 71, 0}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)-33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 127, 0, 83, 62, 65, -105, 3, -33, -1}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len non-null key and var-len nullable value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendShort((short)33);
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 106, 0, 1, -101, 57, -89, 3, 33, 0, 7, 0, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)33);
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 122, 0, 1, -101, 57, -89, 3, 33, 0, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 123, 0, 1, -101, 57, -89, 3, 33, 0}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len non-null key and var-len non-null value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendShort((short)33);
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 110, 0, 1, -101, 57, -89, 3, 33, 0, 6, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 127, 0, 1, -101, 57, -89, 3, 33, 0}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len nullable key and fix-len non-null value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)-33);
-            asm.appendByte((byte)71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 124, 0, 83, 62, 65, -105, 4, 0, -33, -1, 2, 71}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendByte((byte)-71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 124, 0, 5, 93, -52, 2, 2, 1, 2, -71}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 125, 0, 1, -101, 57, -89, 4, 0, 33, 0}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len nullable key and fix-len nullable value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)1133);
-            asm.appendShort((short)1071);
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, -100, -86, -70, -80, 4, 0, 109, 4, 4, 0, 47, 4}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendShort((short)1171);
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 4, 0, -109, 4}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)1133);
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, -100, -86, -70, -80, 4, 0, 109, 4, 2, 1}, asm.build());
-        }
-
-        { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)1133);
-
-            assertRowBytesEquals(new byte[] {42, 0, 121, 0, -100, -86, -70, -80, 4, 0, 109, 4}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len nullable key and var-len nullable value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendInt(-33);
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 61, 0, -79, 50, 6, 0, -33, -1, -1, -1, 7, 0, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendNull();
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 5, 93, -52, 2, 2, 1, 7, 0, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendInt(33);
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, -10, 54, 5, 7, 6, 0, 33, 0, 0, 0, 2, 1}, asm.build());
-        }
-
-        { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendInt(33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 121, 0, -10, 54, 5, 7, 6, 0, 33, 0, 0, 0}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len nullable key and var-len non-null value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendByte((byte)33);
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 108, 0, 116, -97, 78, -100, 3, 0, 33, 6, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendNull();
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 108, 0, 5, 93, -52, 2, 2, 1, 6, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendByte((byte)33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 125, 0, 116, -97, 78, -100, 3, 0, 33}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len non-null key and fix-len nullable value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendUuid(uuidVal);
-
-            assertRowBytesEquals(new byte[] {
-                42, 0, 114, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121,
-                18, 0, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 114, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 115, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len non-null key and fix-len non-null value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendUuid(uuidVal);
-
-            assertRowBytesEquals(new byte[] {
-                42, 0, 118, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121,
-                17, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 119, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len non-null key and var-len nullable value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
-
-            asm.appendString("key");
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 98, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 8, 0, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 114, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 115, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len non-null key and var-len non-null value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
-
-            asm.appendString("key");
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 102, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 7, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 119, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len nullable key and fix-len nullable value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendShort((short)-71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 112, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 4, 0, -71, -1}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendShort((short)71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 4, 0, 71, 0}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 112, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 2, 1}, asm.build());
-        }
-
-        { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 113, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len nullable key and fix-len non-null value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendShort((short)-71L);
-
-            assertRowBytesEquals(new byte[] {42, 0, 116, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 3, -71, -1}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendShort((short)71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 124, 0, 5, 93, -52, 2, 2, 1, 3, 71, 0}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 117, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len nullable key and var-len nullable value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
-
-            asm.appendString("key");
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 96, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 8, 0, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendNull();
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 5, 93, -52, 2, 2, 1, 8, 0, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 112, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 2, 1}, asm.build());
-        }
-
-        { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 113, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len nullable key and var-len non-null value.
-     */
-    @Test
-    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(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
-
-            asm.appendString("key");
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 100, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 7, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendNull();
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 108, 0, 5, 93, -52, 2, 2, 1, 7, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 117, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for key\value columns of different types.
-     */
-    @Test
-    public void mixedTypes() {
-        Column[] keyCols = new Column[] {
-            new Column("keyShortCol", SHORT, false),
-            new Column("keyStrCol", STRING, false)
-        };
-        Column[] valCols = new Column[] {
-            new Column("valIntCol", INTEGER, true),
-            new Column("valStrCol", STRING, true)
-        };
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
-
-            asm.appendShort((short)33);
-            asm.appendString("keystr");
-            asm.appendInt(73);
-            asm.appendString("valstr");
-
-            assertRowBytesEquals(new byte[] {
-                42, 0, 98, 0, 5, -39, 55, 59,
-                11, 1, 2, 33, 0, 107, 101, 121, 115, 116, 114,
-                14, 0, 1, 4, 73, 0, 0, 0, 118, 97, 108, 115, 116, 114}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendShort((short)33);
-            asm.appendString("keystr2");
-            asm.appendNull();
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {
-                42, 0, 114, 0, -80, -78, -91, 1,
-                12, 1, 2, 33, 0, 107, 101, 121, 115, 116, 114, 50,
-                2, 3}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendShort((short)33);
-            asm.appendString("keystr");
-
-            assertRowBytesEquals(new byte[] {
-                42, 0, 115, 0, 5, -39, 55, 59,
-                11, 1, 2, 33, 0, 107, 101, 121, 115, 116, 114,}, asm.build());
-        }
-    }
-
-    /**
-     * @param expected Expected row bytes.
-     * @param actual Actual row bytes.
-     */
-    private void assertRowBytesEquals(byte[] expected, byte[] actual) {
-        assertArrayEquals(expected, actual, Arrays.toString(actual));
-    }
-}
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 5b87c56..94e0848 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
@@ -263,29 +263,45 @@ public class RowTest {
 
         int nonNullVarLenKeyCols = 0;
         int nonNullVarLenValCols = 0;
+        int nonNullVarLenKeySize = 0;
+        int nonNullVarLenValSize = 0;
 
         for (int i = 0; i < vals.length; i++) {
             NativeTypeSpec type = schema.column(i).type().spec();
 
             if (vals[i] != null && !type.fixedLength()) {
                 if (type == NativeTypeSpec.BYTES) {
-                    if (schema.isKeyColumn(i))
+                    byte[] val = (byte[])vals[i];
+                    if (schema.isKeyColumn(i)) {
                         nonNullVarLenKeyCols++;
-                    else
+                        nonNullVarLenKeySize += val.length;
+                    }
+                    else {
                         nonNullVarLenValCols++;
+                        nonNullVarLenValSize += val.length;
+                    }
                 }
                 else if (type == NativeTypeSpec.STRING) {
-                    if (schema.isKeyColumn(i))
+                    if (schema.isKeyColumn(i)) {
                         nonNullVarLenKeyCols++;
-                    else
+                        nonNullVarLenKeySize += RowAssembler.utf8EncodedLength((CharSequence)vals[i]);
+                    }
+                    else {
                         nonNullVarLenValCols++;
+                        nonNullVarLenValSize += RowAssembler.utf8EncodedLength((CharSequence)vals[i]);
+                    }
                 }
                 else
                     throw new IllegalStateException("Unsupported variable-length type: " + type);
             }
         }
 
-        RowAssembler asm = new RowAssembler(schema, nonNullVarLenKeyCols, nonNullVarLenValCols);
+        RowAssembler asm = new RowAssembler(
+            schema,
+            nonNullVarLenKeySize,
+            nonNullVarLenKeyCols,
+            nonNullVarLenValSize,
+            nonNullVarLenValCols);
 
         for (int i = 0; i < vals.length; i++) {
             if (vals[i] == null)
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 2966b92..2be4efb 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
@@ -106,14 +106,12 @@ public class TupleMarshallerImpl implements TupleMarshaller {
 
             if (val == null)
                 chunk.hasNulls = true;
+            else if (col.type().spec().fixedLength())
+                chunk.payloadLen += col.type().sizeInBytes();
             else {
-                if (col.type().spec().fixedLength())
-                    chunk.payloadLen += col.type().sizeInBytes();
-                else {
-                    chunk.nonNullVarlen++;
+                chunk.nonNullVarlen++;
 
-                    chunk.payloadLen += getValueSize(val, col.type());
-                }
+                chunk.payloadLen += getValueSize(val, col.type());
             }
         }