You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ko...@apache.org on 2022/01/17 08:34:36 UTC

[ignite-3] branch main updated: IGNITE-16296 Sql. Refactoring of integration with Data layer (#552)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 96c0801  IGNITE-16296 Sql. Refactoring of integration with Data layer (#552)
96c0801 is described below

commit 96c0801544fcf508138852360f2fa6eebd29109f
Author: korlov42 <ko...@gridgain.com>
AuthorDate: Mon Jan 17 11:34:31 2022 +0300

    IGNITE-16296 Sql. Refactoring of integration with Data layer (#552)
---
 .../ignite/client/fakes/FakeSchemaRegistry.java    |   6 +
 .../sql/engine/ItProjectScanMergeRuleTest.java     |  16 +--
 .../sql/engine/extension/TestExtension.java        |   6 +-
 .../sql/engine/extension/TestPhysTableScan.java    |  21 ++-
 .../sql/engine/extension/TestTableImpl.java        |   3 +-
 ...ite.internal.sql.engine.extension.SqlExtension} |   0
 .../ignite/internal/schema/SchemaRegistry.java     |   9 ++
 .../schema/registry/SchemaRegistryImpl.java        |   6 +
 .../schema/registry/UpgradingRowAdapter.java       |   8 ++
 .../org/apache/ignite/internal/schema/row/Row.java |  10 ++
 .../ignite/internal/schema/row/RowAssembler.java   |  16 ++-
 .../sql/engine/exec/ExecutionServiceImpl.java      |   2 +-
 .../sql/engine/exec/LogicalRelImplementor.java     |   5 +
 .../internal/sql/engine/exec/rel/ModifyNode.java   |  30 ++--
 .../sql/engine/exec/rel/TableScanNode.java         |  11 +-
 .../internal/sql/engine/prepare/PlannerHelper.java |   2 +-
 .../sql/engine/schema/ColumnDescriptor.java        |   6 +-
 .../sql/engine/schema/ColumnDescriptorImpl.java    |  22 ++-
 .../sql/engine/schema/IgniteTableImpl.java         | 158 ++++++++++++++++-----
 .../sql/engine/schema/InternalIgniteTable.java     |  10 +-
 .../sql/engine/schema/SqlSchemaManagerImpl.java    |  26 ++--
 .../sql/engine/schema/TableDescriptorImpl.java     |   2 +-
 .../ignite/internal/sql/engine/util/TypeUtils.java |   2 +-
 .../internal/sql/engine/StopCalciteModuleTest.java |   4 +-
 .../sql/engine/planner/AbstractPlannerTest.java    |  20 ++-
 .../table/impl/DummySchemaManagerImpl.java         |   6 +
 26 files changed, 293 insertions(+), 114 deletions(-)

diff --git a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeSchemaRegistry.java b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeSchemaRegistry.java
index 1cc3ce7..4239d6c 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeSchemaRegistry.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeSchemaRegistry.java
@@ -105,6 +105,12 @@ public class FakeSchemaRegistry implements SchemaRegistry {
 
     /** {@inheritDoc} */
     @Override
+    public Row resolve(BinaryRow row, SchemaDescriptor desc) {
+        return row == null ? null : new Row(desc, row);
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public Row resolve(BinaryRow row) {
         return row == null ? null : new Row(schema(row.schemaVersion()), row);
     }
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItProjectScanMergeRuleTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItProjectScanMergeRuleTest.java
index 9046602..f7d244a 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItProjectScanMergeRuleTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItProjectScanMergeRuleTest.java
@@ -18,10 +18,9 @@
 package org.apache.ignite.internal.sql.engine;
 
 import static org.apache.ignite.internal.sql.engine.util.QueryChecker.containsAnyProject;
-import static org.apache.ignite.internal.sql.engine.util.QueryChecker.containsIndexScan;
+import static org.apache.ignite.internal.sql.engine.util.QueryChecker.containsAnyScan;
 import static org.apache.ignite.internal.sql.engine.util.QueryChecker.containsOneProject;
 import static org.apache.ignite.internal.sql.engine.util.QueryChecker.containsProject;
-import static org.apache.ignite.internal.sql.engine.util.QueryChecker.containsTableScan;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import org.apache.ignite.internal.schema.configuration.SchemaConfigurationConverter;
@@ -81,12 +80,11 @@ public class ItProjectScanMergeRuleTest extends AbstractBasicIntegrationTest {
     /**
      * Tests that the projects exist only for simple expressions without any predicates.
      */
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-14925")
     @Test
     public void testProjects() {
         assertQuery("SELECT NAME FROM products d;")
-                .matches(containsTableScan("PUBLIC", "PRODUCTS"))
-                .matches(containsOneProject("PUBLIC", "PRODUCTS", 4))
+                .matches(containsAnyScan("PUBLIC", "PRODUCTS"))
+                .matches(containsOneProject("PUBLIC", "PRODUCTS", 5))
                 .returns("noname1")
                 .returns("noname2")
                 .returns("noname3")
@@ -94,8 +92,8 @@ public class ItProjectScanMergeRuleTest extends AbstractBasicIntegrationTest {
                 .check();
 
         assertQuery("SELECT SUBCAT_ID, NAME FROM products d;")
-                .matches(containsTableScan("PUBLIC", "PRODUCTS"))
-                .matches(containsOneProject("PUBLIC", "PRODUCTS", 2, 4))
+                .matches(containsAnyScan("PUBLIC", "PRODUCTS"))
+                .matches(containsOneProject("PUBLIC", "PRODUCTS", 4, 5))
                 .returns(11, "noname1")
                 .returns(11, "noname2")
                 .returns(12, "noname3")
@@ -103,8 +101,8 @@ public class ItProjectScanMergeRuleTest extends AbstractBasicIntegrationTest {
                 .check();
 
         assertQuery("SELECT NAME FROM products d WHERE CAT_ID > 1;")
-                .matches(containsIndexScan("PUBLIC", "PRODUCTS"))
-                .matches(containsProject("PUBLIC", "PRODUCTS", 1, 4))
+                .matches(containsAnyScan("PUBLIC", "PRODUCTS"))
+                .matches(containsProject("PUBLIC", "PRODUCTS", 2, 5))
                 .returns("noname2")
                 .returns("noname3")
                 .returns("noname4")
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestExtension.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestExtension.java
index 32b7167..a4e449d 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestExtension.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestExtension.java
@@ -143,9 +143,9 @@ public class TestExtension implements SqlExtension {
         private final Map<String, IgniteTable> tables = Map.of(TEST_TABLE_NAME, new TestTableImpl(
                 new TableDescriptorImpl(
                         List.of(
-                                new ColumnDescriptorImpl("NODE_ID", true, 0, NativeTypes.stringOf(256), null),
-                                new ColumnDescriptorImpl("NUM", true, 1, NativeTypes.INT32, null),
-                                new ColumnDescriptorImpl("VAL", false, 2, NativeTypes.stringOf(256), null)
+                                new ColumnDescriptorImpl("NODE_ID", true, 0, 0, NativeTypes.stringOf(256), null),
+                                new ColumnDescriptorImpl("NUM", true, 1, 1, NativeTypes.INT32, null),
+                                new ColumnDescriptorImpl("VAL", false, 2, 2, NativeTypes.stringOf(256), null)
                         )
                 )
         ));
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestPhysTableScan.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestPhysTableScan.java
index ce7423d..28c1d45 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestPhysTableScan.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestPhysTableScan.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.sql.engine.extension;
 
-import static org.apache.ignite.internal.sql.engine.trait.TraitUtils.changeTraits;
+import static org.apache.calcite.sql.SqlExplainLevel.EXPPLAN_ATTRIBUTES;
 
 import java.util.List;
 import org.apache.calcite.plan.RelOptCluster;
@@ -26,11 +26,14 @@ import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelInput;
+import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.ignite.internal.sql.engine.externalize.RelInputEx;
 import org.apache.ignite.internal.sql.engine.rel.IgniteRel;
 import org.apache.ignite.internal.sql.engine.rel.IgniteRelVisitor;
+import org.apache.ignite.internal.sql.engine.schema.IgniteTable;
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 /**
@@ -56,7 +59,12 @@ public class TestPhysTableScan extends TableScan implements IgniteRel {
      * @param input Context to recover this relation from.
      */
     public TestPhysTableScan(RelInput input) {
-        super(changeTraits(input, TestExtension.CONVENTION));
+        super(
+                input.getCluster(),
+                input.getTraitSet(),
+                List.of(),
+                ((RelInputEx) input).getTableById("tableId")
+        );
     }
 
     /** {@inheritDoc} */
@@ -71,6 +79,15 @@ public class TestPhysTableScan extends TableScan implements IgniteRel {
         return new TestPhysTableScan(cluster, getTraitSet(), getHints(), getTable());
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public RelWriter explainTerms(RelWriter pw) {
+        return pw
+                .itemIf("table", table.getQualifiedName(), pw.getDetailLevel() == EXPPLAN_ATTRIBUTES)
+                .itemIf("tableId", table.unwrap(IgniteTable.class).id().toString(),
+                        pw.getDetailLevel() != EXPPLAN_ATTRIBUTES);
+    }
+
     @Override
     public @Nullable RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) {
         return super.computeSelfCost(planner, mq);
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestTableImpl.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestTableImpl.java
index 241467a..f35be04 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestTableImpl.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/extension/TestTableImpl.java
@@ -18,7 +18,6 @@
 package org.apache.ignite.internal.sql.engine.extension;
 
 import java.util.List;
-import java.util.UUID;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelTraitSet;
@@ -40,7 +39,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
  * A test table implementation.
  */
 class TestTableImpl extends AbstractTable implements IgniteTable {
-    private final IgniteUuid id = new IgniteUuid(UUID.randomUUID(), 0L);
+    private final IgniteUuid id = IgniteUuid.fromString("78b0de45-e1b4-4bc2-8261-2d0d084409de-0");
 
     private final TableDescriptor desc;
 
diff --git a/modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.internal.processors.query.calcite.org.apache.ignite.internal.sql.engine.extension.SqlExtension b/modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.internal.sql.engine.extension.SqlExtension
similarity index 100%
rename from modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.internal.processors.query.calcite.org.apache.ignite.internal.sql.engine.extension.SqlExtension
rename to modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.internal.sql.engine.extension.SqlExtension
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaRegistry.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaRegistry.java
index afa494d..dd422cd 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaRegistry.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaRegistry.java
@@ -65,6 +65,15 @@ public interface SchemaRegistry {
     public int lastSchemaVersion();
 
     /**
+     * Resolve row for the give schema.
+     *
+     * @param row  Binary row.
+     * @param desc Desired schema.
+     * @return Schema-aware row.
+     */
+    Row resolve(BinaryRow row, SchemaDescriptor desc);
+
+    /**
      * Resolve row.
      * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
      *
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/registry/SchemaRegistryImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/registry/SchemaRegistryImpl.java
index 8eca784..6f6a453 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/registry/SchemaRegistryImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/registry/SchemaRegistryImpl.java
@@ -145,6 +145,12 @@ public class SchemaRegistryImpl implements SchemaRegistry {
 
     /** {@inheritDoc} */
     @Override
+    public Row resolve(BinaryRow row, SchemaDescriptor schemaDescriptor) {
+        return resolveInternal(row, schemaDescriptor);
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public Collection<Row> resolve(Collection<BinaryRow> rows) {
         final SchemaDescriptor curSchema = waitLatestSchema();
 
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/registry/UpgradingRowAdapter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/registry/UpgradingRowAdapter.java
index 877f418..b94a3c9 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/registry/UpgradingRowAdapter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/registry/UpgradingRowAdapter.java
@@ -85,6 +85,14 @@ class UpgradingRowAdapter extends Row {
 
     /** {@inheritDoc} */
     @Override
+    public Object value(int colIdx) {
+        int mappedId = mapColumn(colIdx);
+
+        return mappedId < 0 ? mapper.mappedColumn(colIdx).defaultValue() : super.value(mappedId);
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public byte byteValue(int colIdx) throws InvalidTypeException {
         int mappedId = mapColumn(colIdx);
 
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 ac5042a..9ed3563 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
@@ -91,6 +91,16 @@ public class Row implements BinaryRow, SchemaAware {
      *
      * @param col Column index.
      * @return Column value.
+     */
+    public Object value(int col) {
+        return schema.column(col).type().spec().objectValue(this, col);
+    }
+
+    /**
+     * Reads value for specified column.
+     *
+     * @param col Column index.
+     * @return Column value.
      * @throws InvalidTypeException If actual column type does not match the requested column type.
      */
     public byte byteValue(int col) throws InvalidTypeException {
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 4b29c3f..c58901f 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
@@ -153,13 +153,25 @@ public class RowAssembler {
      * @throws SchemaMismatchException If a value doesn't match the current column type.
      */
     public static void writeValue(RowAssembler rowAsm, Column col, Object val) throws SchemaMismatchException {
+        writeValue(rowAsm, col.type(), val);
+    }
+
+    /**
+     * Helper method.
+     *
+     * @param rowAsm Writes a value as a specified type to assembler.
+     * @param type   Type of the value.
+     * @param val    Value.
+     * @throws SchemaMismatchException If a value doesn't match the current column type.
+     */
+    public static void writeValue(RowAssembler rowAsm, NativeType type, Object val) throws SchemaMismatchException {
         if (val == null) {
             rowAsm.appendNull();
 
             return;
         }
 
-        switch (col.type().spec()) {
+        switch (type.spec()) {
             case INT8: {
                 rowAsm.appendByte((byte) val);
 
@@ -241,7 +253,7 @@ public class RowAssembler {
                 break;
             }
             default:
-                throw new InvalidTypeException("Unexpected value: " + col.type());
+                throw new InvalidTypeException("Unexpected value: " + type);
         }
     }
 
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
index 2464c78..4ca2422 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
@@ -488,7 +488,7 @@ public class ExecutionServiceImpl<RowT> implements ExecutionService {
         // Convert to Relational operators graph
         IgniteRel igniteRel = optimize(sql, planner);
 
-        String plan = RelOptUtil.toString(igniteRel, SqlExplainLevel.ALL_ATTRIBUTES);
+        String plan = RelOptUtil.toString(igniteRel, SqlExplainLevel.EXPPLAN_ATTRIBUTES);
 
         return new ExplainPlan(plan, explainFieldsMetadata(ctx));
     }
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
index b2488d7..f107252 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
@@ -22,6 +22,7 @@ import static org.apache.ignite.internal.sql.engine.util.TypeUtils.combinedRowTy
 import static org.apache.ignite.internal.util.ArrayUtils.asList;
 import static org.apache.ignite.internal.util.CollectionUtils.first;
 
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Objects;
@@ -331,6 +332,10 @@ public class LogicalRelImplementor<RowT> implements IgniteRelVisitor<Node<RowT>>
 
         ColocationGroup group = ctx.group(rel.sourceId());
 
+        if (!group.nodeIds().contains(ctx.localNodeId())) {
+            return new ScanNode<>(ctx, rowType, Collections.emptyList());
+        }
+
         return new TableScanNode<>(
                 ctx,
                 rowType,
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/ModifyNode.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/ModifyNode.java
index e1f4170..cf1ab6b 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/ModifyNode.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/ModifyNode.java
@@ -25,13 +25,13 @@ import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.rel.type.RelDataType;
+import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.sql.engine.exec.ExecutionContext;
 import org.apache.ignite.internal.sql.engine.exec.RowHandler;
 import org.apache.ignite.internal.sql.engine.schema.InternalIgniteTable;
 import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
+import org.apache.ignite.internal.table.InternalTable;
 import org.apache.ignite.lang.IgniteInternalException;
-import org.apache.ignite.table.RecordView;
-import org.apache.ignite.table.Tuple;
 
 /**
  * ModifyNode.
@@ -44,9 +44,9 @@ public class ModifyNode<RowT> extends AbstractNode<RowT> implements SingleNode<R
 
     private final List<String> cols;
 
-    private final RecordView<Tuple> tableView;
+    private final InternalTable tableView;
 
-    private List<Tuple> tuples = new ArrayList<>(MODIFY_BATCH_SIZE);
+    private List<BinaryRow> rows = new ArrayList<>(MODIFY_BATCH_SIZE);
 
     private long updatedRows;
 
@@ -81,7 +81,7 @@ public class ModifyNode<RowT> extends AbstractNode<RowT> implements SingleNode<R
         this.op = op;
         this.cols = cols;
 
-        tableView = table.table().recordView();
+        tableView = table.table();
     }
 
     /** {@inheritDoc} */
@@ -114,7 +114,7 @@ public class ModifyNode<RowT> extends AbstractNode<RowT> implements SingleNode<R
             case DELETE:
             case UPDATE:
             case INSERT:
-                tuples.add(table.toTuple(context(), row, op, cols));
+                rows.add(table.toBinaryRow(context(), row, op, cols));
 
                 flushTuples(false);
 
@@ -186,17 +186,17 @@ public class ModifyNode<RowT> extends AbstractNode<RowT> implements SingleNode<R
     }
 
     private void flushTuples(boolean force) {
-        if (nullOrEmpty(tuples) || !force && tuples.size() < MODIFY_BATCH_SIZE) {
+        if (nullOrEmpty(rows) || !force && rows.size() < MODIFY_BATCH_SIZE) {
             return;
         }
 
-        List<Tuple> tuples = this.tuples;
-        this.tuples = new ArrayList<>(MODIFY_BATCH_SIZE);
+        List<BinaryRow> rows = this.rows;
+        this.rows = new ArrayList<>(MODIFY_BATCH_SIZE);
 
         // TODO: IGNITE-15087 Implement support for transactional SQL
         switch (op) {
             case INSERT:
-                Collection<Tuple> duplicates = tableView.insertAll(null, tuples);
+                Collection<BinaryRow> duplicates = tableView.insertAll(rows, null).join();
 
                 if (!duplicates.isEmpty()) {
                     IgniteTypeFactory typeFactory = context().getTypeFactory();
@@ -207,8 +207,8 @@ public class ModifyNode<RowT> extends AbstractNode<RowT> implements SingleNode<R
 
                     throw new IgniteInternalException(
                             "Failed to INSERT some keys because they are already in cache. "
-                                    + "[tuples=" + duplicates.stream()
-                                    .map(tup -> table.toRow(context(), tup, rowFactory, null))
+                                    + "[rows=" + duplicates.stream()
+                                    .map(binRow -> table.toRow(context(), binRow, rowFactory, null))
                                     .map(context().rowHandler()::toString)
                                     .collect(Collectors.toList()) + ']'
                     );
@@ -216,18 +216,18 @@ public class ModifyNode<RowT> extends AbstractNode<RowT> implements SingleNode<R
 
                 break;
             case UPDATE:
-                tableView.upsertAll(null, tuples);
+                tableView.upsertAll(rows, null).join();
 
                 break;
             case DELETE:
-                tableView.deleteAll(null, tuples);
+                tableView.deleteAll(rows, null).join();
 
                 break;
             default:
                 throw new AssertionError();
         }
 
-        updatedRows += tuples.size();
+        updatedRows += rows.size();
     }
 
     private enum State {
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanNode.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanNode.java
index 04ee36e..3566abb 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanNode.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanNode.java
@@ -32,8 +32,7 @@ import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.sql.engine.exec.ExecutionContext;
 import org.apache.ignite.internal.sql.engine.exec.RowHandler;
 import org.apache.ignite.internal.sql.engine.schema.InternalIgniteTable;
-import org.apache.ignite.internal.table.TableImpl;
-import org.apache.ignite.internal.table.TableRow;
+import org.apache.ignite.internal.table.InternalTable;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -44,7 +43,7 @@ public class TableScanNode<RowT> extends AbstractNode<RowT> {
     private static final int NOT_WAITING = -1;
 
     /** Table that provides access to underlying data. */
-    private final TableImpl physTable;
+    private final InternalTable physTable;
 
     /** Table that is an object in SQL schema. */
     private final InternalIgniteTable schemaTable;
@@ -212,7 +211,7 @@ public class TableScanNode<RowT> extends AbstractNode<RowT> {
         if (subscription != null) {
             subscription.request(waiting);
         } else if (curPartIdx < parts.length) {
-            physTable.internalTable().scan(parts[curPartIdx++], null).subscribe(new SubscriberImpl());
+            physTable.scan(parts[curPartIdx++], null).subscribe(new SubscriberImpl());
         } else {
             waiting = NOT_WAITING;
         }
@@ -270,8 +269,6 @@ public class TableScanNode<RowT> extends AbstractNode<RowT> {
     }
 
     private RowT convert(BinaryRow binRow) {
-        final org.apache.ignite.internal.schema.row.Row wrapped = physTable.schemaView().resolve(binRow);
-
-        return schemaTable.toRow(context(), TableRow.tuple(wrapped), factory, requiredColumns);
+        return schemaTable.toRow(context(), binRow, factory, requiredColumns);
     }
 }
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlannerHelper.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlannerHelper.java
index cd8e52a..af6a596 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlannerHelper.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlannerHelper.java
@@ -233,7 +233,7 @@ public class PlannerHelper {
 
             spoolNeeded = modifyNode.getUpdateColumnList().stream()
                     .map(tbl.descriptor()::columnDescriptor)
-                    .mapToInt(ColumnDescriptor::fieldIndex)
+                    .mapToInt(ColumnDescriptor::logicalIndex)
                     .anyMatch(indexedCols::contains);
 
             return (IgniteRel) scan;
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/ColumnDescriptor.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/ColumnDescriptor.java
index b514a87..57293c8 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/ColumnDescriptor.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/ColumnDescriptor.java
@@ -32,11 +32,13 @@ public interface ColumnDescriptor {
 
     String name();
 
-    int fieldIndex();
+    int logicalIndex();
+
+    int physicalIndex();
 
     RelDataType logicalType(IgniteTypeFactory f);
 
-    NativeType storageType();
+    NativeType physicalType();
 
     Object defaultValue();
 }
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/ColumnDescriptorImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/ColumnDescriptorImpl.java
index 32bd82a..f09541e 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/ColumnDescriptorImpl.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/ColumnDescriptorImpl.java
@@ -36,7 +36,9 @@ public class ColumnDescriptorImpl implements ColumnDescriptor {
 
     private final @Nullable Supplier<Object> dfltVal;
 
-    private final int fieldIdx;
+    private final int logicalIndex;
+
+    private final int physicalIndex;
 
     private final NativeType storageType;
 
@@ -47,14 +49,16 @@ public class ColumnDescriptorImpl implements ColumnDescriptor {
     public ColumnDescriptorImpl(
             String name,
             boolean key,
-            int fieldIdx,
+            int logicalIndex,
+            int physicalIndex,
             NativeType storageType,
             @Nullable Supplier<Object> dfltVal
     ) {
         this.key = key;
         this.name = name;
         this.dfltVal = dfltVal;
-        this.fieldIdx = fieldIdx;
+        this.logicalIndex = logicalIndex;
+        this.physicalIndex = physicalIndex;
         this.storageType = storageType;
     }
 
@@ -84,8 +88,14 @@ public class ColumnDescriptorImpl implements ColumnDescriptor {
 
     /** {@inheritDoc} */
     @Override
-    public int fieldIndex() {
-        return fieldIdx;
+    public int logicalIndex() {
+        return logicalIndex;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int physicalIndex() {
+        return physicalIndex;
     }
 
     /** {@inheritDoc} */
@@ -96,7 +106,7 @@ public class ColumnDescriptorImpl implements ColumnDescriptor {
 
     /** {@inheritDoc} */
     @Override
-    public NativeType storageType() {
+    public NativeType physicalType() {
         return storageType;
     }
 }
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java
index d92505f..e646089 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java
@@ -17,11 +17,12 @@
 
 package org.apache.ignite.internal.sql.engine.schema;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
@@ -38,6 +39,11 @@ import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.schema.Statistic;
 import org.apache.calcite.schema.impl.AbstractTable;
 import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.ignite.internal.schema.BinaryRow;
+import org.apache.ignite.internal.schema.SchemaDescriptor;
+import org.apache.ignite.internal.schema.SchemaRegistry;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.sql.engine.exec.ExecutionContext;
 import org.apache.ignite.internal.sql.engine.exec.RowHandler;
 import org.apache.ignite.internal.sql.engine.metadata.ColocationGroup;
@@ -47,9 +53,8 @@ import org.apache.ignite.internal.sql.engine.rel.logical.IgniteLogicalTableScan;
 import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
 import org.apache.ignite.internal.sql.engine.trait.RewindabilityTrait;
 import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
-import org.apache.ignite.internal.table.TableImpl;
+import org.apache.ignite.internal.table.InternalTable;
 import org.apache.ignite.lang.IgniteUuid;
-import org.apache.ignite.table.Tuple;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -58,22 +63,44 @@ import org.jetbrains.annotations.Nullable;
 public class IgniteTableImpl extends AbstractTable implements InternalIgniteTable {
     private final TableDescriptor desc;
 
-    private final TableImpl table;
+    private final InternalTable table;
+
+    private final SchemaRegistry schemaRegistry;
+
+    public final SchemaDescriptor schemaDescriptor;
 
     private final Statistic statistic;
 
     private final Map<String, IgniteIndex> indexes = new ConcurrentHashMap<>();
 
+    private final List<ColumnDescriptor> columnsOrderedByPhysSchema;
+
     /**
      * Constructor.
      *
      * @param desc  Table descriptor.
      * @param table Physical table this schema object created for.
      */
-    public IgniteTableImpl(TableDescriptor desc, TableImpl table) {
+    public IgniteTableImpl(
+            TableDescriptor desc,
+            InternalTable table,
+            SchemaRegistry schemaRegistry
+    ) {
         this.desc = desc;
         this.table = table;
+        this.schemaRegistry = schemaRegistry;
+        this.schemaDescriptor = schemaRegistry.schema();
+
+        assert schemaDescriptor != null;
+
+        List<ColumnDescriptor> tmp = new ArrayList<>(desc.columnsCount());
+        for (int i = 0; i < desc.columnsCount(); i++) {
+            tmp.add(desc.columnDescriptor(i));
+        }
+
+        tmp.sort(Comparator.comparingInt(ColumnDescriptor::physicalIndex));
 
+        columnsOrderedByPhysSchema = tmp;
         statistic = new StatisticsImpl();
     }
 
@@ -104,7 +131,7 @@ public class IgniteTableImpl extends AbstractTable implements InternalIgniteTabl
 
     /** {@inheritDoc} */
     @Override
-    public TableImpl table() {
+    public InternalTable table() {
         return table;
     }
 
@@ -191,7 +218,7 @@ public class IgniteTableImpl extends AbstractTable implements InternalIgniteTabl
     @Override
     public <RowT> RowT toRow(
             ExecutionContext<RowT> ectx,
-            Tuple row,
+            BinaryRow binaryRow,
             RowHandler.RowFactory<RowT> factory,
             @Nullable ImmutableBitSet requiredColumns
     ) {
@@ -203,17 +230,19 @@ public class IgniteTableImpl extends AbstractTable implements InternalIgniteTabl
 
         assert handler.columnCount(res) == (requiredColumns == null ? desc.columnsCount() : requiredColumns.cardinality());
 
+        Row row = schemaRegistry.resolve(binaryRow, schemaDescriptor);
+
         if (requiredColumns == null) {
             for (int i = 0; i < desc.columnsCount(); i++) {
                 ColumnDescriptor colDesc = desc.columnDescriptor(i);
 
-                handler.set(i, res, row.value(colDesc.fieldIndex()));
+                handler.set(i, res, row.value(colDesc.physicalIndex()));
             }
         } else {
             for (int i = 0, j = requiredColumns.nextSetBit(0); j != -1; j = requiredColumns.nextSetBit(j + 1), i++) {
                 ColumnDescriptor colDesc = desc.columnDescriptor(j);
 
-                handler.set(i, res, row.value(colDesc.fieldIndex()));
+                handler.set(i, res, row.value(colDesc.physicalIndex()));
             }
         }
 
@@ -222,7 +251,7 @@ public class IgniteTableImpl extends AbstractTable implements InternalIgniteTabl
 
     /** {@inheritDoc} */
     @Override
-    public <RowT> Tuple toTuple(
+    public <RowT> BinaryRow toBinaryRow(
             ExecutionContext<RowT> ectx,
             RowT row,
             TableModify.Operation op,
@@ -242,63 +271,114 @@ public class IgniteTableImpl extends AbstractTable implements InternalIgniteTabl
         }
     }
 
-    private <RowT> Tuple insertTuple(RowT row, ExecutionContext<RowT> ectx) {
-        Tuple tuple = Tuple.create(desc.columnsCount());
+    private <RowT> BinaryRow insertTuple(RowT row, ExecutionContext<RowT> ectx) {
+        int nonNullVarlenKeyCols = 0;
+        int nonNullVarlenValCols = 0;
 
         RowHandler<RowT> hnd = ectx.rowHandler();
 
-        for (int i = 0; i < desc.columnsCount(); i++) {
-            tuple.set(desc.columnDescriptor(i).name(), hnd.get(i, row));
+        for (ColumnDescriptor colDesc : columnsOrderedByPhysSchema) {
+            if (colDesc.physicalType().spec().fixedLength()) {
+                continue;
+            }
+
+            Object val = hnd.get(colDesc.logicalIndex(), row);
+
+            if (val != null) {
+                if (colDesc.key()) {
+                    nonNullVarlenKeyCols++;
+                } else {
+                    nonNullVarlenValCols++;
+                }
+            }
+        }
+
+        RowAssembler rowAssembler = new RowAssembler(schemaDescriptor, nonNullVarlenKeyCols, nonNullVarlenValCols);
+
+        for (ColumnDescriptor colDesc : columnsOrderedByPhysSchema) {
+            RowAssembler.writeValue(rowAssembler, colDesc.physicalType(), hnd.get(colDesc.logicalIndex(), row));
         }
 
-        return tuple;
+        return rowAssembler.build();
     }
 
-    private <RowT> Tuple updateTuple(RowT row, List<String> updateColList, ExecutionContext<RowT> ectx) {
+    private <RowT> BinaryRow updateTuple(RowT row, List<String> updateColList, ExecutionContext<RowT> ectx) {
+        int nonNullVarlenKeyCols = 0;
+        int nonNullVarlenValCols = 0;
+
         RowHandler<RowT> hnd = ectx.rowHandler();
         int offset = desc.columnsCount();
-        Tuple tuple = Tuple.create(desc.columnsCount());
-        Set<String> colsToSkip = new HashSet<>(updateColList);
-
-        for (int i = 0; i < desc.columnsCount(); i++) {
-            String colName = desc.columnDescriptor(i).name();
+        Set<String> toUpdate = new HashSet<>(updateColList);
 
-            if (!colsToSkip.contains(colName)) {
-                tuple.set(colName, hnd.get(i, row));
+        for (ColumnDescriptor colDesc : columnsOrderedByPhysSchema) {
+            if (colDesc.physicalType().spec().fixedLength()) {
+                continue;
             }
-        }
 
-        for (int i = 0; i < updateColList.size(); i++) {
-            final ColumnDescriptor colDesc = Objects.requireNonNull(desc.columnDescriptor(updateColList.get(i)));
+            Object val = toUpdate.contains(colDesc.name())
+                    ? hnd.get(colDesc.logicalIndex() + offset, row)
+                    : hnd.get(colDesc.logicalIndex(), row);
 
-            assert !colDesc.key();
+            if (val != null) {
+                if (colDesc.key()) {
+                    nonNullVarlenKeyCols++;
+                } else {
+                    nonNullVarlenValCols++;
+                }
+            }
+        }
 
-            Object fieldVal = hnd.get(i + offset, row);
+        RowAssembler rowAssembler = new RowAssembler(schemaDescriptor, nonNullVarlenKeyCols, nonNullVarlenValCols);
 
-            tuple.set(colDesc.name(), fieldVal);
+        for (ColumnDescriptor colDesc : columnsOrderedByPhysSchema) {
+            RowAssembler.writeValue(
+                    rowAssembler,
+                    colDesc.physicalType(),
+                    toUpdate.contains(colDesc.name())
+                            ? hnd.get(colDesc.logicalIndex() + offset, row)
+                            : hnd.get(colDesc.logicalIndex(), row)
+            );
         }
 
-        return tuple;
+        return rowAssembler.build();
     }
 
-    private <RowT> Tuple deleteTuple(RowT row, ExecutionContext<RowT> ectx) {
+    private <RowT> BinaryRow deleteTuple(RowT row, ExecutionContext<RowT> ectx) {
+        int nonNullVarlenKeyCols = 0;
+
         RowHandler<RowT> hnd = ectx.rowHandler();
-        Tuple tuple = Tuple.create();
 
-        int idx = 0;
-        for (int i = 0; i < desc.columnsCount(); i++) {
-            ColumnDescriptor colDesc = desc.columnDescriptor(i);
+        for (ColumnDescriptor colDesc : columnsOrderedByPhysSchema) {
+            if (!colDesc.key()) {
+                break;
+            }
 
-            if (colDesc.key()) {
-                tuple.set(colDesc.name(), hnd.get(idx++, row));
+            if (colDesc.physicalType().spec().fixedLength()) {
+                continue;
             }
+
+            Object val = hnd.get(colDesc.logicalIndex(), row);
+
+            if (val != null) {
+                nonNullVarlenKeyCols++;
+            }
+        }
+
+        RowAssembler rowAssembler = new RowAssembler(schemaDescriptor, nonNullVarlenKeyCols, 0);
+
+        for (ColumnDescriptor colDesc : columnsOrderedByPhysSchema) {
+            if (!colDesc.key()) {
+                break;
+            }
+
+            RowAssembler.writeValue(rowAssembler, colDesc.physicalType(), hnd.get(colDesc.logicalIndex(), row));
         }
 
-        return tuple;
+        return rowAssembler.build();
     }
 
     private ColocationGroup partitionedGroup() {
-        List<List<String>> assignments = table.internalTable().assignments().stream()
+        List<List<String>> assignments = table.assignments().stream()
                 .map(Collections::singletonList)
                 .collect(Collectors.toList());
 
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/InternalIgniteTable.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/InternalIgniteTable.java
index fea7a33..e1b6199 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/InternalIgniteTable.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/InternalIgniteTable.java
@@ -24,14 +24,14 @@ import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.sql.engine.exec.ExecutionContext;
 import org.apache.ignite.internal.sql.engine.exec.RowHandler;
 import org.apache.ignite.internal.sql.engine.metadata.ColocationGroup;
 import org.apache.ignite.internal.sql.engine.prepare.MappingQueryContext;
 import org.apache.ignite.internal.sql.engine.rel.logical.IgniteLogicalIndexScan;
 import org.apache.ignite.internal.sql.engine.rel.logical.IgniteLogicalTableScan;
-import org.apache.ignite.internal.table.TableImpl;
-import org.apache.ignite.table.Tuple;
+import org.apache.ignite.internal.table.InternalTable;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -80,7 +80,7 @@ public interface InternalIgniteTable extends IgniteTable {
     );
 
     /** Returns the internal table. */
-    TableImpl table();
+    InternalTable table();
 
     /**
      * Converts a tuple to relational node row.
@@ -92,7 +92,7 @@ public interface InternalIgniteTable extends IgniteTable {
      */
     <RowT> RowT toRow(
             ExecutionContext<RowT> ectx,
-            Tuple row,
+            BinaryRow row,
             RowHandler.RowFactory<RowT> factory,
             @Nullable ImmutableBitSet requiredColumns
     );
@@ -106,7 +106,7 @@ public interface InternalIgniteTable extends IgniteTable {
      * @param arg  Operation specific argument.
      * @return Cache key-value tuple;
      */
-    <RowT> Tuple toTuple(
+    <RowT> BinaryRow toBinaryRow(
             ExecutionContext<RowT> ectx,
             RowT row,
             TableModify.Operation op,
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
index 917ae3d..3519d2b 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
@@ -47,7 +47,7 @@ import org.jetbrains.annotations.Nullable;
 public class SqlSchemaManagerImpl implements SqlSchemaManager {
     private final Map<String, IgniteSchema> igniteSchemas = new HashMap<>();
 
-    private final Map<IgniteUuid, InternalIgniteTable> tablesById = new ConcurrentHashMap<>();
+    private final Map<IgniteUuid, IgniteTable> tablesById = new ConcurrentHashMap<>();
 
     private final Map<String, Schema> externalCatalogs = new HashMap<>();
 
@@ -79,8 +79,8 @@ public class SqlSchemaManagerImpl implements SqlSchemaManager {
     /** {@inheritDoc} */
     @Override
     @NotNull
-    public InternalIgniteTable tableById(IgniteUuid id) {
-        InternalIgniteTable table = tablesById.get(id);
+    public IgniteTable tableById(IgniteUuid id) {
+        IgniteTable table = tablesById.get(id);
 
         // there is a chance that someone tries to resolve table before
         // the distributed event of that table creation has been processed
@@ -124,7 +124,12 @@ public class SqlSchemaManagerImpl implements SqlSchemaManager {
     private void registerExternalSchema(String catalogName, String schemaName, ExternalSchema schema) {
         Map<String, Table> tables = new HashMap<>();
 
-        schema.tableNames().forEach(name -> tables.put(name, schema.table(name)));
+        for (String name : schema.tableNames()) {
+            IgniteTable table = schema.table(name);
+
+            tables.put(name, table);
+            tablesById.put(table.id(), table);
+        }
 
         SchemaPlus schemaPlus = (SchemaPlus) externalCatalogs.computeIfAbsent(catalogName, n -> Frameworks.createRootSchema(false));
 
@@ -159,18 +164,21 @@ public class SqlSchemaManagerImpl implements SqlSchemaManager {
                 .map(col -> new ColumnDescriptorImpl(
                         col.name(),
                         descriptor.isKeyColumn(col.schemaIndex()),
+                        col.columnOrder(),
                         col.schemaIndex(),
                         col.type(),
                         col::defaultValue
                 ))
                 .collect(Collectors.toList());
 
-        TableDescriptorImpl desc = new TableDescriptorImpl(colDescriptors);
-
-        IgniteTableImpl table0 = new IgniteTableImpl(desc, table);
+        IgniteTableImpl igniteTable = new IgniteTableImpl(
+                new TableDescriptorImpl(colDescriptors),
+                table.internalTable(),
+                table.schemaView()
+        );
 
-        schema.addTable(removeSchema(schemaName, table.name()), table0);
-        tablesById.put(table0.id(), table0);
+        schema.addTable(removeSchema(schemaName, table.name()), igniteTable);
+        tablesById.put(igniteTable.id(), igniteTable);
 
         rebuild();
     }
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptorImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptorImpl.java
index b779f64..0947829 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptorImpl.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptorImpl.java
@@ -63,7 +63,7 @@ public class TableDescriptorImpl extends NullInitializerExpressionFactory implem
             descriptorsMap.put(descriptor.name(), descriptor);
 
             if (descriptor.key()) {
-                keyFieldsBuilder.set(descriptor.fieldIndex());
+                keyFieldsBuilder.set(descriptor.logicalIndex());
             }
         }
 
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java
index e1cb9bf..fa82561 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java
@@ -236,7 +236,7 @@ public class TypeUtils {
 
         assert fldDesc != null;
 
-        return nativeTypeToClass(fldDesc.storageType());
+        return nativeTypeToClass(fldDesc.physicalType());
     }
 
     /**
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java
index b580ea8..c99d24d 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java
@@ -112,8 +112,8 @@ public class StopCalciteModuleTest {
 
         SchemaDescriptor schemaDesc = new SchemaDescriptor(
                 0,
-                new Column[]{new Column("ID", NativeTypes.INT32, false)},
-                new Column[]{new Column("VAL", NativeTypes.INT32, false)}
+                new Column[]{new Column(0, "ID", NativeTypes.INT32, false)},
+                new Column[]{new Column(1, "VAL", NativeTypes.INT32, false)}
         );
 
         schemaReg = new SchemaRegistryImpl(0, (v) -> schemaDesc, () -> INITIAL_SCHEMA_VERSION);
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
index 5a4afad..7df6c4f 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
@@ -70,6 +70,7 @@ import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql2rel.InitializerContext;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.Util;
+import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.schema.NativeType;
 import org.apache.ignite.internal.sql.engine.exec.ExecutionContext;
 import org.apache.ignite.internal.sql.engine.exec.RowHandler.RowFactory;
@@ -97,12 +98,11 @@ import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
 import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
 import org.apache.ignite.internal.sql.engine.type.IgniteTypeSystem;
 import org.apache.ignite.internal.sql.engine.util.BaseQueryContext;
-import org.apache.ignite.internal.table.TableImpl;
+import org.apache.ignite.internal.table.InternalTable;
 import org.apache.ignite.internal.testframework.IgniteAbstractTest;
 import org.apache.ignite.internal.testframework.IgniteTestUtils;
 import org.apache.ignite.internal.util.ArrayUtils;
 import org.apache.ignite.lang.IgniteUuid;
-import org.apache.ignite.table.Tuple;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -730,20 +730,20 @@ public abstract class AbstractPlannerTest extends IgniteAbstractTest {
 
         /** {@inheritDoc} */
         @Override
-        public TableImpl table() {
+        public InternalTable table() {
             throw new AssertionError();
         }
 
         /** {@inheritDoc} */
         @Override
-        public <RowT> RowT toRow(ExecutionContext<RowT> ectx, Tuple row, RowFactory<RowT> factory,
+        public <RowT> RowT toRow(ExecutionContext<RowT> ectx, BinaryRow row, RowFactory<RowT> factory,
                 @Nullable ImmutableBitSet requiredColumns) {
             throw new AssertionError();
         }
 
         /** {@inheritDoc} */
         @Override
-        public <RowT> Tuple toTuple(ExecutionContext<RowT> ectx, RowT row, Operation op, @Nullable Object arg) {
+        public <RowT> BinaryRow toBinaryRow(ExecutionContext<RowT> ectx, RowT row, Operation op, @Nullable Object arg) {
             throw new AssertionError();
         }
     }
@@ -867,7 +867,13 @@ public abstract class AbstractPlannerTest extends IgniteAbstractTest {
 
         /** {@inheritDoc} */
         @Override
-        public int fieldIndex() {
+        public int logicalIndex() {
+            return idx;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public int physicalIndex() {
             return idx;
         }
 
@@ -879,7 +885,7 @@ public abstract class AbstractPlannerTest extends IgniteAbstractTest {
 
         /** {@inheritDoc} */
         @Override
-        public NativeType storageType() {
+        public NativeType physicalType() {
             throw new AssertionError();
         }
 
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummySchemaManagerImpl.java b/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummySchemaManagerImpl.java
index 1a92b89..916822b 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummySchemaManagerImpl.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummySchemaManagerImpl.java
@@ -72,6 +72,12 @@ public class DummySchemaManagerImpl implements SchemaRegistry {
 
     /** {@inheritDoc} */
     @Override
+    public Row resolve(BinaryRow row, SchemaDescriptor desc) {
+        return row == null ? null : new Row(desc, row);
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public Row resolve(BinaryRow row) {
         assert row == null || row.schemaVersion() == schema.version();