IGNITE-15341 Table API. Rename confusing method getOrCreateTable (#316)

diff --git a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/PrimaryKeyConfigurationSchema.java b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/PrimaryKeyConfigurationSchema.java
new file mode 100644
index 0000000..792a40a
--- /dev/null
+++ b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/PrimaryKeyConfigurationSchema.java
@@ -0,0 +1,38 @@
+/*
+ * 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.configuration.schemas.table;
+
+import org.apache.ignite.configuration.annotation.Config;
+import org.apache.ignite.configuration.annotation.Value;
+import org.apache.ignite.configuration.validation.Immutable;
+
+/**
+ * Configuration for primary key constraint in SQL table.
+ */
+@Config
+public class PrimaryKeyConfigurationSchema {
+    /** Primary key columns names. */
+    @Value
+    @Immutable
+    public String[] columns;
+
+    /** Primary key affinity columns names. */
+    @Value(hasDefault = true)
+    @Immutable
+    public String[] affinityColumns = new String[0];
+}
diff --git a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableConfigurationSchema.java b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableConfigurationSchema.java
index a42be6c..7b30ce1 100644
--- a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableConfigurationSchema.java
+++ b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableConfigurationSchema.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.configuration.schemas.table;
 
 import org.apache.ignite.configuration.annotation.Config;
+import org.apache.ignite.configuration.annotation.ConfigValue;
 import org.apache.ignite.configuration.annotation.NamedConfigValue;
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.validation.Immutable;
@@ -25,7 +26,7 @@
 import org.apache.ignite.configuration.validation.Min;
 
 /**
- * Table configuartion schema class.
+ * Table configuration schema class.
  */
 @Config
 public class TableConfigurationSchema {
@@ -49,6 +50,10 @@
     @NamedConfigValue
     public ColumnConfigurationSchema columns;
 
+    /** Primary key configuration. */
+    @ConfigValue
+    public PrimaryKeyConfigurationSchema primaryKey;
+
     /** Indices configuration. */
     @NamedConfigValue
     public TableIndexConfigurationSchema indices;
diff --git a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableIndexConfigurationSchema.java b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableIndexConfigurationSchema.java
index dd6d1c0..88f7838 100644
--- a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableIndexConfigurationSchema.java
+++ b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableIndexConfigurationSchema.java
@@ -52,7 +52,7 @@
     @Value(hasDefault = true)
     public String expr = "";
 
-    /** Affinity column names for PrimaryIndex. */
+    /** Affinity column names for PrimaryKey. */
     @Value(hasDefault = true)
     public String[] affinityColumns = new String[0];
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableValidator.java b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableValidator.java
index ed0d65d..fee009b 100644
--- a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableValidator.java
+++ b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/table/TableValidator.java
@@ -27,7 +27,7 @@
 /**
  * Annotation to validate whole table configuration.
  *
- * Activate SchemaTableValidatorImpl in configuration engine for {@link TablesConfigurationSchema#tables}.
+ * Activate TableValidatorImpl in configuration engine for {@link TablesConfigurationSchema#tables}.
  */
 @Target({ FIELD, PARAMETER })
 @Retention(RUNTIME)
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/SchemaNamedObject.java b/modules/api/src/main/java/org/apache/ignite/lang/TableAlreadyExistsException.java
similarity index 68%
rename from modules/api/src/main/java/org/apache/ignite/schema/SchemaNamedObject.java
rename to modules/api/src/main/java/org/apache/ignite/lang/TableAlreadyExistsException.java
index d876c2b..8e48946 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/SchemaNamedObject.java
+++ b/modules/api/src/main/java/org/apache/ignite/lang/TableAlreadyExistsException.java
@@ -15,16 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.lang;
 
 /**
- * Schema named object.
+ * This exception is thrown when a new table failed to be created,
+ * because a table with same name already exists.
  */
-public interface SchemaNamedObject {
+public class TableAlreadyExistsException extends IgniteException {
     /**
-     * Returns object name.
+     * Create a new exception with given error message.
      *
-     * @return Schema object name.
+     * @param msg Error message.
      */
-    String name();
+    public TableAlreadyExistsException(String msg) {
+        super(msg);
+    }
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/PrimaryIndex.java b/modules/api/src/main/java/org/apache/ignite/schema/PrimaryIndex.java
deleted file mode 100644
index 8584a47..0000000
--- a/modules/api/src/main/java/org/apache/ignite/schema/PrimaryIndex.java
+++ /dev/null
@@ -1,35 +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.schema;
-
-import java.util.List;
-
-/**
- * Primary key index.
- */
-public interface PrimaryIndex extends SortedIndex {
-    /** Primary key index name. */
-    String PRIMARY_KEY_INDEX_NAME = "PK";
-
-    /**
-     * Returns affinity columns.
-     *
-     * @return Columns list.
-     */
-    List<String> affinityColumns();
-}
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/TableIndex.java b/modules/api/src/main/java/org/apache/ignite/schema/TableIndex.java
deleted file mode 100644
index f693590..0000000
--- a/modules/api/src/main/java/org/apache/ignite/schema/TableIndex.java
+++ /dev/null
@@ -1,37 +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.schema;
-
-/**
- * Table index base interface.
- */
-public interface TableIndex extends SchemaNamedObject {
-    /**
-     * Returns index name.
-     *
-     * @return Index name.
-     */
-    @Override String name();
-
-    /**
-     * Returns index type.
-     *
-     * @return Index type.
-     */
-    String type();
-}
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/builder/PrimaryIndexBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/builder/PrimaryIndexBuilder.java
deleted file mode 100644
index d45b266..0000000
--- a/modules/api/src/main/java/org/apache/ignite/schema/builder/PrimaryIndexBuilder.java
+++ /dev/null
@@ -1,61 +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.schema.builder;
-
-import org.apache.ignite.schema.PrimaryIndex;
-
-/**
- * Hash index descriptor builder.
- */
-public interface PrimaryIndexBuilder extends SortedIndexBuilder {
-    /**
-     * Sets affinity columns.
-     *
-     * @param cols Affinity columns
-     * @return Primary index builder.
-     */
-    PrimaryIndexBuilder withAffinityColumns(String... cols);
-
-    /** {@inheritDoc} */
-    @Override PrimaryIndexColumnBuilder addIndexColumn(String name);
-
-    /**
-     * Builds primary index.
-     *
-     * @return Primary index.
-     */
-    @Override PrimaryIndex build();
-
-    /**
-     * Index column builder.
-     */
-    @SuppressWarnings("PublicInnerClass")
-    interface PrimaryIndexColumnBuilder extends SortedIndexColumnBuilder {
-        /** {@inheritDoc} */
-        @Override PrimaryIndexColumnBuilder desc();
-
-        /** {@inheritDoc} */
-        @Override PrimaryIndexColumnBuilder asc();
-
-        /** {@inheritDoc} */
-        @Override PrimaryIndexColumnBuilder withName(String name);
-
-        /** {@inheritDoc} */
-        @Override PrimaryIndexBuilder done();
-    }
-}
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/builder/SchemaTableBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/builder/SchemaTableBuilder.java
deleted file mode 100644
index ef87443..0000000
--- a/modules/api/src/main/java/org/apache/ignite/schema/builder/SchemaTableBuilder.java
+++ /dev/null
@@ -1,64 +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.schema.builder;
-
-import java.util.Map;
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.PrimaryIndex;
-import org.apache.ignite.schema.SchemaTable;
-import org.apache.ignite.schema.TableIndex;
-
-/**
- * Table descriptor builder.
- */
-public interface SchemaTableBuilder extends SchemaObjectBuilder {
-    /**
-     * Adds columns to the table.
-     *
-     * @param columns Table columns.
-     * @return {@code This} for chaining.
-     */
-    SchemaTableBuilder columns(Column... columns);
-
-    /**
-     * Adds an index.
-     *
-     * @param index Table index.
-     * @return {@code This} for chaining.
-     */
-    SchemaTableBuilder withIndex(TableIndex index);
-
-    /**
-     * Shortcut method for adding {@link PrimaryIndex} via {@link #withIndex(TableIndex)}.
-     *
-     * @param colName Key column name.
-     * @return {@code This} for chaining.
-     */
-    SchemaTableBuilder withPrimaryKey(String colName);
-
-    /** {@inheritDoc} */
-    @Override SchemaTableBuilder withHints(Map<String, String> hints);
-
-    /**
-     * Builds table.
-     *
-     * @return Table.
-     */
-    @Override SchemaTable build();
-
-}
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/Column.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/ColumnDefinition.java
similarity index 79%
rename from modules/api/src/main/java/org/apache/ignite/schema/Column.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/ColumnDefinition.java
index 72092fb..6da286f 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/Column.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/ColumnDefinition.java
@@ -15,18 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition;
 
 /**
  * Table column descriptor.
  */
-public interface Column extends SchemaNamedObject {
+public interface ColumnDefinition {
     /**
      * Returns column name.
      *
      * @return Column name.
      */
-    @Override String name();
+    String name();
 
     /**
      * Returns column type.
@@ -43,9 +43,10 @@
     boolean nullable();
 
     /**
-     * Returns column default value.
+     * Returns column default value expression.
      *
-     * @return Default column value.
+     * @return Default column value expression.
      */
+    //TODO: IGNITE-15341 Rename to defaultValueExpr or allow constants? How to distinct expression from string constant???
     Object defaultValue();
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/ColumnType.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/ColumnType.java
similarity index 99%
rename from modules/api/src/main/java/org/apache/ignite/schema/ColumnType.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/ColumnType.java
index d15e72f..eff23e4 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/ColumnType.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/ColumnType.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition;
 
 import java.util.Objects;
 
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/ColumnarIndex.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/PrimaryKeyDefinition.java
similarity index 71%
copy from modules/api/src/main/java/org/apache/ignite/schema/ColumnarIndex.java
copy to modules/api/src/main/java/org/apache/ignite/schema/definition/PrimaryKeyDefinition.java
index f187bb6..77d057f 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/ColumnarIndex.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/PrimaryKeyDefinition.java
@@ -15,27 +15,28 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition;
 
-import java.util.List;
+import java.util.Set;
 
 /**
- * Columnar index interface.
+ * Primary key constraint.
  */
-public interface ColumnarIndex {
+public interface PrimaryKeyDefinition extends SchemaObject {
+    /** Default primary key name. */
+    String PRIMARY_KEY_NAME = "PK";
+
     /**
      * Configured index columns.
      *
      * @return Index columns.
      */
-    List<? extends IndexColumn> columns();
+    Set<String> columns();
 
     /**
-     * Returns all index columns: user defined + implicitly attched.
+     * Returns affinity columns.
      *
-     * @return Indexed columns.
+     * @return Columns list.
      */
-    default List<? extends IndexColumn> indexedColumns() {
-        return columns();
-    }
+    Set<String> affinityColumns();
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/SchemaMode.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/SchemaManagementMode.java
similarity index 90%
rename from modules/api/src/main/java/org/apache/ignite/schema/SchemaMode.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/SchemaManagementMode.java
index a3fc604..893dbcd 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/SchemaMode.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/SchemaManagementMode.java
@@ -15,24 +15,25 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition;
 
 /**
  * Schema mode.
  * <p>
  * Defines the way inserting data will be validated against the schema and schema evolution capabilities.
  */
-public enum SchemaMode {
+//TODO: rename to MANUAL and AUTO?
+public enum SchemaManagementMode {
     /**
      * Normal mode offers strong validation for the inserting data.
      * Explicit schema changes only are allowed.
      */
-    STRICT_SCHEMA,
+    STRICT,
 
     /**
      * Extended mode that allows the schema to be fit the inserting data automatically.
      * Only safe implicit schema changes are allowed, e.g. adding extra columns and widening column type.
      * Changes like column removal or narrowing column type won't be applied implicitly.
      */
-    LIVE_SCHEMA
+    LIVE
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/definition/SchemaObject.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/SchemaObject.java
new file mode 100644
index 0000000..9ca8920
--- /dev/null
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/SchemaObject.java
@@ -0,0 +1,51 @@
+/*
+ * 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.schema.definition;
+
+/**
+ * Schema object.
+ */
+public interface SchemaObject {
+    /** Default schema name. */
+    String DEFAULT_DATABASE_SCHEMA_NAME = "PUBLIC";
+
+    /**
+     * Returns name of schema object.
+     *
+     * @return Object name.
+     */
+    String name();
+
+    /**
+     * Returns database schema name this object belongs to.
+     *
+     * @return Database schema name.
+     */
+    default String schemaName() {
+        return DEFAULT_DATABASE_SCHEMA_NAME;
+    }
+
+    /**
+     * Returns object`s canonical name.
+     *
+     * @return Canonical name.
+     */
+    default String canonicalName() {
+        return schemaName() + '.' + name();
+    }
+}
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/SchemaTable.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/TableDefinition.java
similarity index 74%
rename from modules/api/src/main/java/org/apache/ignite/schema/SchemaTable.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/TableDefinition.java
index 9d3ac56..21b1a15 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/SchemaTable.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/TableDefinition.java
@@ -15,17 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition;
 
 import java.util.Collection;
+import org.apache.ignite.schema.definition.index.IndexDefinition;
 import org.apache.ignite.schema.modification.TableModificationBuilder;
 
 /**
- * Schema table descriptor.
+ * Table schema configuration.
  */
-public interface SchemaTable extends SchemaNamedObject {
-    /** Default schema name. */
-    String DEFAULT_SCHEMA_NAME = "PUBLIC";
+public interface TableDefinition extends SchemaObject {
 
     /**
      * Returns table name.
@@ -39,35 +38,28 @@
      *
      * @return List of columns.
      */
-    Collection<Column> keyColumns();
+    Collection<ColumnDefinition> keyColumns();
 
     /**
      * Returns affinity columns.
      *
      * @return List of columns.
      */
-    Collection<Column> affinityColumns();
+    Collection<ColumnDefinition> affinityColumns();
 
     /**
      * Returns value columns.
      *
      * @return List of columns.
      */
-    Collection<Column> valueColumns();
-
-    /**
-     * Returns canonical table name (Concatenation of schema name and table name).
-     *
-     * @return Canonical table name.
-     */
-    String canonicalName();
+    Collection<ColumnDefinition> valueColumns();
 
     /**
      * Returns table indices.
      *
      * @return Collection of indexes.
      */
-    Collection<TableIndex> indices();
+    Collection<IndexDefinition> indices();
 
     /**
      * Converts table descriptor to table modification builder.
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/builder/TableColumnBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/ColumnDefinitionBuilder.java
similarity index 68%
rename from modules/api/src/main/java/org/apache/ignite/schema/builder/TableColumnBuilder.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/builder/ColumnDefinitionBuilder.java
index ed6b40e..4fd540a 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/builder/TableColumnBuilder.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/ColumnDefinitionBuilder.java
@@ -15,45 +15,45 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema.builder;
+package org.apache.ignite.schema.definition.builder;
 
 import java.util.Map;
-import org.apache.ignite.schema.Column;
+import org.apache.ignite.schema.definition.ColumnDefinition;
 
 /**
  * Table column builder.
  */
-public interface TableColumnBuilder extends SchemaObjectBuilder {
+public interface ColumnDefinitionBuilder extends SchemaObjectBuilder {
     /**
      * Mark column as nullable.
      *
      * @return {@code this} for chaining.
      */
-    TableColumnBuilder asNullable();
+    ColumnDefinitionBuilder asNullable();
 
     /**
      * Mark column as non-nullable.
      *
      * @return {@code this} for chaining.
      */
-    TableColumnBuilder asNonNull();
+    ColumnDefinitionBuilder asNonNull();
 
     /**
-     * Sets column default value.
+     * Sets column default value expression.
      *
-     * @param defValue Default value.
+     * @param defValExpr Default value expression.
      * @return {@code this} for chaining.
      */
-    TableColumnBuilder withDefaultValue(Object defValue);
+    ColumnDefinitionBuilder withDefaultValueExpression(Object defValExpr);
 
     /** {@inheritDoc} */
-    @Override TableColumnBuilder withHints(Map<String, String> hints);
+    @Override ColumnDefinitionBuilder withHints(Map<String, String> hints);
 
     /**
      * Builds column.
      *
      * @return Built column.
      */
-    @Override Column build();
+    @Override ColumnDefinition build();
 }
 
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/builder/HashIndexBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/HashIndexDefinitionBuilder.java
similarity index 74%
rename from modules/api/src/main/java/org/apache/ignite/schema/builder/HashIndexBuilder.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/builder/HashIndexDefinitionBuilder.java
index 4ed2565..4718374 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/builder/HashIndexBuilder.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/HashIndexDefinitionBuilder.java
@@ -15,30 +15,30 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema.builder;
+package org.apache.ignite.schema.definition.builder;
 
 import java.util.Map;
-import org.apache.ignite.schema.HashIndex;
+import org.apache.ignite.schema.definition.index.HashIndexDefinition;
 
 /**
  * Hash index descriptor builder.
  */
-public interface HashIndexBuilder extends SchemaObjectBuilder {
+public interface HashIndexDefinitionBuilder extends SchemaObjectBuilder {
     /**
      * Sets indexed columns.
      *
      * @param columns Indexed columns.
      * @return {@code this} for chaining.
      */
-    HashIndexBuilder withColumns(String... columns);
+    HashIndexDefinitionBuilder withColumns(String... columns);
 
     /** {@inheritDoc} */
-    @Override HashIndexBuilder withHints(Map<String, String> hints);
+    @Override HashIndexDefinitionBuilder withHints(Map<String, String> hints);
 
     /**
      * Builds hash index.
      *
      * @return Hash index.
      */
-    @Override HashIndex build();
+    @Override HashIndexDefinition build();
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/builder/PartialIndexBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/PartialIndexDefinitionBuilder.java
similarity index 78%
rename from modules/api/src/main/java/org/apache/ignite/schema/builder/PartialIndexBuilder.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/builder/PartialIndexDefinitionBuilder.java
index 5ce2376..dcdf98a 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/builder/PartialIndexBuilder.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/PartialIndexDefinitionBuilder.java
@@ -15,35 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema.builder;
+package org.apache.ignite.schema.definition.builder;
 
 import java.util.Map;
-import org.apache.ignite.schema.PartialIndex;
+import org.apache.ignite.schema.definition.index.PartialIndexDefinition;
 
 /**
  * Partial index descriptor builder.
  */
-public interface PartialIndexBuilder extends SortedIndexBuilder {
+public interface PartialIndexDefinitionBuilder extends SortedIndexDefinitionBuilder {
     /**
      * Sets partial index expression.
      *
      * @param expr Partial index expression.
      * @return {@code this} for chaining.
      */
-    PartialIndexBuilder withExpression(String expr);
+    PartialIndexDefinitionBuilder withExpression(String expr);
 
     /** {@inheritDoc} */
     @Override PartialIndexColumnBuilder addIndexColumn(String name);
 
     /** {@inheritDoc} */
-    @Override PartialIndexBuilder withHints(Map<String, String> hints);
+    @Override PartialIndexDefinitionBuilder withHints(Map<String, String> hints);
 
     /**
      * Builds partial index.
      *
      * @return Partial index.
      */
-    @Override PartialIndex build();
+    @Override PartialIndexDefinition build();
 
     /**
      * Index column builder.
@@ -60,6 +60,6 @@
         @Override PartialIndexColumnBuilder withName(String name);
 
         /** {@inheritDoc} */
-        @Override PartialIndexBuilder done();
+        @Override PartialIndexDefinitionBuilder done();
     }
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/builder/HashIndexBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/PrimaryKeyDefinitionBuilder.java
similarity index 60%
copy from modules/api/src/main/java/org/apache/ignite/schema/builder/HashIndexBuilder.java
copy to modules/api/src/main/java/org/apache/ignite/schema/definition/builder/PrimaryKeyDefinitionBuilder.java
index 4ed2565..0fd70e7 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/builder/HashIndexBuilder.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/PrimaryKeyDefinitionBuilder.java
@@ -15,30 +15,34 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema.builder;
+package org.apache.ignite.schema.definition.builder;
 
-import java.util.Map;
-import org.apache.ignite.schema.HashIndex;
+import org.apache.ignite.schema.definition.PrimaryKeyDefinition;
 
 /**
  * Hash index descriptor builder.
  */
-public interface HashIndexBuilder extends SchemaObjectBuilder {
+public interface PrimaryKeyDefinitionBuilder extends SchemaObjectBuilder {
     /**
-     * Sets indexed columns.
+     * Sets affinity columns.
+     *
+     * @param cols Affinity columns. Must be a valid subset of ley columns.
+     * @return Primary index builder.
+     */
+    PrimaryKeyDefinitionBuilder withAffinityColumns(String... cols);
+
+    /**
+     * Sets primary key columns.
      *
      * @param columns Indexed columns.
      * @return {@code this} for chaining.
      */
-    HashIndexBuilder withColumns(String... columns);
-
-    /** {@inheritDoc} */
-    @Override HashIndexBuilder withHints(Map<String, String> hints);
+    PrimaryKeyDefinitionBuilder withColumns(String... columns);
 
     /**
-     * Builds hash index.
+     * Builds primary key.
      *
-     * @return Hash index.
+     * @return Primary key.
      */
-    @Override HashIndex build();
+    @Override PrimaryKeyDefinition build();
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/builder/SchemaObjectBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/SchemaObjectBuilder.java
similarity index 92%
rename from modules/api/src/main/java/org/apache/ignite/schema/builder/SchemaObjectBuilder.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/builder/SchemaObjectBuilder.java
index 3d468bd..cc923b9 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/builder/SchemaObjectBuilder.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/SchemaObjectBuilder.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema.builder;
+package org.apache.ignite.schema.definition.builder;
 
 import java.util.Map;
 
@@ -24,7 +24,7 @@
  */
 public interface SchemaObjectBuilder {
     /**
-     * Provide hints to builder.
+     * Provide hints to a builder.
      *
      * @param hints Hints.
      * @return {@code This} for chaining.
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/builder/SortedIndexBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/SortedIndexDefinitionBuilder.java
similarity index 79%
rename from modules/api/src/main/java/org/apache/ignite/schema/builder/SortedIndexBuilder.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/builder/SortedIndexDefinitionBuilder.java
index 1bacea8..7fb74a2 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/builder/SortedIndexBuilder.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/SortedIndexDefinitionBuilder.java
@@ -15,22 +15,15 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema.builder;
+package org.apache.ignite.schema.definition.builder;
 
 import java.util.Map;
-import org.apache.ignite.schema.SortedIndex;
+import org.apache.ignite.schema.definition.index.SortedIndexDefinition;
 
 /**
  * Sorted index descriptor builder.
  */
-public interface SortedIndexBuilder extends SchemaObjectBuilder {
-    /**
-     * Sets unique flag to {@code true}.
-     *
-     * @return {@code this} for chaining.
-     */
-    SortedIndexBuilder unique();
-
+public interface SortedIndexDefinitionBuilder extends SchemaObjectBuilder {
     /**
      * Adds a column to index.
      *
@@ -40,14 +33,21 @@
     SortedIndexColumnBuilder addIndexColumn(String name);
 
     /** {@inheritDoc} */
-    @Override SortedIndexBuilder withHints(Map<String, String> hints);
+    @Override SortedIndexDefinitionBuilder withHints(Map<String, String> hints);
+
+    /**
+     * Unique index flag.
+     *
+     * @return {@code This} for chaining.
+     */
+    SortedIndexDefinitionBuilder unique(boolean b);
 
     /**
      * Builds sorted index.
      *
      * @return Sorted index.
      */
-    @Override SortedIndex build();
+    @Override SortedIndexDefinition build();
 
     /**
      * Index column builder.
@@ -81,6 +81,6 @@
          *
          * @return Parent builder for chaining.
          */
-        SortedIndexBuilder done();
+        SortedIndexDefinitionBuilder done();
     }
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/TableSchemaBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/TableSchemaBuilder.java
new file mode 100644
index 0000000..e49e251
--- /dev/null
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/builder/TableSchemaBuilder.java
@@ -0,0 +1,72 @@
+/*
+ * 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.schema.definition.builder;
+
+import java.util.Map;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.PrimaryKeyDefinition;
+import org.apache.ignite.schema.definition.TableDefinition;
+import org.apache.ignite.schema.definition.index.IndexDefinition;
+
+/**
+ * Table descriptor builder.
+ */
+public interface TableSchemaBuilder extends SchemaObjectBuilder {
+    /**
+     * Adds columns to the table.
+     *
+     * @param columns Table columns.
+     * @return {@code This} for chaining.
+     */
+    TableSchemaBuilder columns(ColumnDefinition... columns);
+
+    /**
+     * Adds an index.
+     *
+     * @param indexDefinition Table index.
+     * @return {@code This} for chaining.
+     */
+    TableSchemaBuilder withIndex(IndexDefinition indexDefinition);
+
+    /**
+     * Shortcut method for adding {@link PrimaryKeyDefinition} of single column.
+     *
+     * @param colName Key column name.
+     * @return {@code This} for chaining.
+     */
+    TableSchemaBuilder withPrimaryKey(String colName);
+
+    /**
+     * Adds primary key constraint to the table.
+     *
+     * @param primaryKeyDefinition Primary key.
+     * @return {@code This} for chaining.
+     */
+    TableSchemaBuilder withPrimaryKey(PrimaryKeyDefinition primaryKeyDefinition);
+
+    /** {@inheritDoc} */
+    @Override TableSchemaBuilder withHints(Map<String, String> hints);
+
+    /**
+     * Builds table.
+     *
+     * @return Table.
+     */
+    @Override TableDefinition build();
+
+}
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/ColumnarIndex.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/ColumnarIndexDefinition.java
similarity index 81%
rename from modules/api/src/main/java/org/apache/ignite/schema/ColumnarIndex.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/index/ColumnarIndexDefinition.java
index f187bb6..669787e 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/ColumnarIndex.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/ColumnarIndexDefinition.java
@@ -15,27 +15,27 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition.index;
 
 import java.util.List;
 
 /**
  * Columnar index interface.
  */
-public interface ColumnarIndex {
+public interface ColumnarIndexDefinition extends IndexDefinition {
     /**
      * Configured index columns.
      *
      * @return Index columns.
      */
-    List<? extends IndexColumn> columns();
+    List<? extends IndexColumnDefinition> columns();
 
     /**
      * Returns all index columns: user defined + implicitly attched.
      *
      * @return Indexed columns.
      */
-    default List<? extends IndexColumn> indexedColumns() {
+    default List<? extends IndexColumnDefinition> indexedColumns() {
         return columns();
     }
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/HashIndex.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/HashIndexDefinition.java
similarity index 87%
rename from modules/api/src/main/java/org/apache/ignite/schema/HashIndex.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/index/HashIndexDefinition.java
index 2a68e32..8da1925 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/HashIndex.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/HashIndexDefinition.java
@@ -15,12 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition.index;
 
 /**
  * Hash index descriptor.
  */
-public interface HashIndex extends TableIndex, ColumnarIndex {
+public interface HashIndexDefinition extends ColumnarIndexDefinition {
     /** {@inheritDoc} */
     @Override default String type() {
         return "HASH";
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/IndexColumn.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/IndexColumnDefinition.java
similarity index 87%
rename from modules/api/src/main/java/org/apache/ignite/schema/IndexColumn.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/index/IndexColumnDefinition.java
index bea735b..14fe672 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/IndexColumn.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/IndexColumnDefinition.java
@@ -15,16 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition.index;
 
 /**
  * Index column descriptor.
  */
-public interface IndexColumn extends SchemaNamedObject {
+public interface IndexColumnDefinition {
     /**
      * Returns column name.
      *
      * @return Column name.
      */
-    @Override String name();
+    String name();
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/SortedIndex.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/IndexDefinition.java
similarity index 73%
rename from modules/api/src/main/java/org/apache/ignite/schema/SortedIndex.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/index/IndexDefinition.java
index 8381ca0..9ca4da9 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/SortedIndex.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/IndexDefinition.java
@@ -15,19 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition.index;
 
-import java.util.List;
+import org.apache.ignite.schema.definition.SchemaObject;
 
 /**
- * Sorted index descriptor.
+ * Table index base interface.
  */
-public interface SortedIndex extends TableIndex, ColumnarIndex {
-    /** {@inheritDoc} */
-    @Override List<SortedIndexColumn> columns();
-
-    /** {@inheritDoc} */
-    @Override List<SortedIndexColumn> indexedColumns();
+public interface IndexDefinition extends SchemaObject {
+    /**
+     * Returns index name.
+     *
+     * @return Index name.
+     */
+    @Override String name();
 
     /**
      * Unique index flag.
@@ -41,8 +42,10 @@
         return false;
     }
 
-    /** {@inheritDoc} */
-    @Override default String type() {
-        return "SORTED";
-    }
+    /**
+     * Returns index type.
+     *
+     * @return Index type.
+     */
+    String type();
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/PartialIndex.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/PartialIndexDefinition.java
similarity index 88%
rename from modules/api/src/main/java/org/apache/ignite/schema/PartialIndex.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/index/PartialIndexDefinition.java
index 92412d5..1f8754f 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/PartialIndex.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/PartialIndexDefinition.java
@@ -15,12 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition.index;
 
 /**
  * Partial index descriptor.
  */
-public interface PartialIndex extends SortedIndex {
+public interface PartialIndexDefinition extends SortedIndexDefinition {
     /**
      * Partial index expression.
      *
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/SortOrder.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/SortOrder.java
similarity index 94%
rename from modules/api/src/main/java/org/apache/ignite/schema/SortOrder.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/index/SortOrder.java
index 282ebfc..47843cb 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/SortOrder.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/SortOrder.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition.index;
 
 /**
  * Index column sort order.
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/SortedIndexColumn.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/SortedIndexColumnDefinition.java
similarity index 87%
rename from modules/api/src/main/java/org/apache/ignite/schema/SortedIndexColumn.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/index/SortedIndexColumnDefinition.java
index ccc148f..d897b9d 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/SortedIndexColumn.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/SortedIndexColumnDefinition.java
@@ -15,12 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition.index;
 
 /**
  * Sorted index column.
  */
-public interface SortedIndexColumn extends IndexColumn {
+public interface SortedIndexColumnDefinition extends IndexColumnDefinition {
     /**
      * Returns column sort order.
      *
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/HashIndex.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/SortedIndexDefinition.java
similarity index 69%
copy from modules/api/src/main/java/org/apache/ignite/schema/HashIndex.java
copy to modules/api/src/main/java/org/apache/ignite/schema/definition/index/SortedIndexDefinition.java
index 2a68e32..7e4d5d0 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/HashIndex.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/SortedIndexDefinition.java
@@ -15,14 +15,22 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition.index;
+
+import java.util.List;
 
 /**
- * Hash index descriptor.
+ * Sorted index descriptor.
  */
-public interface HashIndex extends TableIndex, ColumnarIndex {
+public interface SortedIndexDefinition extends ColumnarIndexDefinition {
+    /** {@inheritDoc} */
+    @Override List<SortedIndexColumnDefinition> columns();
+
+    /** {@inheritDoc} */
+    @Override List<SortedIndexColumnDefinition> indexedColumns();
+
     /** {@inheritDoc} */
     @Override default String type() {
-        return "HASH";
+        return "SORTED";
     }
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/builder/package-info.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/package-info.java
similarity index 89%
rename from modules/api/src/main/java/org/apache/ignite/schema/builder/package-info.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/index/package-info.java
index 7b6c67f..885e305 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/builder/package-info.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/index/package-info.java
@@ -16,6 +16,6 @@
  */
 
 /**
- * Contains table schema definition builders.
+ * Contains index definition interfaces.
  */
-package org.apache.ignite.schema.builder;
+package org.apache.ignite.schema.definition.index;
\ No newline at end of file
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/package-info.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/package-info.java
similarity index 94%
rename from modules/api/src/main/java/org/apache/ignite/schema/package-info.java
rename to modules/api/src/main/java/org/apache/ignite/schema/definition/package-info.java
index e818bf0..4dacdbd 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/package-info.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/package-info.java
@@ -18,4 +18,4 @@
 /**
  * Contains table schema definition interfaces and classes.
  */
-package org.apache.ignite.schema;
+package org.apache.ignite.schema.definition;
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/modification/AlterColumnBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/modification/AlterColumnBuilder.java
index 1c8916d..9e0d234 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/modification/AlterColumnBuilder.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/modification/AlterColumnBuilder.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.schema.modification;
 
-import org.apache.ignite.schema.ColumnType;
+import org.apache.ignite.schema.definition.ColumnType;
 
 /**
  * Alter column builder.
diff --git a/modules/api/src/main/java/org/apache/ignite/schema/modification/TableModificationBuilder.java b/modules/api/src/main/java/org/apache/ignite/schema/modification/TableModificationBuilder.java
index 9e7f903..2a07e5d 100644
--- a/modules/api/src/main/java/org/apache/ignite/schema/modification/TableModificationBuilder.java
+++ b/modules/api/src/main/java/org/apache/ignite/schema/modification/TableModificationBuilder.java
@@ -17,8 +17,8 @@
 
 package org.apache.ignite.schema.modification;
 
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.TableIndex;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.index.IndexDefinition;
 
 /**
  * Collect schema modification commands and pass them to manager to create a schema upgrade script.
@@ -30,7 +30,7 @@
      * @param column Column.
      * @return {@code this} for chaining.
      */
-    TableModificationBuilder addColumn(Column column);
+    TableModificationBuilder addColumn(ColumnDefinition column);
 
     /**
      * Adds new non-affinity key column.
@@ -38,7 +38,7 @@
      * @param column Column.
      * @return {@code this} for chaining.
      */
-    TableModificationBuilder addKeyColumn(Column column);
+    TableModificationBuilder addKeyColumn(ColumnDefinition column);
 
     /**
      * Creates alter column builder..
@@ -61,10 +61,10 @@
     /**
      * Adds new table index.
      *
-     * @param index Table index.
+     * @param indexDefinition Table index.
      * @return {@code this} for chaining.
      */
-    TableModificationBuilder addIndex(TableIndex index);
+    TableModificationBuilder addIndex(IndexDefinition indexDefinition);
 
     /**
      * Drops table index.
diff --git a/modules/api/src/main/java/org/apache/ignite/table/manager/IgniteTables.java b/modules/api/src/main/java/org/apache/ignite/table/manager/IgniteTables.java
index 8ee0e7e..4525f88 100644
--- a/modules/api/src/main/java/org/apache/ignite/table/manager/IgniteTables.java
+++ b/modules/api/src/main/java/org/apache/ignite/table/manager/IgniteTables.java
@@ -21,6 +21,7 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Consumer;
 import org.apache.ignite.configuration.schemas.table.TableChange;
+import org.apache.ignite.lang.TableAlreadyExistsException;
 import org.apache.ignite.table.Table;
 
 /**
@@ -34,18 +35,42 @@
      * @param name Table name.
      * @param tableInitChange Table changer.
      * @return Newly created table.
+     * @throws TableAlreadyExistsException If table with given name already exists.
      */
     Table createTable(String name, Consumer<TableChange> tableInitChange);
 
     /**
-     * Creates a new table with the given {@code name}.
-     * If a table with the same name already exists, an exception will be thrown.
+     * Creates a new table with the given {@code name} asynchronously.
+     * If a table with the same name already exists, a future will be completed with exception.
+     *
+     * @param name Table name.
+     * @param tableInitChange Table changer.
+     * @return Future representing pending completion of the operation.
+     * @see TableAlreadyExistsException
+     */
+    CompletableFuture<Table> createTableAsync(String name, Consumer<TableChange> tableInitChange);
+
+    /**
+     * Creates a new table with the given {@code name} or returns an existing one with the same {@code name}.
+     *
+     * Note: the configuration of the existed table will NOT be validated against the given {@code tableInitChange}.
+     *
+     * @param name Table name.
+     * @param tableInitChange Table changer.
+     * @return Existing or newly created table.
+     */
+    Table createTableIfNotExists(String name, Consumer<TableChange> tableInitChange);
+
+    /**
+     * Creates a new table with the given {@code name} or returns an existing one with the same {@code name}.
+     *
+     * Note: the configuration of the existed table will NOT be validated against the given {@code tableInitChange}.
      *
      * @param name Table name.
      * @param tableInitChange Table changer.
      * @return Future representing pending completion of the operation.
      */
-    CompletableFuture<Table> createTableAsync(String name, Consumer<TableChange> tableInitChange);
+    CompletableFuture<Table> createTableIfNotExistsAsync(String name, Consumer<TableChange> tableInitChange);
 
     /**
      * Alter a cluster table.
@@ -65,24 +90,6 @@
     CompletableFuture<Void> alterTableAsync(String name, Consumer<TableChange> tableChange);
 
     /**
-     * Creates a new table with the given {@code name} or returns an existing one with the same {@code name}.
-     *
-     * @param name Table name.
-     * @param tableInitChange Table changer.
-     * @return Existing or newly created table.
-     */
-    Table getOrCreateTable(String name, Consumer<TableChange> tableInitChange);
-
-    /**
-     * Creates a new table with the given {@code name} or returns an existing one with the same {@code name}.
-     *
-     * @param name Table name.
-     * @param tableInitChange Table changer.
-     * @return Future representing pending completion of the operation.
-     */
-    CompletableFuture<Table> getOrCreateTableAsync(String name, Consumer<TableChange> tableInitChange);
-
-    /**
      * Drops a table with the name specified.
      * If a table with the specified name does not exist in the cluster, the operation has no effect.
      *
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTables.java b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTables.java
index 981bf32..49d2854 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTables.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTables.java
@@ -71,12 +71,12 @@
     }
 
     /** {@inheritDoc} */
-    @Override public Table getOrCreateTable(String name, Consumer<TableChange> tableInitChange) {
-        return getOrCreateTableAsync(name, tableInitChange).join();
+    @Override public Table createTableIfNotExists(String name, Consumer<TableChange> tableInitChange) {
+        return createTableIfNotExistsAsync(name, tableInitChange).join();
     }
 
     /** {@inheritDoc} */
-    @Override public CompletableFuture<Table> getOrCreateTableAsync(String name, Consumer<TableChange> tableInitChange) {
+    @Override public CompletableFuture<Table> createTableIfNotExistsAsync(String name, Consumer<TableChange> tableInitChange) {
         Objects.requireNonNull(name);
         Objects.requireNonNull(tableInitChange);
 
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java b/modules/client/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
index fc48d0c..706852d 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
@@ -49,7 +49,7 @@
 import org.apache.ignite.internal.client.HostAndPortRange;
 import org.apache.ignite.internal.client.TcpIgniteClient;
 import org.apache.ignite.internal.client.query.JdbcClientQueryEventHandler;
-import org.apache.ignite.schema.SchemaTable;
+import org.apache.ignite.schema.definition.TableDefinition;
 import org.jetbrains.annotations.Nullable;
 
 import static java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT;
@@ -124,7 +124,7 @@
 
         holdability = HOLD_CURSORS_OVER_COMMIT;
 
-        schema = SchemaTable.DEFAULT_SCHEMA_NAME;
+        schema = TableDefinition.DEFAULT_DATABASE_SCHEMA_NAME;
 
         client = null;
     }
@@ -760,7 +760,7 @@
      */
     public static String normalizeSchema(String schemaName) {
         if (schemaName == null || schemaName.isEmpty())
-            return SchemaTable.DEFAULT_SCHEMA_NAME;
+            return TableDefinition.DEFAULT_DATABASE_SCHEMA_NAME;
 
         String res;
 
diff --git a/modules/client/src/test/java/org/apache/ignite/client/AbstractClientTableTest.java b/modules/client/src/test/java/org/apache/ignite/client/AbstractClientTableTest.java
index 38fffa5..3b5f1bc 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/AbstractClientTableTest.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/AbstractClientTableTest.java
@@ -70,7 +70,7 @@
     }
 
     protected Table defaultTable() {
-        server.tables().getOrCreateTable(DEFAULT_TABLE, tbl -> tbl.changeReplicas(1));
+        server.tables().createTableIfNotExists(DEFAULT_TABLE, tbl -> tbl.changeReplicas(1));
 
         return client.tables().table(DEFAULT_TABLE);
     }
diff --git a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeIgniteTables.java b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeIgniteTables.java
index f637de9..e48ef8c 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeIgniteTables.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeIgniteTables.java
@@ -77,7 +77,7 @@
     }
 
     /** {@inheritDoc} */
-    @Override public Table getOrCreateTable(String name, Consumer<TableChange> tableInitChange) {
+    @Override public Table createTableIfNotExists(String name, Consumer<TableChange> tableInitChange) {
         var newTable = getNewTable(name);
 
         var oldTable = tables.putIfAbsent(name, newTable);
@@ -91,8 +91,8 @@
     }
 
     /** {@inheritDoc} */
-    @Override public CompletableFuture<Table> getOrCreateTableAsync(String name, Consumer<TableChange> tableInitChange) {
-        return CompletableFuture.completedFuture(getOrCreateTable(name, tableInitChange));
+    @Override public CompletableFuture<Table> createTableIfNotExistsAsync(String name, Consumer<TableChange> tableInitChange) {
+        return CompletableFuture.completedFuture(createTableIfNotExists(name, tableInitChange));
     }
 
     /** {@inheritDoc} */
diff --git a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java
index 1370643..18e5917 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java
@@ -25,7 +25,7 @@
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.table.InternalTable;
 import org.apache.ignite.lang.IgniteUuid;
-import org.apache.ignite.schema.SchemaMode;
+import org.apache.ignite.schema.definition.SchemaManagementMode;
 import org.apache.ignite.tx.Transaction;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -65,12 +65,12 @@
     }
 
     /** {@inheritDoc} */
-    @Override public @NotNull SchemaMode schemaMode() {
-        return SchemaMode.STRICT_SCHEMA;
+    @Override public @NotNull SchemaManagementMode schemaMode() {
+        return SchemaManagementMode.STRICT;
     }
 
     /** {@inheritDoc} */
-    @Override public void schema(SchemaMode schemaMode) {
+    @Override public void schema(SchemaManagementMode schemaMode) {
         // No-op.
     }
 
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/AbstractSchemaChangeTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/AbstractSchemaChangeTest.java
index 3cb5ff6..7698c98 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/AbstractSchemaChangeTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/AbstractSchemaChangeTest.java
@@ -30,10 +30,10 @@
 import org.apache.ignite.internal.testframework.WorkDirectory;
 import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
 import org.apache.ignite.internal.util.IgniteUtils;
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
@@ -199,10 +199,10 @@
      */
     protected void createTable(List<Ignite> nodes) {
         // Create table on node 0.
-        SchemaTable schTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns(
+        TableDefinition schTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns(
             SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(),
             SchemaBuilders.column("valInt", ColumnType.INT32).asNullable().build(),
-            SchemaBuilders.column("valStr", ColumnType.string()).withDefaultValue("default").build()
+            SchemaBuilders.column("valStr", ColumnType.string()).withDefaultValueExpression("default").build()
         ).withPrimaryKey("key").build();
 
         nodes.get(0).tables().createTable(
@@ -215,7 +215,7 @@
      * @param nodes Cluster nodes.
      * @param columnToAdd Column to add.
      */
-    protected void addColumn(List<Ignite> nodes, Column columnToAdd) {
+    protected void addColumn(List<Ignite> nodes, ColumnDefinition columnToAdd) {
         nodes.get(0).tables().alterTable(TABLE,
             chng -> chng.changeColumns(cols -> {
                 int colIdx = chng.columns().namedListKeys().stream().mapToInt(Integer::parseInt).max().getAsInt() + 1;
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITDynamicTableCreationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITDynamicTableCreationTest.java
index 8ca1199..50d60d7 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITDynamicTableCreationTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITDynamicTableCreationTest.java
@@ -30,9 +30,9 @@
 import org.apache.ignite.internal.testframework.WorkDirectory;
 import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
 import org.apache.ignite.internal.util.IgniteUtils;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
 import org.apache.ignite.table.KeyValueBinaryView;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.table.Tuple;
@@ -107,7 +107,7 @@
         assertEquals(3, clusterNodes.size());
 
         // Create table on node 0.
-        SchemaTable schTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns(
+        TableDefinition schTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns(
             SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(),
             SchemaBuilders.column("val", ColumnType.INT32).asNullable().build()
         ).withPrimaryKey("key").build();
@@ -158,16 +158,15 @@
         assertEquals(3, clusterNodes.size());
 
         // Create table on node 0.
-        SchemaTable scmTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns(
+        TableDefinition scmTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns(
             SchemaBuilders.column("key", ColumnType.UUID).asNonNull().build(),
             SchemaBuilders.column("affKey", ColumnType.INT64).asNonNull().build(),
             SchemaBuilders.column("valStr", ColumnType.string()).asNullable().build(),
             SchemaBuilders.column("valInt", ColumnType.INT32).asNullable().build(),
             SchemaBuilders.column("valNull", ColumnType.INT16).asNullable().build()
-        ).withIndex(
-            SchemaBuilders.pkIndex()
-                .addIndexColumn("key").done()
-                .addIndexColumn("affKey").done()
+        ).withPrimaryKey(
+            SchemaBuilders.primaryKey()
+                .withColumns("key", "affKey")
                 .withAffinityColumns("affKey")
                 .build()
         ).build();
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITIgniteNodeRestartTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITIgniteNodeRestartTest.java
index 12b1a19..eb375a5 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITIgniteNodeRestartTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITIgniteNodeRestartTest.java
@@ -23,9 +23,9 @@
 import org.apache.ignite.internal.app.IgniteImpl;
 import org.apache.ignite.internal.schema.configuration.SchemaConfigurationConverter;
 import org.apache.ignite.internal.testframework.IgniteAbstractTest;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.table.Tuple;
 import org.junit.jupiter.api.Disabled;
@@ -159,16 +159,16 @@
             "  }\n" +
             "}", workDir.resolve(NODE_NAME));
 
-        SchemaTable scmTbl1 = SchemaBuilders.tableBuilder("PUBLIC", TABLE_NAME).columns(
+        TableDefinition scmTbl1 = SchemaBuilders.tableBuilder("PUBLIC", TABLE_NAME).columns(
             SchemaBuilders.column("id", ColumnType.INT32).asNonNull().build(),
             SchemaBuilders.column("name", ColumnType.string()).asNullable().build()
-        ).withIndex(
-            SchemaBuilders.pkIndex()
-                .addIndexColumn("id").done()
+        ).withPrimaryKey(
+            SchemaBuilders.primaryKey()
+                .withColumns("id")
                 .build()
         ).build();
 
-        Table table = ignite.tables().getOrCreateTable(
+        Table table = ignite.tables().createTableIfNotExists(
             scmTbl1.canonicalName(), tbl -> SchemaConfigurationConverter.convert(scmTbl1, tbl).changePartitions(10));
 
         for (int i = 0; i < 100; i++) {
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITLiveSchemaChangeKVViewTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITLiveSchemaChangeKVViewTest.java
index 0ca0573..edcd8e5 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITLiveSchemaChangeKVViewTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITLiveSchemaChangeKVViewTest.java
@@ -22,7 +22,7 @@
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.SchemaMismatchException;
 import org.apache.ignite.internal.table.TableImpl;
-import org.apache.ignite.schema.SchemaMode;
+import org.apache.ignite.schema.definition.SchemaManagementMode;
 import org.apache.ignite.table.KeyValueBinaryView;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.table.Tuple;
@@ -61,7 +61,7 @@
 
         Table tbl = grid.get(1).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         KeyValueBinaryView kvBinaryView = tbl.kvView();
 
@@ -86,7 +86,7 @@
 
         Table tbl = grid.get(0).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         KeyValueBinaryView kvBinaryView = tbl.kvView();
 
@@ -99,7 +99,7 @@
         assertEquals("111", res.value("valStrNew"));
         assertEquals(Integer.valueOf(333), res.value("valIntNew"));
 
-        ((TableImpl)tbl).schemaType(SchemaMode.STRICT_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.STRICT);
 
         Tuple anotherKey = Tuple.create().set("key", 2L);
         Tuple anotherVal = Tuple.create().set("valStrNew", "111").set("valIntNew", 333);
@@ -125,7 +125,7 @@
 
         Table tbl = grid.get(1).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         KeyValueBinaryView view = tbl.kvView();
 
@@ -155,7 +155,7 @@
 
         Table tbl = grid.get(1).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         KeyValueBinaryView view = tbl.kvView();
 
@@ -187,7 +187,7 @@
 
         Table tbl = grid.get(0).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         KeyValueBinaryView view = tbl.kvView();
 
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITLiveSchemaChangeTableTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITLiveSchemaChangeTableTest.java
index 8df0b9e..d80703c 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITLiveSchemaChangeTableTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITLiveSchemaChangeTableTest.java
@@ -24,7 +24,7 @@
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.SchemaMismatchException;
 import org.apache.ignite.internal.table.TableImpl;
-import org.apache.ignite.schema.SchemaMode;
+import org.apache.ignite.schema.definition.SchemaManagementMode;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.table.Tuple;
 import org.junit.jupiter.api.Test;
@@ -63,7 +63,7 @@
 
         Table tbl = grid.get(0).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         Tuple row = Tuple.create().set("key", 1L).set("valStrNew", "111").set("valIntNew", 333);
 
@@ -90,7 +90,7 @@
 
         tbl.insert(oldSchemaTuple);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         Tuple upsertOldSchemaTuple = Tuple.create().set("key", 32L).set("valStrNew", "111").set("valIntNew", 333);
 
@@ -115,7 +115,7 @@
 
         Tuple oldSchemaTuple = Tuple.create().set("key", 32L).set("valInt", 111).set("valStr", "str");
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         Tuple row = Tuple.create().set("key", 1L).set("valStrNew", "111").set("valIntNew", 333);
 
@@ -144,7 +144,7 @@
 
         Table tbl = grid.get(0).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         Tuple val = Tuple.create().set("key", 1L).set("valStrNew", "111").set("valIntNew", 333);
 
@@ -154,7 +154,7 @@
         assertEquals("111", res.value("valStrNew"));
         assertEquals(Integer.valueOf(333), res.value("valIntNew"));
 
-        ((TableImpl)tbl).schemaType(SchemaMode.STRICT_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.STRICT);
 
         Tuple anotherKey = Tuple.create().set("key", 2L).set("valStrNew", "111").set("valIntNew", 333);
 
@@ -179,7 +179,7 @@
 
         Table tbl = grid.get(0).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         Tuple oldSchemaVal = Tuple.create().set("key", 32L).set("valInt", 111).set("valStr", "str");
         Tuple upsertOldSchemaVal = Tuple.create().set("key", 32L).set("valStrNew", "111").set("valIntNew", 333);
@@ -207,7 +207,7 @@
 
         Table tbl = grid.get(0).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         UUID uuid = UUID.randomUUID();
 
@@ -263,7 +263,7 @@
 
         Table tbl = grid.get(0).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         UUID uuid = UUID.randomUUID();
 
@@ -296,7 +296,7 @@
 
         Table tbl = grid.get(0).tables().table(TABLE);
 
-        ((TableImpl)tbl).schemaType(SchemaMode.LIVE_SCHEMA);
+        ((TableImpl)tbl).schemaType(SchemaManagementMode.LIVE);
 
         Tuple rowWithObject = Tuple.create().set("key", 1L).set("newBrokenColumn", new Object());
 
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITSchemaChangeKVViewTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITSchemaChangeKVViewTest.java
index 4f6ffa4..94f673b 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITSchemaChangeKVViewTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITSchemaChangeKVViewTest.java
@@ -22,9 +22,9 @@
 import java.util.function.Supplier;
 import org.apache.ignite.app.Ignite;
 import org.apache.ignite.internal.schema.SchemaMismatchException;
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.ColumnType;
 import org.apache.ignite.table.KeyValueBinaryView;
 import org.apache.ignite.table.Tuple;
 import org.junit.jupiter.api.Test;
@@ -101,7 +101,7 @@
             );
         }
 
-        addColumn(grid, SchemaBuilders.column("valStrNew", ColumnType.string()).asNullable().withDefaultValue("default").build());
+        addColumn(grid, SchemaBuilders.column("valStrNew", ColumnType.string()).asNullable().withDefaultValueExpression("default").build());
 
         {
             // Check old row conversion.
@@ -181,7 +181,7 @@
 
         createTable(grid);
 
-        final Column column = SchemaBuilders.column("val", ColumnType.string()).asNullable().withDefaultValue("default").build();
+        final ColumnDefinition column = SchemaBuilders.column("val", ColumnType.string()).asNullable().withDefaultValueExpression("default").build();
 
         KeyValueBinaryView kvView = grid.get(0).tables().table(TABLE).kvView();
 
@@ -219,7 +219,7 @@
             );
         }
 
-        addColumn(grid, SchemaBuilders.column("val", ColumnType.string()).asNullable().withDefaultValue("default").build());
+        addColumn(grid, SchemaBuilders.column("val", ColumnType.string()).asNullable().withDefaultValueExpression("default").build());
 
         {
             kvView.put(Tuple.create().set("key", 5L), Tuple.create().set("valInt", 555));
@@ -271,7 +271,7 @@
         }
 
         changeDefault(grid, colName, (Supplier<Object> & Serializable)() -> "newDefault");
-        addColumn(grid, SchemaBuilders.column("val", ColumnType.string()).withDefaultValue("newDefault").build());
+        addColumn(grid, SchemaBuilders.column("val", ColumnType.string()).withDefaultValueExpression("newDefault").build());
 
         {
             kvView.put(Tuple.create().set("key", 2L), Tuple.create().set("valInt", 222));
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITSchemaChangeTableViewTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITSchemaChangeTableViewTest.java
index 7ee8e28..f823abf 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITSchemaChangeTableViewTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITSchemaChangeTableViewTest.java
@@ -22,9 +22,9 @@
 import java.util.function.Supplier;
 import org.apache.ignite.app.Ignite;
 import org.apache.ignite.internal.schema.SchemaMismatchException;
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.ColumnType;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.table.Tuple;
 import org.junit.jupiter.api.Test;
@@ -97,7 +97,7 @@
             );
         }
 
-        addColumn(grid, SchemaBuilders.column("valStrNew", ColumnType.string()).asNullable().withDefaultValue("default").build());
+        addColumn(grid, SchemaBuilders.column("valStrNew", ColumnType.string()).asNullable().withDefaultValueExpression("default").build());
 
         // Check old row conversion.
         Tuple keyTuple1 = Tuple.create().set("key", 1L);
@@ -181,7 +181,7 @@
         }
 
         renameColumn(grid, "valInt", "val2");
-        addColumn(grid, SchemaBuilders.column("valInt", ColumnType.INT32).asNullable().withDefaultValue(-1).build());
+        addColumn(grid, SchemaBuilders.column("valInt", ColumnType.INT32).asNullable().withDefaultValueExpression(-1).build());
 
         {
             // Check old row conversion.
@@ -214,7 +214,7 @@
 
         createTable(grid);
 
-        final Column column = SchemaBuilders.column("val", ColumnType.string()).asNullable().withDefaultValue("default").build();
+        final ColumnDefinition column = SchemaBuilders.column("val", ColumnType.string()).asNullable().withDefaultValueExpression("default").build();
 
         Table tbl = grid.get(0).tables().table(TABLE);
 
@@ -246,7 +246,7 @@
             );
         }
 
-        addColumn(grid, SchemaBuilders.column("val", ColumnType.string()).withDefaultValue("default").build());
+        addColumn(grid, SchemaBuilders.column("val", ColumnType.string()).withDefaultValueExpression("default").build());
 
         {
             tbl.insert(Tuple.create().set("key", 5L).set("valInt", 555));
@@ -297,7 +297,7 @@
         }
 
         changeDefault(grid, colName, (Supplier<Object> & Serializable)() -> "newDefault");
-        addColumn(grid, SchemaBuilders.column("val", ColumnType.string()).withDefaultValue("newDefault").build());
+        addColumn(grid, SchemaBuilders.column("val", ColumnType.string()).withDefaultValueExpression("newDefault").build());
 
         {
             tbl.insert(Tuple.create().set("key", 2L).set("valInt", 222));
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITThinClientConnectionTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITThinClientConnectionTest.java
index afd3ec9..ff92c7b 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITThinClientConnectionTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ITThinClientConnectionTest.java
@@ -31,9 +31,9 @@
 import org.apache.ignite.internal.testframework.IgniteAbstractTest;
 import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
 import org.apache.ignite.internal.util.IgniteUtils;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.table.Tuple;
 import org.junit.jupiter.api.AfterEach;
@@ -98,7 +98,7 @@
         var keyCol = "key";
         var valCol = "val";
 
-        SchemaTable schTbl = SchemaBuilders.tableBuilder(SCHEMA_NAME, TABLE_NAME).columns(
+        TableDefinition schTbl = SchemaBuilders.tableBuilder(SCHEMA_NAME, TABLE_NAME).columns(
                 SchemaBuilders.column(keyCol, ColumnType.INT32).asNonNull().build(),
                 SchemaBuilders.column(valCol, ColumnType.string()).asNullable().build()
         ).withPrimaryKey(keyCol).build();
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/PlatformTestNodeRunner.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/PlatformTestNodeRunner.java
index 19554e3..8c76ec1 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/PlatformTestNodeRunner.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/PlatformTestNodeRunner.java
@@ -30,9 +30,9 @@
 import org.apache.ignite.internal.app.IgniteImpl;
 import org.apache.ignite.internal.schema.configuration.SchemaConfigurationConverter;
 import org.apache.ignite.internal.util.IgniteUtils;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
 
 /**
  * Helper class for non-Java platform tests (.NET, C++, Python, ...).
@@ -79,7 +79,7 @@
         var keyCol = "key";
         var valCol = "val";
 
-        SchemaTable schTbl = SchemaBuilders.tableBuilder(SCHEMA_NAME, TABLE_NAME).columns(
+        TableDefinition schTbl = SchemaBuilders.tableBuilder(SCHEMA_NAME, TABLE_NAME).columns(
                 SchemaBuilders.column(keyCol, ColumnType.INT32).asNonNull().build(),
                 SchemaBuilders.column(valCol, ColumnType.string()).asNullable().build()
         ).withPrimaryKey(keyCol).build();
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/jdbc/ITJdbcMetadataSelfTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/jdbc/ITJdbcMetadataSelfTest.java
index 395cf26..ef27ca9 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/jdbc/ITJdbcMetadataSelfTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/jdbc/ITJdbcMetadataSelfTest.java
@@ -34,9 +34,9 @@
 import java.util.Set;
 import org.apache.ignite.internal.client.proto.ProtocolVersion;
 import org.apache.ignite.internal.schema.configuration.SchemaConfigurationConverter;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.table.Tuple;
 import org.junit.jupiter.api.BeforeAll;
@@ -65,13 +65,13 @@
     public static void createTables() {
         assert !clusterNodes.isEmpty();
 
-        SchemaTable perTbl = SchemaBuilders.tableBuilder("PUBLIC", "PERSON").columns(
+        TableDefinition perTbl = SchemaBuilders.tableBuilder("PUBLIC", "PERSON").columns(
             SchemaBuilders.column("NAME", ColumnType.string()).asNullable().build(),
             SchemaBuilders.column("AGE", ColumnType.INT32).asNullable().build(),
             SchemaBuilders.column("ORGID", ColumnType.INT32).asNonNull().build()
         ).withPrimaryKey("ORGID").build();
 
-        SchemaTable orgTbl = SchemaBuilders.tableBuilder("PUBLIC", "ORGANIZATION").columns(
+        TableDefinition orgTbl = SchemaBuilders.tableBuilder("PUBLIC", "ORGANIZATION").columns(
             SchemaBuilders.column("ID", ColumnType.INT32).asNonNull().build(),
             SchemaBuilders.column("NAME", ColumnType.string()).asNullable().build(),
             SchemaBuilders.column("BIGDATA", ColumnType.decimalOf(20, 10)).asNullable().build()
@@ -575,13 +575,10 @@
      * @throws SQLException on error.
      */
     private static void assertIsEmpty(ResultSet rs) throws SQLException {
-        try {
+        try (rs) {
             boolean empty = !rs.next();
 
             assertTrue(empty, "Result should be empty because invalid catalog is specified.");
         }
-        finally {
-            rs.close();
-        }
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java
index 508be27..9a2f8a2 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java
@@ -20,7 +20,7 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.BitSet;
-import org.apache.ignite.schema.ColumnType;
+import org.apache.ignite.schema.definition.ColumnType;
 
 /**
  * A thin wrapper over {@link NativeTypeSpec} to instantiate parameterized constrained types.
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/PrimaryIndexImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/PrimaryIndexImpl.java
deleted file mode 100644
index f433531..0000000
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/PrimaryIndexImpl.java
+++ /dev/null
@@ -1,69 +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.Collections;
-import java.util.List;
-import org.apache.ignite.internal.tostring.IgniteToStringInclude;
-import org.apache.ignite.internal.tostring.S;
-import org.apache.ignite.schema.PrimaryIndex;
-import org.apache.ignite.schema.SortedIndexColumn;
-
-/**
- * Primary key index.
- */
-public class PrimaryIndexImpl extends SortedIndexImpl implements PrimaryIndex {
-    /** Affinity columns. */
-    @IgniteToStringInclude
-    private final List<String> affCols;
-
-    /**
-     * Constructor.
-     *
-     * @param cols Index columns.
-     * @param affCols Affinity columns.
-     */
-    public PrimaryIndexImpl(List<SortedIndexColumn> cols, List<String> affCols) {
-        super(PrimaryIndex.PRIMARY_KEY_INDEX_NAME, cols, true);
-        this.affCols = Collections.unmodifiableList(affCols);
-    }
-
-    /** {@inheritDoc} */
-    @Override public List<String> affinityColumns() {
-        return affCols;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String type() {
-        return "PK";
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean unique() {
-        return true;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(PrimaryIndexImpl.class, this,
-            "type", type(),
-            "name", name(),
-            "uniq", unique(),
-            "cols", columns());
-    }
-}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaTableImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaTableImpl.java
deleted file mode 100644
index 97589ff..0000000
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaTableImpl.java
+++ /dev/null
@@ -1,140 +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.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.apache.ignite.internal.schema.modification.TableModificationBuilderImpl;
-import org.apache.ignite.internal.tostring.S;
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.IndexColumn;
-import org.apache.ignite.schema.PrimaryIndex;
-import org.apache.ignite.schema.SchemaTable;
-import org.apache.ignite.schema.TableIndex;
-import org.apache.ignite.schema.modification.TableModificationBuilder;
-
-/**
- * Table.
- */
-@SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
-public class SchemaTableImpl extends AbstractSchemaObject implements SchemaTable {
-    /** Schema name. */
-    private final String schemaName;
-
-    /** Key columns. */
-    private final LinkedHashMap<String, Column> cols;
-
-    /** Indices. */
-    private final Map<String, TableIndex> indices;
-
-    /** Cached key columns. */
-    private final List<Column> keyCols;
-
-    /** Cached key affinity columns. */
-    private final List<Column> affCols;
-
-    /** Cached value columns. */
-    private final List<Column> valCols;
-
-    /**
-     * Constructor.
-     *
-     * @param schemaName Schema name.
-     * @param tableName Table name.
-     * @param cols Columns.
-     * @param indices Indices.
-     */
-    public SchemaTableImpl(
-        String schemaName,
-        String tableName,
-        final LinkedHashMap<String, Column> cols,
-        final Map<String, TableIndex> indices
-    ) {
-        super(tableName);
-
-        this.schemaName = schemaName;
-        this.cols = cols;
-        this.indices = indices;
-
-        final PrimaryIndex pkIndex = (PrimaryIndex)indices.get(PrimaryIndex.PRIMARY_KEY_INDEX_NAME);
-        final Set<String> pkColNames = pkIndex.columns().stream().map(IndexColumn::name).collect(Collectors.toSet());
-
-        assert pkIndex != null;
-
-        keyCols = pkIndex.columns().stream().map(c -> cols.get(c.name())).collect(Collectors.toUnmodifiableList());
-        affCols = pkIndex.affinityColumns().stream().map(cols::get).collect(Collectors.toUnmodifiableList());
-        valCols = cols.values().stream().filter(c -> !pkColNames.contains(c.name())).collect(Collectors.toUnmodifiableList());
-
-    }
-
-    /** {@inheritDoc} */
-    @Override public Collection<Column> keyColumns() {
-        return keyCols;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Collection<Column> affinityColumns() {
-        return affCols;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Collection<Column> valueColumns() {
-        return valCols;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String canonicalName() {
-        return schemaName + '.' + name();
-    }
-
-    /** {@inheritDoc} */
-    @Override public Collection<TableIndex> indices() {
-        return Collections.unmodifiableCollection(indices.values());
-    }
-
-    /** {@inheritDoc} */
-    @Override public TableModificationBuilder toBuilder() {
-        return new TableModificationBuilderImpl(this);
-    }
-
-    /**
-     * @param name Column name.
-     * @return {@code True} if column with given name already exists, {@code false} otherwise.
-     */
-    public boolean hasColumn(String name) {
-        return cols.containsKey(name);
-    }
-
-    /**
-     * @param name Column name.
-     * @return {@code True} if key column with given name already exists, {@code false} otherwise.
-     */
-    public boolean hasKeyColumn(String name) {
-        return keyCols.stream().anyMatch(c -> c.name().equals(name));
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(SchemaTableImpl.class, this);
-    }
-}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaUtils.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaUtils.java
index 7d1e35d..9572062 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaUtils.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/SchemaUtils.java
@@ -25,7 +25,7 @@
 import org.apache.ignite.internal.schema.mapping.ColumnMapper;
 import org.apache.ignite.internal.schema.mapping.ColumnMapping;
 import org.apache.ignite.lang.LoggerMessageHelper;
-import org.apache.ignite.schema.SchemaTable;
+import org.apache.ignite.schema.definition.TableDefinition;
 
 /**
  * Stateless schema utils that produces helper methods for schema preparation.
@@ -39,9 +39,9 @@
      * @return Schema descriptor.
      */
     public static SchemaDescriptor prepareSchemaDescriptor(int schemaVer, TableView tblCfg) {
-        SchemaTable schemaTbl = SchemaConfigurationConverter.convert(tblCfg);
+        TableDefinition tableDef = SchemaConfigurationConverter.convert(tblCfg);
 
-        return SchemaDescriptorConverter.convert(schemaVer, schemaTbl);
+        return SchemaDescriptorConverter.convert(schemaVer, tableDef);
     }
 
     /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/PrimaryKeyBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/PrimaryKeyBuilderImpl.java
deleted file mode 100644
index be1783d..0000000
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/PrimaryKeyBuilderImpl.java
+++ /dev/null
@@ -1,119 +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.builder;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import org.apache.ignite.internal.schema.PrimaryIndexImpl;
-import org.apache.ignite.schema.PrimaryIndex;
-import org.apache.ignite.schema.SortedIndexColumn;
-import org.apache.ignite.schema.builder.PrimaryIndexBuilder;
-
-import static org.apache.ignite.schema.PrimaryIndex.PRIMARY_KEY_INDEX_NAME;
-
-/**
- * Primary index builder.
- */
-public class PrimaryKeyBuilderImpl extends SortedIndexBuilderImpl implements PrimaryIndexBuilder {
-    /** */
-    private List<String> affCols;
-
-    /**
-     * Constructor.
-     */
-    public PrimaryKeyBuilderImpl() {
-        super(PRIMARY_KEY_INDEX_NAME);
-
-        super.unique();
-    }
-
-    /** {@inheritDoc} */
-    @Override public PrimaryKeyBuilderImpl withHints(Map<String, String> hints) {
-        super.withHints(hints);
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public PrimaryKeyBuilderImpl unique() {
-        return this; // Nothing to do.
-    }
-
-    @Override public PkIndexColumnBuilderImpl addIndexColumn(String name) {
-        return new PkIndexColumnBuilderImpl(this).withName(name);
-    }
-
-    /** {@inheritDoc} */
-    @Override public PrimaryKeyBuilderImpl withAffinityColumns(String... affCols) {
-        this.affCols = Arrays.asList(affCols);
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public PrimaryIndex build() {
-        if (affCols == null)
-            affCols = columns().stream().map(SortedIndexColumn::name).collect(Collectors.toList());
-        else
-            assert affCols.stream().allMatch(cols::containsKey) : "Affinity column should be a valid PK index column.";
-
-        return new PrimaryIndexImpl(columns(), affCols);
-    }
-
-    /**
-     * Index column builder.
-     */
-    private static class PkIndexColumnBuilderImpl extends SortedIndexColumnBuilderImpl implements PrimaryIndexColumnBuilder {
-        /**
-         * Constructor.
-         *
-         * @param parent Parent builder.
-         */
-        PkIndexColumnBuilderImpl(PrimaryKeyBuilderImpl parent) {
-            super(parent);
-        }
-
-        /** {@inheritDoc} */
-        @Override public PkIndexColumnBuilderImpl withName(String name) {
-            super.withName(name);
-
-            return this;
-        }
-
-        /** {@inheritDoc} */
-        @Override public PkIndexColumnBuilderImpl desc() {
-            super.desc();
-
-            return this;
-        }
-
-        /** {@inheritDoc} */
-        @Override public PkIndexColumnBuilderImpl asc() {
-            super.asc();
-
-            return this;
-        }
-
-        /** {@inheritDoc} */
-        @Override public PrimaryKeyBuilderImpl done() {
-            return (PrimaryKeyBuilderImpl)super.done();
-        }
-    }
-}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/SchemaTableBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/SchemaTableBuilderImpl.java
deleted file mode 100644
index ae42c64..0000000
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/SchemaTableBuilderImpl.java
+++ /dev/null
@@ -1,146 +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.builder;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.apache.ignite.internal.schema.SchemaTableImpl;
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.ColumnarIndex;
-import org.apache.ignite.schema.IndexColumn;
-import org.apache.ignite.schema.PrimaryIndex;
-import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
-import org.apache.ignite.schema.SortedIndex;
-import org.apache.ignite.schema.TableIndex;
-import org.apache.ignite.schema.builder.SchemaTableBuilder;
-
-import static org.apache.ignite.schema.PrimaryIndex.PRIMARY_KEY_INDEX_NAME;
-
-/**
- * Table builder.
- */
-public class SchemaTableBuilderImpl implements SchemaTableBuilder {
-    /** Schema name. */
-    private final String schemaName;
-
-    /** Table name. */
-    private final String tableName;
-
-    /** Columns. */
-    private final LinkedHashMap<String, Column> columns = new LinkedHashMap<>();
-
-    /** Indices. */
-    private final Map<String, TableIndex> indices = new HashMap<>();
-
-    /**
-     * Constructor.
-     *
-     * @param schemaName Schema name.
-     * @param tableName Table name.
-     */
-    public SchemaTableBuilderImpl(String schemaName, String tableName) {
-        this.schemaName = schemaName;
-        this.tableName = tableName;
-    }
-
-    /** {@inheritDoc} */
-    @Override public SchemaTableBuilderImpl columns(Column... columns) {
-        for (int i = 0; i < columns.length; i++) {
-            if (this.columns.put(columns[i].name(), columns[i]) != null)
-                throw new IllegalArgumentException("Column with same name already exists: columnName=" + columns[i].name());
-        }
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public SchemaTableBuilder withIndex(TableIndex index) {
-        if (index instanceof PrimaryIndex) {
-            if (!PRIMARY_KEY_INDEX_NAME.equals(index.name()))
-                throw new IllegalArgumentException("Not valid index name for a primary index: " + index.name());
-        }
-        else if (PRIMARY_KEY_INDEX_NAME.equals(index.name()))
-            throw new IllegalArgumentException("Not valid index name for a secondary index: " + index.name());
-
-        if (indices.put(index.name(), index) != null)
-            throw new IllegalArgumentException("Index with same name already exists: " + index.name());
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public SchemaTableBuilder withPrimaryKey(String colName) {
-        withIndex(SchemaBuilders.pkIndex().addIndexColumn(colName).done().withAffinityColumns(colName).build());
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public SchemaTableBuilder withHints(Map<String, String> hints) {
-        // No op.
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public SchemaTable build() {
-        assert schemaName != null : "Table name was not specified.";
-
-        validateIndices(indices.values(), columns.values());
-
-        assert columns.size() > ((SortedIndex)indices.get(PRIMARY_KEY_INDEX_NAME)).columns().size() : "Key or/and value columns was not defined.";
-
-        return new SchemaTableImpl(
-            schemaName,
-            tableName,
-            columns,
-            Collections.unmodifiableMap(indices)
-        );
-    }
-
-    /**
-     * Validate indices.
-     *
-     * @param indices Table indices.
-     * @param columns Table columns.
-     */
-    public static void validateIndices(Collection<TableIndex> indices, Collection<Column> columns) {
-        Set<String> colNames = columns.stream().map(Column::name).collect(Collectors.toSet());
-
-        assert indices.stream()
-            .filter(ColumnarIndex.class::isInstance)
-            .map(ColumnarIndex.class::cast)
-            .flatMap(idx -> idx.columns().stream())
-            .map(IndexColumn::name)
-            .allMatch(colNames::contains) : "Index column doesn't exists in schema.";
-
-        TableIndex pkIdx = indices.stream().filter(idx -> PRIMARY_KEY_INDEX_NAME.equals(idx.name())).findAny().orElse(null);
-
-        assert pkIdx != null : "Primary key index is not configured.";
-        assert !((PrimaryIndex)pkIdx).affinityColumns().isEmpty() : "Primary key must have one affinity column at least.";
-
-        // Note: E.g. functional index is not columnar index as it index an expression result only.
-        assert indices.stream().allMatch(ColumnarIndex.class::isInstance) : "Columnar indices are supported only.";
-    }
-}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/TableColumnBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/TableColumnBuilderImpl.java
deleted file mode 100644
index 130f3d3..0000000
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/TableColumnBuilderImpl.java
+++ /dev/null
@@ -1,84 +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.builder;
-
-import java.util.Map;
-import org.apache.ignite.internal.schema.ColumnImpl;
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.ColumnType;
-import org.apache.ignite.schema.builder.TableColumnBuilder;
-
-/**
- * Column builder.
- */
-public class TableColumnBuilderImpl implements TableColumnBuilder {
-    /** Column name. */
-    private final String colName;
-
-    /** Column type. */
-    private final ColumnType colType;
-
-    /** Nullable flag. */
-    private boolean nullable;
-
-    /** Default value. */
-    private Object defValue;
-
-    /**
-     * Constructor.
-     * @param colName Column name.
-     * @param colType Column type.
-     */
-    public TableColumnBuilderImpl(String colName, ColumnType colType) {
-        this.colName = colName;
-        this.colType = colType;
-    }
-
-    /** {@inheritDoc} */
-    @Override public TableColumnBuilderImpl asNullable() {
-        nullable = true;
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public TableColumnBuilderImpl asNonNull() {
-        nullable = false;
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public TableColumnBuilderImpl withDefaultValue(Object defValue) {
-        this.defValue = defValue;
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public TableColumnBuilderImpl withHints(Map<String, String> hints) {
-        // No op.
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Column build() {
-        return new ColumnImpl(colName, colType, nullable, defValue);
-    }
-}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverter.java
index 134e0a2..496202c 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverter.java
@@ -26,8 +26,8 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.UUID;
@@ -38,30 +38,31 @@
 import org.apache.ignite.configuration.schemas.table.ColumnView;
 import org.apache.ignite.configuration.schemas.table.IndexColumnChange;
 import org.apache.ignite.configuration.schemas.table.IndexColumnView;
+import org.apache.ignite.configuration.schemas.table.PrimaryKeyView;
 import org.apache.ignite.configuration.schemas.table.TableChange;
 import org.apache.ignite.configuration.schemas.table.TableConfiguration;
 import org.apache.ignite.configuration.schemas.table.TableIndexChange;
 import org.apache.ignite.configuration.schemas.table.TableIndexView;
 import org.apache.ignite.configuration.schemas.table.TableView;
 import org.apache.ignite.configuration.schemas.table.TablesChange;
-import org.apache.ignite.internal.schema.ColumnImpl;
-import org.apache.ignite.internal.schema.HashIndexImpl;
-import org.apache.ignite.internal.schema.PartialIndexImpl;
-import org.apache.ignite.internal.schema.PrimaryIndexImpl;
-import org.apache.ignite.internal.schema.SchemaTableImpl;
-import org.apache.ignite.internal.schema.SortedIndexColumnImpl;
-import org.apache.ignite.internal.schema.SortedIndexImpl;
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.ColumnType;
-import org.apache.ignite.schema.HashIndex;
-import org.apache.ignite.schema.IndexColumn;
-import org.apache.ignite.schema.PartialIndex;
-import org.apache.ignite.schema.PrimaryIndex;
-import org.apache.ignite.schema.SchemaTable;
-import org.apache.ignite.schema.SortOrder;
-import org.apache.ignite.schema.SortedIndex;
-import org.apache.ignite.schema.SortedIndexColumn;
-import org.apache.ignite.schema.TableIndex;
+import org.apache.ignite.internal.schema.definition.ColumnDefinitionImpl;
+import org.apache.ignite.internal.schema.definition.TableDefinitionImpl;
+import org.apache.ignite.internal.schema.definition.index.HashIndexDefinitionImpl;
+import org.apache.ignite.internal.schema.definition.index.PartialIndexDefinitionImpl;
+import org.apache.ignite.internal.schema.definition.index.PrimaryKeyDefinitionImpl;
+import org.apache.ignite.internal.schema.definition.index.SortedIndexColumnDefinitionImpl;
+import org.apache.ignite.internal.schema.definition.index.SortedIndexDefinitionImpl;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.PrimaryKeyDefinition;
+import org.apache.ignite.schema.definition.TableDefinition;
+import org.apache.ignite.schema.definition.index.HashIndexDefinition;
+import org.apache.ignite.schema.definition.index.IndexColumnDefinition;
+import org.apache.ignite.schema.definition.index.IndexDefinition;
+import org.apache.ignite.schema.definition.index.PartialIndexDefinition;
+import org.apache.ignite.schema.definition.index.SortOrder;
+import org.apache.ignite.schema.definition.index.SortedIndexColumnDefinition;
+import org.apache.ignite.schema.definition.index.SortedIndexDefinition;
 
 /**
  * Configuration to schema and vice versa converter.
@@ -76,9 +77,6 @@
     /** Partial index type. */
     private static final String PARTIAL_TYPE = "PARTIAL";
 
-    /** Primary key index type. */
-    private static final String PK_TYPE = "PK";
-
     /** Types map. */
     private static final Map<String, ColumnType> types = new HashMap<>();
 
@@ -111,7 +109,7 @@
      * @param colInit IndexColumnChange to fulfill.
      * @return IndexColumnChange to get result from.
      */
-    public static IndexColumnChange convert(SortedIndexColumn col, IndexColumnChange colInit) {
+    public static IndexColumnChange convert(SortedIndexColumnDefinition col, IndexColumnChange colInit) {
         colInit.changeName(col.name());
 
         colInit.changeAsc(col.sortOrder() == SortOrder.ASC);
@@ -125,8 +123,8 @@
      * @param colCfg IndexColumnView.
      * @return SortedIndexColumn.
      */
-    public static SortedIndexColumn convert(IndexColumnView colCfg) {
-        return new SortedIndexColumnImpl(colCfg.name(), colCfg.asc() ? SortOrder.ASC : SortOrder.DESC);
+    public static SortedIndexColumnDefinition convert(IndexColumnView colCfg) {
+        return new SortedIndexColumnDefinitionImpl(colCfg.name(), colCfg.asc() ? SortOrder.ASC : SortOrder.DESC);
     }
 
     /**
@@ -136,22 +134,22 @@
      * @param idxChg TableIndexChange to fulfill.
      * @return TableIndexChange to get result from.
      */
-    public static TableIndexChange convert(TableIndex idx, TableIndexChange idxChg) {
+    public static TableIndexChange convert(IndexDefinition idx, TableIndexChange idxChg) {
         idxChg.changeName(idx.name());
         idxChg.changeType(idx.type());
 
         switch (idx.type().toUpperCase()) {
             case HASH_TYPE:
-                HashIndex hashIdx = (HashIndex)idx;
+                HashIndexDefinition hashIdx = (HashIndexDefinition)idx;
 
-                String[] colNames = hashIdx.columns().stream().map(IndexColumn::name).toArray(String[]::new);
+                String[] colNames = hashIdx.columns().stream().map(IndexColumnDefinition::name).toArray(String[]::new);
 
                 idxChg.changeColNames(colNames);
 
                 break;
 
             case PARTIAL_TYPE:
-                PartialIndex partIdx = (PartialIndex)idx;
+                PartialIndexDefinition partIdx = (PartialIndexDefinition)idx;
 
                 idxChg.changeUniq(partIdx.unique());
                 idxChg.changeExpr(partIdx.expr());
@@ -159,40 +157,25 @@
                 idxChg.changeColumns(colsChg -> {
                     int colIdx = 0;
 
-                    for (SortedIndexColumn col : partIdx.columns())
+                    for (SortedIndexColumnDefinition col : partIdx.columns())
                         colsChg.create(String.valueOf(colIdx++), colInit -> convert(col, colInit));
                 });
 
                 break;
 
             case SORTED_TYPE:
-                SortedIndex sortIdx = (SortedIndex)idx;
+                SortedIndexDefinition sortIdx = (SortedIndexDefinition)idx;
                 idxChg.changeUniq(sortIdx.unique());
 
                 idxChg.changeColumns(colsInit -> {
                     int colIdx = 0;
 
-                    for (SortedIndexColumn col : sortIdx.columns())
+                    for (SortedIndexColumnDefinition col : sortIdx.columns())
                         colsInit.create(String.valueOf(colIdx++), colInit -> convert(col, colInit));
                 });
 
                 break;
 
-            case PK_TYPE:
-                PrimaryIndex primIdx = (PrimaryIndex)idx;
-
-                idxChg.changeColumns(colsInit -> {
-                    int colIdx = 0;
-
-                    for (SortedIndexColumn col : primIdx.columns())
-                        colsInit.create(String.valueOf(colIdx++), colInit -> convert(col, colInit));
-                });
-
-                idxChg.changeAffinityColumns(primIdx.affinityColumns().toArray(
-                    new String[primIdx.affinityColumns().size()]));
-
-                break;
-
             default:
                 throw new IllegalArgumentException("Unknown index type " + idx.type());
         }
@@ -206,7 +189,7 @@
      * @param idxView TableIndexView.
      * @return TableIndex.
      */
-    public static TableIndex convert(TableIndexView idxView) {
+    public static IndexDefinition convert(TableIndexView idxView) {
         String name = idxView.name();
         String type = idxView.type();
 
@@ -214,48 +197,32 @@
             case HASH_TYPE:
                 String[] hashCols = idxView.colNames();
 
-                return new HashIndexImpl(name, hashCols);
+                return new HashIndexDefinitionImpl(name, hashCols);
 
             case SORTED_TYPE:
-                boolean sortedUniq = idxView.uniq();
-
-                SortedMap<Integer, SortedIndexColumn> sortedCols = new TreeMap<>();
+                SortedMap<Integer, SortedIndexColumnDefinition> sortedCols = new TreeMap<>();
 
                 for (String key : idxView.columns().namedListKeys()) {
-                    SortedIndexColumn col = convert(idxView.columns().get(key));
+                    SortedIndexColumnDefinition col = convert(idxView.columns().get(key));
 
                     sortedCols.put(Integer.valueOf(key), col);
                 }
 
-                return new SortedIndexImpl(name, new ArrayList<>(sortedCols.values()), sortedUniq);
+                return new SortedIndexDefinitionImpl(name, new ArrayList<>(sortedCols.values()), idxView.uniq());
 
             case PARTIAL_TYPE:
-                boolean partialUniq = idxView.uniq();
                 String expr = idxView.expr();
 
                 NamedListView<? extends IndexColumnView> colsView = idxView.columns();
-                SortedMap<Integer, SortedIndexColumn> partialCols = new TreeMap<>();
+                SortedMap<Integer, SortedIndexColumnDefinition> partialCols = new TreeMap<>();
 
                 for (String key : idxView.columns().namedListKeys()) {
-                    SortedIndexColumn col = convert(colsView.get(key));
+                    SortedIndexColumnDefinition col = convert(colsView.get(key));
 
                     partialCols.put(Integer.valueOf(key), col);
                 }
 
-                return new PartialIndexImpl(name, new ArrayList<>(partialCols.values()), partialUniq, expr);
-
-            case PK_TYPE:
-                SortedMap<Integer, SortedIndexColumn> cols = new TreeMap<>();
-
-                for (String key : idxView.columns().namedListKeys()) {
-                    SortedIndexColumn col = convert(idxView.columns().get(key));
-
-                    cols.put(Integer.valueOf(key), col);
-                }
-
-                String[] affCols = idxView.affinityColumns();
-
-                return new PrimaryIndexImpl(new ArrayList<>(cols.values()), List.of(affCols));
+                return new PartialIndexDefinitionImpl(name, new ArrayList<>(partialCols.values()), expr, idxView.uniq());
 
             default:
                 throw new IllegalArgumentException("Unknown type " + type);
@@ -263,6 +230,16 @@
     }
 
     /**
+     * Convert PrimaryKeyView into PrimaryKey.
+     *
+     * @param primaryKey PrimaryKeyView.
+     * @return TableIn.
+     */
+    public static PrimaryKeyDefinition convert(PrimaryKeyView primaryKey) {
+        return new PrimaryKeyDefinitionImpl(Set.of(primaryKey.columns()), Set.of(primaryKey.affinityColumns()));
+    }
+
+    /**
      * Convert ColumnType to ColumnTypeChange.
      *
      * @param colType ColumnType.
@@ -379,7 +356,7 @@
      * @param colChg Column
      * @return ColumnChange to get result from.
      */
-    public static ColumnChange convert(Column col, ColumnChange colChg) {
+    public static ColumnChange convert(ColumnDefinition col, ColumnChange colChg) {
         colChg.changeName(col.name());
         colChg.changeType(colTypeInit -> convert(col.type(), colTypeInit));
 
@@ -397,8 +374,8 @@
      * @param colView Column view.
      * @return Column.
      */
-    public static Column convert(ColumnView colView) {
-        return new ColumnImpl(
+    public static ColumnDefinition convert(ColumnView colView) {
+        return new ColumnDefinitionImpl(
             colView.name(),
             convert(colView.type()),
             colView.nullable(),
@@ -406,52 +383,57 @@
     }
 
     /**
-     * Convert schema table to schema table change.
+     * Convert table schema to table changer.
      *
-     * @param tbl Schema table to convert.
+     * @param tbl Table schema to convert.
      * @param tblChg Change to fulfill.
      * @return TableChange to get result from.
      */
-    public static TableChange convert(SchemaTable tbl, TableChange tblChg) {
+    public static TableChange convert(TableDefinition tbl, TableChange tblChg) {
         tblChg.changeName(tbl.canonicalName());
 
         tblChg.changeIndices(idxsChg -> {
             int idxIdx = 0;
 
-            for (TableIndex idx : tbl.indices())
+            for (IndexDefinition idx : tbl.indices())
                 idxsChg.create(String.valueOf(idxIdx++), idxInit -> convert(idx, idxInit));
         });
 
         tblChg.changeColumns(colsChg -> {
             int colIdx = 0;
 
-            for (Column col : tbl.keyColumns())
+            for (ColumnDefinition col : tbl.keyColumns())
                 colsChg.create(String.valueOf(colIdx++), colChg -> convert(col, colChg));
 
-            for (Column col : tbl.valueColumns())
+            for (ColumnDefinition col : tbl.valueColumns())
                 colsChg.create(String.valueOf(colIdx++), colChg -> convert(col, colChg));
         });
 
+        tblChg.changePrimaryKey(pkCng -> {
+            pkCng.changeColumns(tbl.keyColumns().stream().map(ColumnDefinition::name).toArray(String[]::new))
+                .changeAffinityColumns(tbl.affinityColumns().stream().map(ColumnDefinition::name).toArray(String[]::new));
+        });
+
         return tblChg;
     }
 
     /**
-     * Convert TableConfiguration to SchemaTable.
+     * Convert TableConfiguration to TableSchema.
      *
      * @param tblCfg TableConfiguration to convert.
-     * @return SchemaTable.
+     * @return Table schema.
      */
-    public static SchemaTable convert(TableConfiguration tblCfg) {
+    public static TableDefinition convert(TableConfiguration tblCfg) {
         return convert(tblCfg.value());
     }
 
     /**
-     * Convert configuration to SchemaTable.
+     * Convert table configuration view to table schema.
      *
      * @param tblView TableView to convert.
-     * @return SchemaTable.
+     * @return Table schema.
      */
-    public static SchemaTableImpl convert(TableView tblView) {
+    public static TableDefinitionImpl convert(TableView tblView) {
         String canonicalName = tblView.name();
         int sepPos = canonicalName.indexOf('.');
         String schemaName = canonicalName.substring(0, sepPos);
@@ -459,13 +441,13 @@
 
         NamedListView<? extends ColumnView> colsView = tblView.columns();
 
-        SortedMap<Integer, Column> columns = new TreeMap<>();
+        SortedMap<Integer, ColumnDefinition> columns = new TreeMap<>();
 
         for (String key : colsView.namedListKeys()) {
             ColumnView colView = colsView.get(key);
 
             if (colView != null) {
-                Column col = convert(colView);
+                ColumnDefinition col = convert(colView);
 
                 columns.put(Integer.valueOf(key), col);
             }
@@ -473,20 +455,22 @@
 
         NamedListView<? extends TableIndexView> idxsView = tblView.indices();
 
-        Map<String, TableIndex> indices = new HashMap<>(idxsView.size());
+        Map<String, IndexDefinition> indices = new HashMap<>(idxsView.size());
 
         for (String key : idxsView.namedListKeys()) {
             TableIndexView idxView = idxsView.get(key);
-            TableIndex idx = convert(idxView);
+            IndexDefinition idx = convert(idxView);
 
             indices.put(idx.name(), idx);
         }
 
-        LinkedHashMap<String, Column> colsMap = new LinkedHashMap<>(colsView.size());
+        LinkedHashMap<String, ColumnDefinition> colsMap = new LinkedHashMap<>(colsView.size());
 
         columns.forEach((i, v) -> colsMap.put(v.name(), v));
 
-        return new SchemaTableImpl(schemaName, tableName, colsMap, indices);
+        PrimaryKeyDefinition primaryKey = convert(tblView.primaryKey());
+
+        return new TableDefinitionImpl(schemaName, tableName, colsMap, primaryKey, indices);
     }
 
     /**
@@ -496,7 +480,7 @@
      * @param tblsChange Tables change to fulfill.
      * @return TablesChange to get result from.
      */
-    public static TablesChange createTable(SchemaTable tbl, TablesChange tblsChange) {
+    public static TablesChange createTable(TableDefinition tbl, TablesChange tblsChange) {
         return tblsChange.changeTables(tblsChg -> tblsChg.create(tbl.canonicalName(), tblChg -> convert(tbl, tblChg)));
     }
 
@@ -507,7 +491,7 @@
      * @param tblsChange TablesChange change to fulfill.
      * @return TablesChange to get result from.
      */
-    public static TablesChange dropTable(SchemaTable tbl, TablesChange tblsChange) {
+    public static TablesChange dropTable(TableDefinition tbl, TablesChange tblsChange) {
         return tblsChange.changeTables(schmTblChange -> schmTblChange.delete(tbl.canonicalName()));
     }
 
@@ -518,7 +502,7 @@
      * @param tblChange TableChange to fulfill.
      * @return TableChange to get result from.
      */
-    public static TableChange addIndex(TableIndex idx, TableChange tblChange) {
+    public static TableChange addIndex(IndexDefinition idx, TableChange tblChange) {
         return tblChange.changeIndices(idxsChg -> idxsChg.create(idx.name(), idxChg -> convert(idx, idxChg)));
     }
 
@@ -540,7 +524,7 @@
      * @param tblChange TableChange to fulfill.
      * @return TableChange to get result from.
      */
-    public static TableChange addColumn(Column column, TableChange tblChange) {
+    public static TableChange addColumn(ColumnDefinition column, TableChange tblChange) {
         return tblChange.changeColumns(colsChg -> colsChg.create(column.name(), colChg -> convert(column, colChg)));
     }
 
@@ -578,7 +562,7 @@
         else if (cls == double.class)
             return ColumnType.DOUBLE;
 
-        // Boxed primitives.
+            // Boxed primitives.
         else if (cls == Byte.class)
             return ColumnType.INT8;
         else if (cls == Short.class)
@@ -592,7 +576,7 @@
         else if (cls == Double.class)
             return ColumnType.DOUBLE;
 
-        // Temporal types.
+            // Temporal types.
         else if (cls == LocalDate.class)
             return ColumnType.DATE;
         else if (cls == LocalTime.class)
@@ -602,7 +586,7 @@
         else if (cls == Instant.class)
             return ColumnType.timestamp(ColumnType.TemporalColumnType.DEFAULT_PRECISION);
 
-        // Other types
+            // Other types
         else if (cls == String.class)
             return ColumnType.string();
         else if (cls == UUID.class)
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverter.java
index 191f103..5c09ade 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverter.java
@@ -36,8 +36,9 @@
 import org.apache.ignite.internal.schema.NativeTypes;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.SchemaException;
-import org.apache.ignite.schema.ColumnType;
-import org.apache.ignite.schema.SchemaTable;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
 
 import static org.apache.ignite.internal.schema.NativeTypes.DOUBLE;
 import static org.apache.ignite.internal.schema.NativeTypes.FLOAT;
@@ -48,7 +49,7 @@
 import static org.apache.ignite.internal.schema.NativeTypes.UUID;
 
 /**
- * Build SchemaDescriptor from SchemaTable internal configuration.
+ * Build SchemaDescriptor from Table internal configuration.
  */
 public class SchemaDescriptorConverter {
     /**
@@ -148,7 +149,7 @@
      * @param colCfg Column to confvert.
      * @return Internal Column.
      */
-    private static Column convert(org.apache.ignite.schema.Column colCfg) {
+    private static Column convert(ColumnDefinition colCfg) {
         NativeType type = convert(colCfg.type());
 
         return new Column(colCfg.name(), type, colCfg.nullable(), new ConstantSupplier(convertDefault(type, (String)colCfg.defaultValue())));
@@ -202,25 +203,24 @@
     }
 
     /**
-     * Build schema descriptor by SchemaTable.
+     * Build schema descriptor by table schema.
      *
-     * @param tblId Table id.
      * @param schemaVer Schema version.
-     * @param tblCfg SchemaTable.
+     * @param tblCfg Table schema.
      * @return SchemaDescriptor.
      */
-    public static SchemaDescriptor convert(int schemaVer, SchemaTable tblCfg) {
-        List<org.apache.ignite.schema.Column> keyColsCfg = new ArrayList<>(tblCfg.keyColumns());
+    public static SchemaDescriptor convert(int schemaVer, TableDefinition tblCfg) {
+        List<ColumnDefinition> keyColsCfg = new ArrayList<>(tblCfg.keyColumns());
 
         Column[] keyCols = new Column[keyColsCfg.size()];
 
         for (int i = 0; i < keyCols.length; i++)
             keyCols[i] = convert(keyColsCfg.get(i));
 
-        String[] affCols = tblCfg.affinityColumns().stream().map(org.apache.ignite.schema.Column::name)
+        String[] affCols = tblCfg.affinityColumns().stream().map(ColumnDefinition::name)
             .toArray(String[]::new);
 
-        List<org.apache.ignite.schema.Column> valColsCfg = new ArrayList<>(tblCfg.valueColumns());
+        List<ColumnDefinition> valColsCfg = new ArrayList<>(tblCfg.valueColumns());
 
         Column[] valCols = new Column[valColsCfg.size()];
 
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaTableValidatorImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/TableValidatorImpl.java
similarity index 67%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaTableValidatorImpl.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/TableValidatorImpl.java
index 6c7db2f..9f4f782 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaTableValidatorImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/TableValidatorImpl.java
@@ -19,22 +19,23 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.stream.Collectors;
 import org.apache.ignite.configuration.NamedListView;
 import org.apache.ignite.configuration.schemas.table.TableValidator;
 import org.apache.ignite.configuration.schemas.table.TableView;
 import org.apache.ignite.configuration.validation.ValidationContext;
 import org.apache.ignite.configuration.validation.ValidationIssue;
 import org.apache.ignite.configuration.validation.Validator;
-import org.apache.ignite.internal.schema.SchemaTableImpl;
-import org.apache.ignite.internal.schema.builder.SchemaTableBuilderImpl;
-import org.apache.ignite.schema.Column;
+import org.apache.ignite.internal.schema.definition.TableDefinitionImpl;
+import org.apache.ignite.internal.schema.definition.builder.TableSchemaBuilderImpl;
+import org.apache.ignite.schema.definition.ColumnDefinition;
 
 /**
- * SchemaTable validator implementation.
+ * Table schema configuration validator implementation.
  */
-public class SchemaTableValidatorImpl implements Validator<TableValidator, NamedListView<TableView>> {
+public class TableValidatorImpl implements Validator<TableValidator, NamedListView<TableView>> {
     /** Static instance. */
-    public static final SchemaTableValidatorImpl INSTANCE = new SchemaTableValidatorImpl();
+    public static final TableValidatorImpl INSTANCE = new TableValidatorImpl();
 
     /** {@inheritDoc} */
     @Override public void validate(TableValidator annotation, ValidationContext<NamedListView<TableView>> ctx) {
@@ -44,12 +45,15 @@
             TableView view = list.get(key);
             
             try {
-                SchemaTableImpl tbl = SchemaConfigurationConverter.convert(view);
+                TableDefinitionImpl tbl = SchemaConfigurationConverter.convert(view);
 
-                Collection<Column> allColumns = new ArrayList<>(tbl.keyColumns());
+                assert !tbl.keyColumns().isEmpty();
+                assert !tbl.affinityColumns().isEmpty();
+
+                Collection<ColumnDefinition> allColumns = new ArrayList<>(tbl.keyColumns());
                 allColumns.addAll(tbl.valueColumns());
 
-                SchemaTableBuilderImpl.validateIndices(tbl.indices(), allColumns);
+                TableSchemaBuilderImpl.validateIndices(tbl.indices(), allColumns, tbl.affinityColumns().stream().map(ColumnDefinition::name).collect(Collectors.toSet()));
             }
             catch (IllegalArgumentException e) {
                 ctx.addIssue(new ValidationIssue("Validator works success by key " + ctx.currentKey() + ". Found "
@@ -60,6 +64,6 @@
     }
 
     /** Private constructor. */
-    private SchemaTableValidatorImpl() {
+    private TableValidatorImpl() {
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/AbstractSchemaObject.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/AbstractSchemaObject.java
similarity index 88%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/AbstractSchemaObject.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/AbstractSchemaObject.java
index 4e9eac1..a9577d4 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/AbstractSchemaObject.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/AbstractSchemaObject.java
@@ -15,15 +15,15 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
+package org.apache.ignite.internal.schema.definition;
 
 import org.apache.ignite.internal.tostring.S;
-import org.apache.ignite.schema.SchemaNamedObject;
+import org.apache.ignite.schema.definition.SchemaObject;
 
 /**
  * Schema object base class.
  */
-public abstract class AbstractSchemaObject implements SchemaNamedObject {
+public abstract class AbstractSchemaObject implements SchemaObject {
     /** Schema object name. */
     private final String name;
 
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ColumnImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/ColumnDefinitionImpl.java
similarity index 67%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/ColumnImpl.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/ColumnDefinitionImpl.java
index 84e75f0..e9b2b73 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ColumnImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/ColumnDefinitionImpl.java
@@ -15,18 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
+package org.apache.ignite.internal.schema.definition;
 
-import org.apache.ignite.internal.tostring.IgniteToStringInclude;
 import org.apache.ignite.internal.tostring.S;
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.ColumnType;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.ColumnType;
 import org.jetbrains.annotations.Nullable;
 
 /**
  * Table column.
  */
-public class ColumnImpl extends AbstractSchemaObject implements Column {
+public class ColumnDefinitionImpl implements ColumnDefinition {
+    /** Column name. */
+    private final String name;
+
     /** Column type. */
     private final ColumnType type;
 
@@ -34,22 +36,26 @@
     private final boolean nullable;
 
     /** Default value. */
-    @IgniteToStringInclude(sensitive = true)
-    private final Object defVal;
+    private final Object defValExpr;
 
     /**
      * Constructor.
      *
      * @param name Column name.
      * @param type Column type.
-     * @param nullable Nullable flag.
-     * @param defVal Default value.
+     * @param nullable Nullability flag.
+     * @param defValExpr Default value.
      */
-    public ColumnImpl(String name, ColumnType type, boolean nullable, @Nullable Object defVal) {
-        super(name);
+    public ColumnDefinitionImpl(String name, ColumnType type, boolean nullable, @Nullable Object defValExpr) {
+        this.name = name;
         this.type = type;
         this.nullable = nullable;
-        this.defVal = defVal;
+        this.defValExpr = defValExpr;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return name;
     }
 
     /** {@inheritDoc} */
@@ -64,11 +70,11 @@
 
     /** {@inheritDoc} */
     @Override public Object defaultValue() {
-        return defVal;
+        return defValExpr;
     }
 
     /** {@inheritDoc} */
     @Override public String toString() {
-        return S.toString(ColumnImpl.class, this);
+        return S.toString(ColumnDefinitionImpl.class, this);
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/TableDefinitionImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/TableDefinitionImpl.java
new file mode 100644
index 0000000..95a0aab
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/TableDefinitionImpl.java
@@ -0,0 +1,148 @@
+/*
+ * 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.definition;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.internal.schema.modification.TableModificationBuilderImpl;
+import org.apache.ignite.internal.tostring.S;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.PrimaryKeyDefinition;
+import org.apache.ignite.schema.definition.TableDefinition;
+import org.apache.ignite.schema.definition.index.IndexDefinition;
+import org.apache.ignite.schema.modification.TableModificationBuilder;
+
+/**
+ * Table.
+ */
+@SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
+public class TableDefinitionImpl extends AbstractSchemaObject implements TableDefinition {
+    /** Schema name. */
+    private final String schemaName;
+
+    /** Key columns. */
+    private final LinkedHashMap<String, ColumnDefinition> cols;
+
+    /** Indices. */
+    private final Map<String, IndexDefinition> indices;
+
+    /** Cached key columns. */
+    private final List<ColumnDefinition> keyCols;
+
+    /** Cached key affinity columns. */
+    private final List<ColumnDefinition> affCols;
+
+    /** Cached value columns. */
+    private final List<ColumnDefinition> valCols;
+
+    /**
+     * Constructor.
+     *
+     * @param schemaName Schema name.
+     * @param tableName Table name.
+     * @param cols Columns.
+     * @param primaryKeyDefinition Primary key.
+     * @param indices Indices.
+     */
+    public TableDefinitionImpl(
+        String schemaName,
+        String tableName,
+        LinkedHashMap<String, ColumnDefinition> cols,
+        PrimaryKeyDefinition primaryKeyDefinition,
+        Map<String, IndexDefinition> indices
+    ) {
+        super(tableName);
+
+        this.schemaName = schemaName;
+        this.cols = cols;
+        this.indices = indices;
+
+        Set<String> pkCols = primaryKeyDefinition.columns();
+        Set<String> pkAffCols = primaryKeyDefinition.affinityColumns();
+
+        keyCols = new ArrayList<>(pkCols.size());
+        affCols = new ArrayList<>(pkAffCols.size());
+        valCols = new ArrayList<>(cols.size() - pkCols.size());
+
+        for (Map.Entry<String, ColumnDefinition> e : cols.entrySet()) {
+            if (pkCols.contains(e.getKey())) {
+                keyCols.add(e.getValue());
+
+                if (pkAffCols.contains(e.getValue().name()))
+                    affCols.add(e.getValue());
+            } else
+                valCols.add(e.getValue());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public String schemaName() {
+        return schemaName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<ColumnDefinition> keyColumns() {
+        return keyCols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<ColumnDefinition> affinityColumns() {
+        return affCols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<ColumnDefinition> valueColumns() {
+        return valCols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IndexDefinition> indices() {
+        return Collections.unmodifiableCollection(indices.values());
+    }
+
+    /** {@inheritDoc} */
+    @Override public TableModificationBuilder toBuilder() {
+        return new TableModificationBuilderImpl(this);
+    }
+
+    /**
+     * @param name Column name.
+     * @return {@code True} if column with given name already exists, {@code false} otherwise.
+     */
+    public boolean hasColumn(String name) {
+        return cols.containsKey(name);
+    }
+
+    /**
+     * @param name Column name.
+     * @return {@code True} if key column with given name already exists, {@code false} otherwise.
+     */
+    public boolean hasKeyColumn(String name) {
+        return keyCols.stream().anyMatch(c -> c.name().equals(name));
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(TableDefinitionImpl.class, this);
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/AbstractIndexBuilder.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/AbstractIndexBuilder.java
similarity index 65%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/AbstractIndexBuilder.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/AbstractIndexBuilder.java
index 3225c28..b160748 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/AbstractIndexBuilder.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/AbstractIndexBuilder.java
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.builder;
+package org.apache.ignite.internal.schema.definition.builder;
 
 import java.util.Collections;
 import java.util.Map;
-import org.apache.ignite.schema.builder.SchemaObjectBuilder;
+import org.apache.ignite.schema.definition.builder.SchemaObjectBuilder;
 
 /**
  * Index base class.
@@ -28,6 +28,9 @@
     /** Index name. */
     protected final String name;
 
+    /** Unique flag. */
+    private boolean unique;
+
     /** Builder hints. */
     protected Map<String, String> hints;
 
@@ -37,9 +40,39 @@
      * @param name Index name.
      */
     AbstractIndexBuilder(String name) {
-        this.name = name;
+        this(name, false);
     }
 
+    /**
+     * Constructor.
+     *
+     * @param name Index name.
+     * @param unique Unique flag.
+     */
+    AbstractIndexBuilder(String name, boolean unique) {
+        this.name = name;
+        this.unique = unique;
+    }
+
+    /**
+     * Unique index flag.
+     *
+     * @return Unique flag.
+     */
+    public boolean unique() {
+        return unique;
+    }
+
+    /**
+     * Sets unique index flag.
+     *
+     * @return {@code This} for chaining.
+     */
+    public AbstractIndexBuilder unique(boolean unique) {
+        this.unique = unique;
+
+        return this;
+    }
 
     /** {@inheritDoc} */
     @Override public AbstractIndexBuilder withHints(Map<String, String> hints) {
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/ColumnDefinitionBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/ColumnDefinitionBuilderImpl.java
new file mode 100644
index 0000000..487511d
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/ColumnDefinitionBuilderImpl.java
@@ -0,0 +1,84 @@
+/*
+ * 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.definition.builder;
+
+import java.util.Map;
+import org.apache.ignite.internal.schema.definition.ColumnDefinitionImpl;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.builder.ColumnDefinitionBuilder;
+
+/**
+ * Column builder.
+ */
+public class ColumnDefinitionBuilderImpl implements ColumnDefinitionBuilder {
+    /** Column name. */
+    private final String colName;
+
+    /** Column type. */
+    private final ColumnType colType;
+
+    /** Nullable flag. */
+    private boolean nullable;
+
+    /** Default value expression. */
+    private Object defValExpr;
+
+    /**
+     * Constructor.
+     * @param colName Column name.
+     * @param colType Column type.
+     */
+    public ColumnDefinitionBuilderImpl(String colName, ColumnType colType) {
+        this.colName = colName;
+        this.colType = colType;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ColumnDefinitionBuilderImpl asNullable() {
+        nullable = true;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ColumnDefinitionBuilderImpl asNonNull() {
+        nullable = false;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ColumnDefinitionBuilderImpl withDefaultValueExpression(Object defValExpr) {
+        this.defValExpr = defValExpr;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ColumnDefinitionBuilderImpl withHints(Map<String, String> hints) {
+        // No op.
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ColumnDefinition build() {
+        return new ColumnDefinitionImpl(colName, colType, nullable, defValExpr);
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/HashIndexBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/HashIndexDefinitionBuilderImpl.java
similarity index 63%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/HashIndexBuilderImpl.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/HashIndexDefinitionBuilderImpl.java
index 9013f66..137fc7c 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/HashIndexBuilderImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/HashIndexDefinitionBuilderImpl.java
@@ -15,17 +15,17 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.builder;
+package org.apache.ignite.internal.schema.definition.builder;
 
 import java.util.Map;
-import org.apache.ignite.internal.schema.HashIndexImpl;
-import org.apache.ignite.schema.HashIndex;
-import org.apache.ignite.schema.builder.HashIndexBuilder;
+import org.apache.ignite.internal.schema.definition.index.HashIndexDefinitionImpl;
+import org.apache.ignite.schema.definition.builder.HashIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.index.HashIndexDefinition;
 
 /**
  * Hash index builder.
  */
-public class HashIndexBuilderImpl extends AbstractIndexBuilder implements HashIndexBuilder {
+public class HashIndexDefinitionBuilderImpl extends AbstractIndexBuilder implements HashIndexDefinitionBuilder {
     /** Index columns. */
     private String[] columns;
 
@@ -34,29 +34,29 @@
      *
      * @param name Index name.
      */
-    public HashIndexBuilderImpl(String name) {
+    public HashIndexDefinitionBuilderImpl(String name) {
         super(name);
     }
 
     /** {@inheritDoc} */
-    @Override public HashIndexBuilder withColumns(String... columns) {
+    @Override public HashIndexDefinitionBuilder withColumns(String... columns) {
         this.columns = columns.clone();
 
         return this;
     }
 
     /** {@inheritDoc} */
-    @Override public HashIndexBuilderImpl withHints(Map<String, String> hints) {
+    @Override public HashIndexDefinitionBuilderImpl withHints(Map<String, String> hints) {
         super.withHints(hints);
 
         return this;
     }
 
     /** {@inheritDoc} */
-    @Override public HashIndex build() {
+    @Override public HashIndexDefinition build() {
         assert columns != null;
         assert columns.length > 0;
 
-        return new HashIndexImpl(name, columns);
+        return new HashIndexDefinitionImpl(name, columns);
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/PartialIndexBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/PartialIndexDefinitionBuilderImpl.java
similarity index 67%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/PartialIndexBuilderImpl.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/PartialIndexDefinitionBuilderImpl.java
index 80aea18..95a772c 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/PartialIndexBuilderImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/PartialIndexDefinitionBuilderImpl.java
@@ -15,19 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.builder;
+package org.apache.ignite.internal.schema.definition.builder;
 
 import java.util.Map;
 import java.util.stream.Collectors;
-import org.apache.ignite.internal.schema.PartialIndexImpl;
-import org.apache.ignite.internal.schema.SortedIndexColumnImpl;
-import org.apache.ignite.schema.PartialIndex;
-import org.apache.ignite.schema.builder.PartialIndexBuilder;
+import org.apache.ignite.internal.schema.definition.index.PartialIndexDefinitionImpl;
+import org.apache.ignite.internal.schema.definition.index.SortedIndexColumnDefinitionImpl;
+import org.apache.ignite.schema.definition.builder.PartialIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.index.PartialIndexDefinition;
 
 /**
  * Partial index builder.
  */
-public class PartialIndexBuilderImpl extends SortedIndexBuilderImpl implements PartialIndexBuilder {
+public class PartialIndexDefinitionBuilderImpl extends SortedIndexDefinitionBuilderImpl implements PartialIndexDefinitionBuilder {
     /** Partial index expression. */
     private String expr;
 
@@ -36,31 +36,31 @@
      *
      * @param idxName Index name.
      */
-    public PartialIndexBuilderImpl(String idxName) {
+    public PartialIndexDefinitionBuilderImpl(String idxName) {
         super(idxName);
     }
 
     /** {@inheritDoc} */
-    @Override public PartialIndexBuilderImpl withHints(Map<String, String> hints) {
+    @Override public PartialIndexDefinitionBuilderImpl withHints(Map<String, String> hints) {
         super.withHints(hints);
 
         return this;
     }
 
     /** {@inheritDoc} */
-    @Override public PartialIndex build() {
+    @Override public PartialIndexDefinition build() {
         assert expr != null && !expr.trim().isEmpty();
 
-        return new PartialIndexImpl(
+        return new PartialIndexDefinitionImpl(
             name,
-            cols.values().stream().map(c -> new SortedIndexColumnImpl(c.name, c.asc)).collect(Collectors.toList()),
-            unique,
-            expr
+            cols.values().stream().map(c -> new SortedIndexColumnDefinitionImpl(c.name, c.asc)).collect(Collectors.toList()),
+            expr,
+            unique()
         );
     }
 
     /** {@inheritDoc} */
-    @Override public PartialIndexBuilder withExpression(String expr) {
+    @Override public PartialIndexDefinitionBuilder withExpression(String expr) {
         this.expr = expr;
 
         return this;
@@ -80,7 +80,7 @@
          *
          * @param idxBuilder Index builder.
          */
-        PartialIndexColumnBuilderImpl(PartialIndexBuilderImpl idxBuilder) {
+        PartialIndexColumnBuilderImpl(PartialIndexDefinitionBuilderImpl idxBuilder) {
             super(idxBuilder);
         }
 
@@ -106,8 +106,8 @@
         }
 
         /** {@inheritDoc} */
-        @Override public PartialIndexBuilderImpl done() {
-            return (PartialIndexBuilderImpl)super.done();
+        @Override public PartialIndexDefinitionBuilderImpl done() {
+            return (PartialIndexDefinitionBuilderImpl)super.done();
         }
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/PrimaryKeyDefinitionBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/PrimaryKeyDefinitionBuilderImpl.java
new file mode 100644
index 0000000..b85006c
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/PrimaryKeyDefinitionBuilderImpl.java
@@ -0,0 +1,83 @@
+/*
+ * 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.definition.builder;
+
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.internal.schema.definition.index.PrimaryKeyDefinitionImpl;
+import org.apache.ignite.internal.tostring.IgniteToStringInclude;
+import org.apache.ignite.schema.definition.PrimaryKeyDefinition;
+import org.apache.ignite.schema.definition.builder.PrimaryKeyDefinitionBuilder;
+import org.apache.ignite.schema.definition.builder.SchemaObjectBuilder;
+
+/**
+ * Primary key builder.
+ */
+public class PrimaryKeyDefinitionBuilderImpl implements SchemaObjectBuilder, PrimaryKeyDefinitionBuilder {
+    /** Index columns. */
+    @IgniteToStringInclude
+    private String[] columns;
+
+    /** Affinity columns, */
+    @IgniteToStringInclude
+    private String[] affinityColumns;
+
+    /** Builder hints. */
+    protected Map<String, String> hints;
+
+    /** {@inheritDoc} */
+    @Override public PrimaryKeyDefinitionBuilderImpl withColumns(String... columns) {
+        this.columns = columns;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public PrimaryKeyDefinitionBuilderImpl withAffinityColumns(String... affinityColumns) {
+        this.affinityColumns = affinityColumns;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public PrimaryKeyDefinitionBuilderImpl withHints(Map<String, String> hints) {
+        this.hints = hints;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public PrimaryKeyDefinition build() {
+        if (columns == null)
+            throw new IllegalStateException("Primary key column(s) must be configured.");
+
+        Set<String> cols = Set.of(columns);
+
+        Set<String> affCols;
+
+        if (affinityColumns != null) {
+            affCols = Set.of(affinityColumns);
+
+            if (!cols.containsAll(affCols))
+                throw new IllegalStateException("Schema definition error: All affinity columns must be part of key.");
+        } else
+            affCols = cols;
+
+        return new PrimaryKeyDefinitionImpl(cols, affCols);
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/SortedIndexBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/SortedIndexDefinitionBuilderImpl.java
similarity index 69%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/SortedIndexBuilderImpl.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/SortedIndexDefinitionBuilderImpl.java
index 0f7fb54..97f9b31 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/SortedIndexBuilderImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/SortedIndexDefinitionBuilderImpl.java
@@ -15,40 +15,37 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.builder;
+package org.apache.ignite.internal.schema.definition.builder;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
-import org.apache.ignite.internal.schema.SortedIndexColumnImpl;
-import org.apache.ignite.internal.schema.SortedIndexImpl;
-import org.apache.ignite.schema.SortOrder;
-import org.apache.ignite.schema.SortedIndex;
-import org.apache.ignite.schema.SortedIndexColumn;
-import org.apache.ignite.schema.builder.SortedIndexBuilder;
+import org.apache.ignite.internal.schema.definition.index.SortedIndexColumnDefinitionImpl;
+import org.apache.ignite.internal.schema.definition.index.SortedIndexDefinitionImpl;
+import org.apache.ignite.schema.definition.builder.SortedIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.index.SortOrder;
+import org.apache.ignite.schema.definition.index.SortedIndexColumnDefinition;
+import org.apache.ignite.schema.definition.index.SortedIndexDefinition;
 
 /**
  * Sorted index builder.
  */
-public class SortedIndexBuilderImpl extends AbstractIndexBuilder implements SortedIndexBuilder {
+public class SortedIndexDefinitionBuilderImpl extends AbstractIndexBuilder implements SortedIndexDefinitionBuilder {
     /** Index columns. */
     protected final Map<String, SortedIndexColumnBuilderImpl> cols = new HashMap<>();
 
-    /** Unique flag. */
-    protected boolean unique;
-
     /**
      * Constructor.
      *
      * @param name Index name.
      */
-    public SortedIndexBuilderImpl(String name) {
+    public SortedIndexDefinitionBuilderImpl(String name) {
         super(name);
     }
 
     /** {@inheritDoc} */
-    @Override public SortedIndexBuilderImpl withHints(Map<String, String> hints) {
+    @Override public SortedIndexDefinitionBuilderImpl withHints(Map<String, String> hints) {
         super.withHints(hints);
 
         return this;
@@ -60,8 +57,8 @@
     }
 
     /** {@inheritDoc} */
-    @Override public SortedIndexBuilderImpl unique() {
-        unique = true;
+    @Override public SortedIndexDefinitionBuilderImpl unique(boolean unique) {
+        super.unique(unique);
 
         return this;
     }
@@ -77,18 +74,15 @@
     /**
      * @return Index columns.
      */
-    public List<SortedIndexColumn> columns() {
-        return cols.values().stream().map(c -> new SortedIndexColumnImpl(c.name, c.asc)).collect(Collectors.toList());
+    public List<SortedIndexColumnDefinition> columns() {
+        return cols.values().stream().map(c -> new SortedIndexColumnDefinitionImpl(c.name, c.asc)).collect(Collectors.toList());
     }
 
     /** {@inheritDoc} */
-    @Override public SortedIndex build() {
+    @Override public SortedIndexDefinition build() {
         assert !cols.isEmpty();
 
-        return new SortedIndexImpl(
-            name,
-            columns(),
-            unique);
+        return new SortedIndexDefinitionImpl(name, columns(), unique());
     }
 
     /**
@@ -96,7 +90,7 @@
      */
     protected static class SortedIndexColumnBuilderImpl implements SortedIndexColumnBuilder {
         /** Index builder. */
-        private final SortedIndexBuilderImpl parent;
+        private final SortedIndexDefinitionBuilderImpl parent;
 
         /** Columns name. */
         protected String name;
@@ -109,7 +103,7 @@
          *
          * @param parent Parent builder.
          */
-        SortedIndexColumnBuilderImpl(SortedIndexBuilderImpl parent) {
+        SortedIndexColumnBuilderImpl(SortedIndexDefinitionBuilderImpl parent) {
             this.parent = parent;
         }
 
@@ -139,7 +133,7 @@
         }
 
         /** {@inheritDoc} */
-        @Override public SortedIndexBuilderImpl done() {
+        @Override public SortedIndexDefinitionBuilderImpl done() {
             parent.addIndexColumn(this);
 
             return parent;
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/TableSchemaBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/TableSchemaBuilderImpl.java
new file mode 100644
index 0000000..e26017f
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/builder/TableSchemaBuilderImpl.java
@@ -0,0 +1,147 @@
+/*
+ * 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.definition.builder;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.ignite.internal.schema.definition.TableDefinitionImpl;
+import org.apache.ignite.schema.SchemaBuilders;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.PrimaryKeyDefinition;
+import org.apache.ignite.schema.definition.TableDefinition;
+import org.apache.ignite.schema.definition.builder.TableSchemaBuilder;
+import org.apache.ignite.schema.definition.index.ColumnarIndexDefinition;
+import org.apache.ignite.schema.definition.index.IndexColumnDefinition;
+import org.apache.ignite.schema.definition.index.IndexDefinition;
+
+/**
+ * Table builder.
+ */
+public class TableSchemaBuilderImpl implements TableSchemaBuilder {
+    /** Schema name. */
+    private final String schemaName;
+
+    /** Table name. */
+    private final String tableName;
+
+    /** Columns. */
+    private final LinkedHashMap<String, ColumnDefinition> columns = new LinkedHashMap<>();
+
+    /** Indices. */
+    private final Map<String, IndexDefinition> indices = new HashMap<>();
+
+    /** Table primary key. */
+    private PrimaryKeyDefinition primaryKeyDefinition;
+
+    /**
+     * Constructor.
+     *
+     * @param schemaName Schema name.
+     * @param tableName Table name.
+     */
+    public TableSchemaBuilderImpl(String schemaName, String tableName) {
+        this.schemaName = schemaName;
+        this.tableName = tableName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public TableSchemaBuilderImpl columns(ColumnDefinition... columns) {
+        for (ColumnDefinition column : columns) {
+            if (this.columns.put(column.name(), column) != null)
+                throw new IllegalArgumentException("Column with same name already exists: columnName=" + column.name());
+        }
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public TableSchemaBuilder withIndex(IndexDefinition indexDefinition) {
+        if (indices.put(indexDefinition.name(), indexDefinition) != null)
+            throw new IllegalArgumentException("Index with same name already exists: " + indexDefinition.name());
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public TableSchemaBuilder withPrimaryKey(String colName) {
+        primaryKeyDefinition = SchemaBuilders.primaryKey().withColumns(colName).build();
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public TableSchemaBuilder withPrimaryKey(PrimaryKeyDefinition primaryKeyDefinition) {
+        this.primaryKeyDefinition = primaryKeyDefinition;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public TableSchemaBuilder withHints(Map<String, String> hints) {
+        // No op.
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public TableDefinition build() {
+        assert schemaName != null : "Database schema name must be specified.";
+
+        assert columns.size() > primaryKeyDefinition.columns().size() : "Key or/and value columns must be defined.";
+        assert primaryKeyDefinition != null : "Primary key index must be configured.";
+
+        validateIndices(indices.values(), columns.values(), primaryKeyDefinition.affinityColumns());
+
+        return new TableDefinitionImpl(
+            schemaName,
+            tableName,
+            columns,
+            primaryKeyDefinition,
+            Collections.unmodifiableMap(indices)
+        );
+    }
+
+    /**
+     * Validate indices.
+     *
+     * @param indices Table indices.
+     * @param cols Table columns.
+     * @param affColNames Affinity columns names.
+     */
+    public static void validateIndices(Collection<IndexDefinition> indices, Collection<ColumnDefinition> cols, Set<String> affColNames) {
+        Set<String> colNames = cols.stream().map(ColumnDefinition::name).collect(Collectors.toSet());
+
+        for (IndexDefinition idx : indices) {
+            assert idx instanceof ColumnarIndexDefinition : "Only columnar indices are supported.";
+            // Note: E.g. functional index is not columnar index as it index an expression result only.
+
+            ColumnarIndexDefinition idx0 = (ColumnarIndexDefinition)idx;
+
+            if (!idx0.columns().stream().map(IndexColumnDefinition::name).allMatch(colNames::contains))
+                throw new IllegalStateException("Index column must exist in the schema.");
+
+            if (idx0.unique() &&
+                    !(idx0.columns().stream().map(IndexColumnDefinition::name).allMatch(affColNames::contains)))
+                throw new IllegalStateException("Unique index must contains all affinity columns.");
+        }
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/HashIndexImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/HashIndexDefinitionImpl.java
similarity index 66%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/HashIndexImpl.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/HashIndexDefinitionImpl.java
index fde1522..a81b5d0 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/HashIndexImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/HashIndexDefinitionImpl.java
@@ -15,23 +15,24 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
+package org.apache.ignite.internal.schema.definition.index;
 
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
+import org.apache.ignite.internal.schema.definition.AbstractSchemaObject;
 import org.apache.ignite.internal.tostring.IgniteToStringInclude;
 import org.apache.ignite.internal.tostring.S;
-import org.apache.ignite.schema.HashIndex;
-import org.apache.ignite.schema.IndexColumn;
+import org.apache.ignite.schema.definition.index.HashIndexDefinition;
+import org.apache.ignite.schema.definition.index.IndexColumnDefinition;
 
 /**
  * Hash index.
  */
-public class HashIndexImpl extends AbstractSchemaObject implements HashIndex {
+public class HashIndexDefinitionImpl extends AbstractSchemaObject implements HashIndexDefinition {
     /** Index columns. */
     @IgniteToStringInclude
-    private final List<IndexColumn> columns;
+    private final List<IndexColumnDefinition> columns;
 
     /**
      * Constructor.
@@ -39,21 +40,22 @@
      * @param name Index name.
      * @param columns Index columns.
      */
-    public HashIndexImpl(String name, String[] columns) {
+    public HashIndexDefinitionImpl(String name, String[] columns) {
         super(name);
 
-        this.columns = Arrays.stream(columns).map(IndexColumnImpl::new).collect(Collectors.toUnmodifiableList());
+        this.columns = Arrays.stream(columns).map(IndexColumnDefinitionImpl::new).collect(Collectors.toUnmodifiableList());
     }
 
+
     /** {@inheritDoc} */
     @SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
-    @Override public List<IndexColumn> columns() {
+    @Override public List<IndexColumnDefinition> columns() {
         return columns;
     }
 
     /** {@inheritDoc} */
     @Override public String toString() {
-        return S.toString(HashIndexImpl.class, this,
+        return S.toString(HashIndexDefinitionImpl.class, this,
             "type", type(),
             "name", name());
     }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/IndexColumnImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/IndexColumnDefinitionImpl.java
similarity index 70%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/IndexColumnImpl.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/IndexColumnDefinitionImpl.java
index 9948859..b264d0f 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/IndexColumnImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/IndexColumnDefinitionImpl.java
@@ -15,26 +15,27 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
+package org.apache.ignite.internal.schema.definition.index;
 
+import org.apache.ignite.internal.schema.definition.AbstractSchemaObject;
 import org.apache.ignite.internal.tostring.S;
-import org.apache.ignite.schema.IndexColumn;
+import org.apache.ignite.schema.definition.index.IndexColumnDefinition;
 
 /**
  * Non-ordered index column.
  */
-class IndexColumnImpl extends AbstractSchemaObject implements IndexColumn {
+class IndexColumnDefinitionImpl extends AbstractSchemaObject implements IndexColumnDefinition {
     /**
      * Constructor.
      *
      * @param name Column name.
      */
-    IndexColumnImpl(String name) {
+    IndexColumnDefinitionImpl(String name) {
         super(name);
     }
 
     /** {@inheritDoc} */
     @Override public String toString() {
-        return S.toString(IndexColumnImpl.class.getSimpleName(), "name", name());
+        return S.toString(IndexColumnDefinitionImpl.class.getSimpleName(), "name", name());
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/PartialIndexImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/PartialIndexDefinitionImpl.java
similarity index 70%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/PartialIndexImpl.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/PartialIndexDefinitionImpl.java
index 3500497..70c8990 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/PartialIndexImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/PartialIndexDefinitionImpl.java
@@ -15,17 +15,17 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
+package org.apache.ignite.internal.schema.definition.index;
 
 import java.util.List;
 import org.apache.ignite.internal.tostring.S;
-import org.apache.ignite.schema.PartialIndex;
-import org.apache.ignite.schema.SortedIndexColumn;
+import org.apache.ignite.schema.definition.index.PartialIndexDefinition;
+import org.apache.ignite.schema.definition.index.SortedIndexColumnDefinition;
 
 /**
  * Partial table index.
  */
-public class PartialIndexImpl extends SortedIndexImpl implements PartialIndex {
+public class PartialIndexDefinitionImpl extends SortedIndexDefinitionImpl implements PartialIndexDefinition {
     /** Expression. */
     private final String expr;
 
@@ -34,11 +34,11 @@
      *
      * @param name Index name.
      * @param columns Index columns.
-     * @param uniq Unique flag.
      * @param expr Partial index expression.
+     * @param unique Unique flag.
      */
-    public PartialIndexImpl(String name, List<SortedIndexColumn> columns, boolean uniq, String expr) {
-        super(name, columns, uniq);
+    public PartialIndexDefinitionImpl(String name, List<SortedIndexColumnDefinition> columns, String expr, boolean unique) {
+        super(name, columns, unique);
 
         this.expr = expr;
     }
@@ -50,7 +50,7 @@
 
     /** {@inheritDoc} */
     @Override public String toString() {
-        return S.toString(PartialIndex.class, this,
+        return S.toString(PartialIndexDefinition.class, this,
             "type", type(),
             "name", name(),
             "uniq", unique(),
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/PrimaryKeyDefinitionImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/PrimaryKeyDefinitionImpl.java
new file mode 100644
index 0000000..2723d41
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/PrimaryKeyDefinitionImpl.java
@@ -0,0 +1,68 @@
+/*
+ * 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.definition.index;
+
+import java.util.Set;
+import org.apache.ignite.internal.schema.definition.AbstractSchemaObject;
+import org.apache.ignite.internal.tostring.IgniteToStringInclude;
+import org.apache.ignite.internal.tostring.S;
+import org.apache.ignite.schema.definition.PrimaryKeyDefinition;
+
+/**
+ * Primary key index.
+ */
+public class PrimaryKeyDefinitionImpl extends AbstractSchemaObject implements PrimaryKeyDefinition {
+    /** Index columns. */
+    @IgniteToStringInclude
+    private final Set<String> columns;
+
+    /** Affinity columns. */
+    @IgniteToStringInclude
+    private final Set<String> affCols;
+
+    /**
+     * Constructor.
+     *
+     * @param columns Index columns.
+     * @param affinityColumns Affinity columns.
+     */
+    public PrimaryKeyDefinitionImpl(Set<String> columns, Set<String> affinityColumns) {
+        super(PrimaryKeyDefinition.PRIMARY_KEY_NAME);
+
+        this.columns = columns;
+        this.affCols = affinityColumns;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<String> columns() {
+        return columns;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<String> affinityColumns() {
+        return affCols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(PrimaryKeyDefinitionImpl.class, this,
+            "name", name(),
+            "cols", columns(),
+            "affCols", affinityColumns());
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SortedIndexColumnImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/SortedIndexColumnDefinitionImpl.java
similarity index 67%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/SortedIndexColumnImpl.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/SortedIndexColumnDefinitionImpl.java
index aafcb5f..3341d54 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SortedIndexColumnImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/SortedIndexColumnDefinitionImpl.java
@@ -15,16 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
+package org.apache.ignite.internal.schema.definition.index;
 
 import org.apache.ignite.internal.tostring.S;
-import org.apache.ignite.schema.SortOrder;
-import org.apache.ignite.schema.SortedIndexColumn;
+import org.apache.ignite.schema.definition.index.SortOrder;
+import org.apache.ignite.schema.definition.index.SortedIndexColumnDefinition;
 
 /**
  * Ordered index column.
  */
-public class SortedIndexColumnImpl extends AbstractSchemaObject implements SortedIndexColumn {
+public class SortedIndexColumnDefinitionImpl implements SortedIndexColumnDefinition {
+    /** Schema object name. */
+    private final String name;
+
     /** Sort order. */
     private final SortOrder sortOrder;
 
@@ -34,19 +37,23 @@
      * @param name Column name.
      * @param sortOrder Sort order flag.
      */
-    public SortedIndexColumnImpl(String name, SortOrder sortOrder) {
-        super(name);
-
+    public SortedIndexColumnDefinitionImpl(String name, SortOrder sortOrder) {
+        this.name = name;
         this.sortOrder = sortOrder;
     }
 
     /** {@inheritDoc} */
+    @Override public String name() {
+        return name;
+    }
+
+    /** {@inheritDoc} */
     @Override public SortOrder sortOrder() {
         return sortOrder;
     }
 
     /** {@inheritDoc} */
     @Override public String toString() {
-        return S.toString(SortedIndexColumnImpl.class, this);
+        return S.toString(SortedIndexColumnDefinitionImpl.class, this);
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SortedIndexImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/SortedIndexDefinitionImpl.java
similarity index 63%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/SortedIndexImpl.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/SortedIndexDefinitionImpl.java
index 3b5a44a..b6e54c8 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/SortedIndexImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/SortedIndexDefinitionImpl.java
@@ -15,58 +15,59 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
+package org.apache.ignite.internal.schema.definition.index;
 
 import java.util.Collections;
 import java.util.List;
+import org.apache.ignite.internal.schema.definition.AbstractSchemaObject;
 import org.apache.ignite.internal.tostring.IgniteToStringInclude;
 import org.apache.ignite.internal.tostring.S;
-import org.apache.ignite.schema.SortedIndex;
-import org.apache.ignite.schema.SortedIndexColumn;
+import org.apache.ignite.schema.definition.index.SortedIndexColumnDefinition;
+import org.apache.ignite.schema.definition.index.SortedIndexDefinition;
 
 /**
  * Sorted index.
  */
-public class SortedIndexImpl extends AbstractSchemaObject implements SortedIndex {
+public class SortedIndexDefinitionImpl extends AbstractSchemaObject implements SortedIndexDefinition {
     /** Columns. */
     @IgniteToStringInclude
-    private final List<SortedIndexColumn> cols;
+    private final List<SortedIndexColumnDefinition> cols;
 
     /** Unique flag. */
-    private final boolean uniq;
+    private final boolean unique;
 
     /**
      * Constructor.
      *
      * @param name Index name.
      * @param cols Index columns.
-     * @param uniq Unique flag.
+     * @param unique Unique flag.
      */
-    public SortedIndexImpl(String name, List<SortedIndexColumn> cols, boolean uniq) {
+    public SortedIndexDefinitionImpl(String name, List<SortedIndexColumnDefinition> cols, boolean unique) {
         super(name);
 
         this.cols = Collections.unmodifiableList(cols);
-        this.uniq = uniq;
-    }
-
-    /** {@inheritDoc} */
-    @Override public List<SortedIndexColumn> columns() {
-        return cols;
-    }
-
-    /** {@inheritDoc} */
-    @Override public List<SortedIndexColumn> indexedColumns() {
-        return cols;
+        this.unique = unique;
     }
 
     /** {@inheritDoc} */
     @Override public boolean unique() {
-        return uniq;
+        return unique;
+    }
+
+    /** {@inheritDoc} */
+    @Override public List<SortedIndexColumnDefinition> columns() {
+        return cols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public List<SortedIndexColumnDefinition> indexedColumns() {
+        return cols;
     }
 
     /** {@inheritDoc} */
     @Override public String toString() {
-        return S.toString(SortedIndex.class, this,
+        return S.toString(SortedIndexDefinition.class, this,
             "type", type(),
             "name", name());
     }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/modification/AlterColumnBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/modification/AlterColumnBuilderImpl.java
index 3b3a6a8..92e5092 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/modification/AlterColumnBuilderImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/modification/AlterColumnBuilderImpl.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.schema.modification;
 
-import org.apache.ignite.schema.ColumnType;
+import org.apache.ignite.schema.definition.ColumnType;
 import org.apache.ignite.schema.modification.AlterColumnBuilder;
 import org.apache.ignite.schema.modification.TableModificationBuilder;
 
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/modification/TableModificationBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/modification/TableModificationBuilderImpl.java
index fa9bece..06bd428 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/modification/TableModificationBuilderImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/modification/TableModificationBuilderImpl.java
@@ -17,10 +17,10 @@
 
 package org.apache.ignite.internal.schema.modification;
 
-import org.apache.ignite.internal.schema.SchemaTableImpl;
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.PrimaryIndex;
-import org.apache.ignite.schema.TableIndex;
+import org.apache.ignite.internal.schema.definition.TableDefinitionImpl;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.PrimaryKeyDefinition;
+import org.apache.ignite.schema.definition.index.IndexDefinition;
 import org.apache.ignite.schema.modification.AlterColumnBuilder;
 import org.apache.ignite.schema.modification.TableModificationBuilder;
 
@@ -29,19 +29,19 @@
  */
 public class TableModificationBuilderImpl implements TableModificationBuilder {
     /** Table. */
-    private final SchemaTableImpl table;
+    private final TableDefinitionImpl table;
 
     /**
      * Constructor.
      *
      * @param table Table.
      */
-    public TableModificationBuilderImpl(SchemaTableImpl table) {
+    public TableModificationBuilderImpl(TableDefinitionImpl table) {
         this.table = table;
     }
 
     /** {@inheritDoc} */
-    @Override public TableModificationBuilder addColumn(Column column) {
+    @Override public TableModificationBuilder addColumn(ColumnDefinition column) {
         if (table.hasColumn(column.name()))
             throw new IllegalArgumentException("Duplicate column: name='" + column.name() + '\'');
 
@@ -49,7 +49,7 @@
     }
 
     /** {@inheritDoc} */
-    @Override public TableModificationBuilder addKeyColumn(Column column) {
+    @Override public TableModificationBuilder addKeyColumn(ColumnDefinition column) {
         if (table.hasColumn(column.name()))
             throw new IllegalArgumentException("Duplicate column: name=" + column.name() + '\'');
 
@@ -70,18 +70,18 @@
     }
 
     /** {@inheritDoc} */
-    @Override public TableModificationBuilder addIndex(TableIndex index) {
-        assert !PrimaryIndex.PRIMARY_KEY_INDEX_NAME.equals(index.name());
+    @Override public TableModificationBuilder addIndex(IndexDefinition indexDefinition) {
+        assert !PrimaryKeyDefinition.PRIMARY_KEY_NAME.equals(indexDefinition.name());
 
-        if (table.indices().stream().anyMatch(i -> i.name().equals(index.name())))
-            throw new IllegalArgumentException("Index already exists: name=" + index.name() + '\'');
+        if (table.indices().stream().anyMatch(i -> i.name().equals(indexDefinition.name())))
+            throw new IllegalArgumentException("Index already exists: name=" + indexDefinition.name() + '\'');
 
         return this;
     }
 
     /** {@inheritDoc} */
     @Override public TableModificationBuilder dropIndex(String indexName) {
-        if (PrimaryIndex.PRIMARY_KEY_INDEX_NAME.equals(indexName))
+        if (PrimaryKeyDefinition.PRIMARY_KEY_NAME.equals(indexName))
             throw new IllegalArgumentException("Can't drop primary key index: name=" + indexName);
 
         return this;
diff --git a/modules/schema/src/main/java/org/apache/ignite/schema/SchemaBuilders.java b/modules/schema/src/main/java/org/apache/ignite/schema/SchemaBuilders.java
index fa806c0..7fba4b7 100644
--- a/modules/schema/src/main/java/org/apache/ignite/schema/SchemaBuilders.java
+++ b/modules/schema/src/main/java/org/apache/ignite/schema/SchemaBuilders.java
@@ -17,18 +17,20 @@
 
 package org.apache.ignite.schema;
 
-import org.apache.ignite.internal.schema.builder.HashIndexBuilderImpl;
-import org.apache.ignite.internal.schema.builder.PartialIndexBuilderImpl;
-import org.apache.ignite.internal.schema.builder.PrimaryKeyBuilderImpl;
-import org.apache.ignite.internal.schema.builder.SchemaTableBuilderImpl;
-import org.apache.ignite.internal.schema.builder.SortedIndexBuilderImpl;
-import org.apache.ignite.internal.schema.builder.TableColumnBuilderImpl;
-import org.apache.ignite.schema.builder.HashIndexBuilder;
-import org.apache.ignite.schema.builder.PartialIndexBuilder;
-import org.apache.ignite.schema.builder.PrimaryIndexBuilder;
-import org.apache.ignite.schema.builder.SchemaTableBuilder;
-import org.apache.ignite.schema.builder.SortedIndexBuilder;
-import org.apache.ignite.schema.builder.TableColumnBuilder;
+import org.apache.ignite.internal.schema.definition.builder.ColumnDefinitionBuilderImpl;
+import org.apache.ignite.internal.schema.definition.builder.HashIndexDefinitionBuilderImpl;
+import org.apache.ignite.internal.schema.definition.builder.PartialIndexDefinitionBuilderImpl;
+import org.apache.ignite.internal.schema.definition.builder.PrimaryKeyDefinitionBuilderImpl;
+import org.apache.ignite.internal.schema.definition.builder.SortedIndexDefinitionBuilderImpl;
+import org.apache.ignite.internal.schema.definition.builder.TableSchemaBuilderImpl;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
+import org.apache.ignite.schema.definition.builder.ColumnDefinitionBuilder;
+import org.apache.ignite.schema.definition.builder.HashIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.builder.PartialIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.builder.PrimaryKeyDefinitionBuilder;
+import org.apache.ignite.schema.definition.builder.SortedIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.builder.TableSchemaBuilder;
 
 /**
  * Schema builder helper.
@@ -43,7 +45,7 @@
      * @param valueClass Value class.
      * @return Table descriptor for given key-value pair.
      */
-    public static SchemaTable buildSchema(String schemaName, String tableName, Class<?> keyClass, Class<?> valueClass) {
+    public static TableDefinition buildSchema(String schemaName, String tableName, Class<?> keyClass, Class<?> valueClass) {
         // TODO IGNITE-13749: implement schema generation from classes.
 
         return null;
@@ -56,8 +58,8 @@
      * @param tableName Table name.
      * @return Table descriptor builder.
      */
-    public static SchemaTableBuilder tableBuilder(String schemaName, String tableName) {
-        return new SchemaTableBuilderImpl(schemaName, tableName);
+    public static TableSchemaBuilder tableBuilder(String schemaName, String tableName) {
+        return new TableSchemaBuilderImpl(schemaName, tableName);
     }
 
     /**
@@ -67,17 +69,17 @@
      * @param type Column type.
      * @return Column builder.
      */
-    public static TableColumnBuilder column(String name, ColumnType type) {
-        return new TableColumnBuilderImpl(name, type);
+    public static ColumnDefinitionBuilder column(String name, ColumnType type) {
+        return new ColumnDefinitionBuilderImpl(name, type);
     }
 
     /**
-     * Creates primary index builder.
+     * Creates primary key builder.
      *
-     * @return Primary index builder.
+     * @return Primary key builder.
      */
-    public static PrimaryIndexBuilder pkIndex() {
-        return new PrimaryKeyBuilderImpl();
+    public static PrimaryKeyDefinitionBuilder primaryKey() {
+        return new PrimaryKeyDefinitionBuilderImpl();
     }
 
     /**
@@ -86,8 +88,8 @@
      * @param name Index name.
      * @return Sorted index builder.
      */
-    public static SortedIndexBuilder sortedIndex(String name) {
-        return new SortedIndexBuilderImpl(name);
+    public static SortedIndexDefinitionBuilder sortedIndex(String name) {
+        return new SortedIndexDefinitionBuilderImpl(name);
     }
 
     /**
@@ -96,8 +98,8 @@
      * @param name Index name.
      * @return Partial index builder.
      */
-    public static PartialIndexBuilder partialIndex(String name) {
-        return new PartialIndexBuilderImpl(name);
+    public static PartialIndexDefinitionBuilder partialIndex(String name) {
+        return new PartialIndexDefinitionBuilderImpl(name);
     }
 
     /**
@@ -106,8 +108,8 @@
      * @param name Index name.
      * @return Hash index builder.
      */
-    public static HashIndexBuilder hashIndex(String name) {
-        return new HashIndexBuilderImpl(name);
+    public static HashIndexDefinitionBuilder hashIndex(String name) {
+        return new HashIndexDefinitionBuilderImpl(name);
     }
 
     // Stub.
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnDefinitionTest.java
similarity index 97%
rename from modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
rename to modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnDefinitionTest.java
index c6d30bc..e6cf5ba 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/ColumnDefinitionTest.java
@@ -29,7 +29,7 @@
 /**
  *
  */
-public class ColumnTest {
+public class ColumnDefinitionTest {
     /**
      *
      */
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java
index 5c732bc..67c7916 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.schema;
 
-import org.apache.ignite.schema.ColumnType;
+import org.apache.ignite.schema.definition.ColumnType;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaConfigurationTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaConfigurationTest.java
index 50dffcf..abca1d7 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaConfigurationTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaConfigurationTest.java
@@ -18,10 +18,11 @@
 package org.apache.ignite.internal.schema;
 
 import java.util.Map;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
-import org.apache.ignite.schema.builder.SchemaTableBuilder;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.SchemaObject;
+import org.apache.ignite.schema.definition.TableDefinition;
+import org.apache.ignite.schema.definition.builder.TableSchemaBuilder;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -33,23 +34,21 @@
      */
     @Test
     public void testInitialSchema() {
-        final SchemaTableBuilder builder = SchemaBuilders.tableBuilder(SchemaTable.DEFAULT_SCHEMA_NAME, "table1");
+        final TableSchemaBuilder builder = SchemaBuilders.tableBuilder(SchemaObject.DEFAULT_DATABASE_SCHEMA_NAME, "table1");
 
         builder
             .columns(
                 // Declaring columns in user order.
                 SchemaBuilders.column("id", ColumnType.INT64).build(),
-                SchemaBuilders.column("label", ColumnType.stringOf(2)).withDefaultValue("AI").build(),
+                SchemaBuilders.column("label", ColumnType.stringOf(2)).withDefaultValueExpression("AI").build(),
                 SchemaBuilders.column("name", ColumnType.string()).asNonNull().build(),
                 SchemaBuilders.column("data", ColumnType.blobOf(255)).asNullable().build(),
                 SchemaBuilders.column("affId", ColumnType.INT32).build()
             )
 
-            .withIndex(
-                SchemaBuilders.pkIndex()  // Declare index column in order.
-                    .addIndexColumn("id").desc().done()
-                    .addIndexColumn("affId").asc().done()
-                    .addIndexColumn("name").asc().done()
+            .withPrimaryKey(
+                SchemaBuilders.primaryKey()  // Declare index column in order.
+                    .withColumns("id", "affId", "name")
                     .withAffinityColumns("affId") // Optional affinity declaration. If not set, all columns will be affinity cols.
                     .build()
             )
@@ -87,7 +86,7 @@
      */
     @Test
     public void testSchemaModification() {
-        final SchemaTable table = SchemaBuilders.tableBuilder("PUBLIC", "table1")
+        final TableDefinition table = SchemaBuilders.tableBuilder("PUBLIC", "table1")
             .columns(
                 // Declaring columns in user order.
                 SchemaBuilders.column("id", ColumnType.INT64).build(),
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/TemporalTypesTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/TemporalTypesTest.java
index 5c6bbe1..e424d2a 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/TemporalTypesTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/TemporalTypesTest.java
@@ -21,7 +21,7 @@
 import java.time.LocalTime;
 import java.time.temporal.ChronoUnit;
 import org.apache.ignite.internal.schema.row.TemporalTypesHelper;
-import org.apache.ignite.schema.ColumnType;
+import org.apache.ignite.schema.definition.ColumnType;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/TableColumnBuilderTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/ColumnDefinitionBuilderTest.java
similarity index 73%
rename from modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/TableColumnBuilderTest.java
rename to modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/ColumnDefinitionBuilderTest.java
index c0f7af3..73f187f 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/TableColumnBuilderTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/ColumnDefinitionBuilderTest.java
@@ -17,10 +17,10 @@
 
 package org.apache.ignite.internal.schema.builder;
 
-import org.apache.ignite.schema.Column;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.builder.TableColumnBuilder;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.builder.ColumnDefinitionBuilder;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -29,19 +29,19 @@
 /**
  * Tests for table column builder.
  */
-public class TableColumnBuilderTest {
+public class ColumnDefinitionBuilderTest {
     /**
      * Check column parameters.
      */
     @Test
     public void testCreateColumn() {
-        TableColumnBuilder builder = SchemaBuilders.column("TEST", ColumnType.DOUBLE);
+        ColumnDefinitionBuilder builder = SchemaBuilders.column("TEST", ColumnType.DOUBLE);
 
-        Column col = builder.asNonNull().withDefaultValue(1.).build();
+        ColumnDefinition col = builder.asNonNull().withDefaultValueExpression("NOW()").build();
 
         assertEquals("TEST", col.name());
         assertEquals(ColumnType.DOUBLE, col.type());
-        assertEquals(1., col.defaultValue());
+        assertEquals("NOW()", col.defaultValue());
         assertFalse(col.nullable());
     }
 }
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/HashIndexBuilderTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/HashIndexDefinitionBuilderTest.java
similarity index 79%
rename from modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/HashIndexBuilderTest.java
rename to modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/HashIndexDefinitionBuilderTest.java
index 106723c..258825e 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/HashIndexBuilderTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/HashIndexDefinitionBuilderTest.java
@@ -18,9 +18,9 @@
 package org.apache.ignite.internal.schema.builder;
 
 import java.util.Collections;
-import org.apache.ignite.schema.HashIndex;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.builder.HashIndexBuilder;
+import org.apache.ignite.schema.definition.builder.HashIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.index.HashIndexDefinition;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -29,16 +29,16 @@
 /**
  * Tests for hash index builder.
  */
-public class HashIndexBuilderTest {
+public class HashIndexDefinitionBuilderTest {
     /**
      * Build index and check its parameters.
      */
     @Test
     public void testBuild() {
-        HashIndexBuilder builder = SchemaBuilders.hashIndex("testHI")
+        HashIndexDefinitionBuilder builder = SchemaBuilders.hashIndex("testHI")
             .withColumns("A", "B", "C")
             .withHints(Collections.singletonMap("param","value"));
-        HashIndex idx = builder.build();
+        HashIndexDefinition idx = builder.build();
 
         assertEquals("testHI", idx.name());
         assertEquals(3, idx.columns().size());
@@ -49,7 +49,7 @@
      */
     @Test
     public void testBuildNoColumns() {
-        HashIndexBuilder builder = SchemaBuilders.hashIndex("testHI");
+        HashIndexDefinitionBuilder builder = SchemaBuilders.hashIndex("testHI");
 
         assertThrows(AssertionError.class, builder::build);
     }
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PartialIndexBuilderTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PartialIndexDefinitionBuilderTest.java
similarity index 79%
rename from modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PartialIndexBuilderTest.java
rename to modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PartialIndexDefinitionBuilderTest.java
index 50c818c..7365f82 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PartialIndexBuilderTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PartialIndexDefinitionBuilderTest.java
@@ -17,9 +17,9 @@
 
 package org.apache.ignite.internal.schema.builder;
 
-import org.apache.ignite.schema.PartialIndex;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.builder.PartialIndexBuilder;
+import org.apache.ignite.schema.definition.builder.PartialIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.index.PartialIndexDefinition;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -27,18 +27,18 @@
 /**
  * Tests for partial index builder.
  */
-public class PartialIndexBuilderTest {
+public class PartialIndexDefinitionBuilderTest {
     /**
      * Test partial index parameters.
      */
     @Test
     public void testPartialIndexCreate() {
-        PartialIndexBuilder builder = SchemaBuilders.partialIndex("TEST");
+        PartialIndexDefinitionBuilder builder = SchemaBuilders.partialIndex("TEST");
 
         builder.addIndexColumn("A").done();
         builder.withExpression("WHERE A > 0");
 
-        PartialIndex idx = builder.build();
+        PartialIndexDefinition idx = builder.build();
 
         assertEquals(1, idx.columns().size());
         assertEquals("WHERE A > 0", idx.expr());
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PrimaryKeyBuilderTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PrimaryKeyBuilderTest.java
deleted file mode 100644
index 1e15096..0000000
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PrimaryKeyBuilderTest.java
+++ /dev/null
@@ -1,46 +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.builder;
-
-import org.apache.ignite.schema.PrimaryIndex;
-import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SortOrder;
-import org.apache.ignite.schema.builder.PrimaryIndexBuilder;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-/**
- * Primary key builder test.
- */
-public class PrimaryKeyBuilderTest {
-    /** Test primary index parameters. */
-    @Test
-    public void testPrimaryKey() {
-        PrimaryIndexBuilder builder = SchemaBuilders.pkIndex();
-
-        builder.addIndexColumn("A").desc().done();
-        builder.addIndexColumn("B").asc().done();
-
-        PrimaryIndex idx = builder.build();
-
-        assertEquals(2, idx.columns().size());
-        assertEquals(SortOrder.DESC, idx.columns().get(0).sortOrder());
-        assertEquals(SortOrder.ASC, idx.columns().get(1).sortOrder());
-    }
-}
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PrimaryKeyDefinitionDefinitionBuilderTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PrimaryKeyDefinitionDefinitionBuilderTest.java
new file mode 100644
index 0000000..1d28aac
--- /dev/null
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/PrimaryKeyDefinitionDefinitionBuilderTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.builder;
+
+import java.util.List;
+import org.apache.ignite.schema.SchemaBuilders;
+import org.apache.ignite.schema.definition.PrimaryKeyDefinition;
+import org.apache.ignite.schema.definition.builder.PrimaryKeyDefinitionBuilder;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Primary key builder test.
+ */
+public class PrimaryKeyDefinitionDefinitionBuilderTest {
+    /** Test primary key parameters. */
+    @Test
+    public void testPrimaryKeyWithAffinityColumns() {
+        PrimaryKeyDefinitionBuilder builder = SchemaBuilders.primaryKey();
+
+        builder.withColumns("A", "B", "C").withAffinityColumns("B").build();
+
+        PrimaryKeyDefinition idx = builder.build();
+
+        assertEquals(3, idx.columns().size());
+        assertEquals(1, idx.affinityColumns().size());
+
+        assertTrue(idx.columns().containsAll(List.of("A", "B", "C")));
+        assertTrue(idx.affinityColumns().contains("B"));
+
+        assertFalse(idx.affinityColumns().contains("A"));
+        assertFalse(idx.affinityColumns().contains("C"));
+    }
+
+    /** Test primary key parameters. */
+    @Test
+    public void testPrimaryKey() {
+        PrimaryKeyDefinitionBuilder builder = SchemaBuilders.primaryKey();
+
+        builder.withColumns("A", "B", "C").build();
+
+        PrimaryKeyDefinition idx = builder.build();
+
+        assertEquals(3, idx.columns().size());
+        assertEquals(3, idx.affinityColumns().size());
+
+        assertTrue(idx.columns().containsAll(List.of("A", "B", "C")));
+        assertTrue(idx.affinityColumns().containsAll(List.of("A", "B", "C")));
+    }
+
+    /** Test primary key parameters. */
+    @Test
+    public void testPrimaryKeyWrongAffinityColumn() {
+        PrimaryKeyDefinitionBuilder builder = SchemaBuilders.primaryKey()
+                                        .withColumns("A", "B")
+                                        .withAffinityColumns("C");
+
+        assertThrows(IllegalStateException.class, builder::build);
+    }
+}
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/SortedIndexBuilderTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/SortedIndexDefinitionBuilderTest.java
similarity index 67%
rename from modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/SortedIndexBuilderTest.java
rename to modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/SortedIndexDefinitionBuilderTest.java
index 36b67e0..0c5c64b 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/SortedIndexBuilderTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/SortedIndexDefinitionBuilderTest.java
@@ -18,32 +18,33 @@
 package org.apache.ignite.internal.schema.builder;
 
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SortedIndex;
-import org.apache.ignite.schema.builder.SortedIndexBuilder;
+import org.apache.ignite.schema.definition.builder.SortedIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.index.SortOrder;
+import org.apache.ignite.schema.definition.index.SortedIndexDefinition;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 
 /**
  * Tests for sorted index builder.
  */
-public class SortedIndexBuilderTest {
+public class SortedIndexDefinitionBuilderTest {
     /**
      * Build sorted index and check it's parameters.
      */
     @Test
     public void testBuild() {
-        SortedIndexBuilder builder = SchemaBuilders.sortedIndex("SIDX");
+        SortedIndexDefinitionBuilder builder = SchemaBuilders.sortedIndex("SIDX");
 
         builder.addIndexColumn("A").asc().done();
         builder.addIndexColumn("B").desc().done();
 
-        builder.unique();
+        SortedIndexDefinition idx = builder.build();
 
-        SortedIndex idx = builder.build();
-
-        assertTrue(idx.unique());
+        assertFalse(idx.unique());
         assertEquals(2, idx.indexedColumns().size());
+        assertEquals(SortOrder.ASC, idx.columns().get(0).sortOrder());
+        assertEquals(SortOrder.DESC, idx.columns().get(1).sortOrder());
     }
 }
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/SchemaTableBuilderTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/TableDefinitionBuilderTest.java
similarity index 77%
rename from modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/SchemaTableBuilderTest.java
rename to modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/TableDefinitionBuilderTest.java
index 3e0f53a..e802818 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/SchemaTableBuilderTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/builder/TableDefinitionBuilderTest.java
@@ -17,30 +17,30 @@
 
 package org.apache.ignite.internal.schema.builder;
 
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
-import org.apache.ignite.schema.builder.SchemaTableBuilder;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
+import org.apache.ignite.schema.definition.builder.TableSchemaBuilder;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
- * Tests for schema table builder.
+ * Tests for table schema builder.
  */
-public class SchemaTableBuilderTest {
+public class TableDefinitionBuilderTest {
     /**
-     * Create schema table and check its parameters.
+     * Create table schema and check its parameters.
      */
     @Test
     public void testBuild() {
-        SchemaTableBuilder builder = SchemaBuilders.tableBuilder("SNAME","TNAME")
+        TableSchemaBuilder builder = SchemaBuilders.tableBuilder("SNAME","TNAME")
             .columns(
                 SchemaBuilders.column("COL1", ColumnType.DOUBLE).build(),
                 SchemaBuilders.column("COL2", ColumnType.DOUBLE).build())
             .withPrimaryKey("COL1");
 
-        SchemaTable tbl = builder.build();
+        TableDefinition tbl = builder.build();
 
         assertEquals("SNAME.TNAME", tbl.canonicalName());
         assertEquals("TNAME", tbl.name());
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverterTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverterTest.java
index f92ee5b..6707be1 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverterTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverterTest.java
@@ -29,27 +29,28 @@
 import org.apache.ignite.configuration.schemas.table.TablesConfiguration;
 import org.apache.ignite.internal.configuration.ConfigurationRegistry;
 import org.apache.ignite.internal.configuration.storage.TestConfigurationStorage;
-import org.apache.ignite.schema.ColumnType;
-import org.apache.ignite.schema.HashIndex;
-import org.apache.ignite.schema.PartialIndex;
-import org.apache.ignite.schema.PrimaryIndex;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
-import org.apache.ignite.schema.SortedIndex;
-import org.apache.ignite.schema.SortedIndexColumn;
-import org.apache.ignite.schema.TableIndex;
-import org.apache.ignite.schema.builder.HashIndexBuilder;
-import org.apache.ignite.schema.builder.PartialIndexBuilder;
-import org.apache.ignite.schema.builder.PrimaryIndexBuilder;
-import org.apache.ignite.schema.builder.SchemaTableBuilder;
-import org.apache.ignite.schema.builder.SortedIndexBuilder;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
+import org.apache.ignite.schema.definition.builder.HashIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.builder.PartialIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.builder.SortedIndexDefinitionBuilder;
+import org.apache.ignite.schema.definition.builder.TableSchemaBuilder;
+import org.apache.ignite.schema.definition.index.HashIndexDefinition;
+import org.apache.ignite.schema.definition.index.IndexColumnDefinition;
+import org.apache.ignite.schema.definition.index.IndexDefinition;
+import org.apache.ignite.schema.definition.index.PartialIndexDefinition;
+import org.apache.ignite.schema.definition.index.SortOrder;
+import org.apache.ignite.schema.definition.index.SortedIndexDefinition;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
  * SchemaConfigurationConverter tests.
@@ -57,7 +58,7 @@
 @SuppressWarnings("InstanceVariableMayNotBeInitialized")
 public class SchemaConfigurationConverterTest {
     /** Table builder. */
-    private SchemaTableBuilder tblBuilder;
+    private TableSchemaBuilder tblBuilder;
 
     /** Configuration registry with one table for each test. */
     private ConfigurationRegistry confRegistry;
@@ -65,14 +66,14 @@
     /**
      * Prepare configuration registry for test.
      *
-     * @throws ExecutionException If failed.
+     * @throws ExecutionException   If failed.
      * @throws InterruptedException If failed.
      */
     @BeforeEach
     public void createRegistry() throws ExecutionException, InterruptedException {
         confRegistry = new ConfigurationRegistry(
             List.of(TablesConfiguration.KEY),
-            Map.of(TableValidator.class, Set.of(SchemaTableValidatorImpl.INSTANCE)),
+            Map.of(TableValidator.class, Set.of(TableValidatorImpl.INSTANCE)),
             new TestConfigurationStorage(DISTRIBUTED),
             List.of()
         );
@@ -80,22 +81,22 @@
         confRegistry.start();
 
         tblBuilder = SchemaBuilders.tableBuilder("SNAME", "TNAME")
-            .columns(
-                SchemaBuilders.column("COL1", ColumnType.DOUBLE).build(),
-                SchemaBuilders.column("COL2", ColumnType.DOUBLE).build(),
-                SchemaBuilders.column("A", ColumnType.INT8).build(),
-                SchemaBuilders.column("B", ColumnType.INT8).build(),
-                SchemaBuilders.column("C", ColumnType.INT8).build()
-            ).withPrimaryKey("COL1");
+                         .columns(
+                             SchemaBuilders.column("COL1", ColumnType.DOUBLE).build(),
+                             SchemaBuilders.column("COL2", ColumnType.DOUBLE).build(),
+                             SchemaBuilders.column("A", ColumnType.INT8).build(),
+                             SchemaBuilders.column("B", ColumnType.INT8).build(),
+                             SchemaBuilders.column("C", ColumnType.INT8).build()
+                         ).withPrimaryKey("COL1");
 
-        SchemaTable tbl = tblBuilder.build();
+        TableDefinition tbl = tblBuilder.build();
 
         confRegistry.getConfiguration(TablesConfiguration.KEY).change(
-            ch -> {
-                SchemaConfigurationConverter.createTable(tbl, ch)
-                    .changeTables(tblsCh -> tblsCh.createOrUpdate(tbl.canonicalName(),
-                        tblCh -> tblCh.changeReplicas(1)));
-            }).get();
+            ch -> SchemaConfigurationConverter.createTable(tbl, ch)
+                      .changeTables(
+                          tblsCh -> tblsCh.createOrUpdate(tbl.canonicalName(), tblCh -> tblCh.changeReplicas(1))
+                      )
+        ).get();
     }
 
     @AfterEach
@@ -108,16 +109,16 @@
      */
     @Test
     public void testConvertHashIndex() throws ExecutionException, InterruptedException {
-        HashIndexBuilder builder = SchemaBuilders.hashIndex("testHI")
-            .withColumns("A", "B", "C")
-            .withHints(Collections.singletonMap("param", "value"));
-        HashIndex idx = builder.build();
+        HashIndexDefinitionBuilder builder = SchemaBuilders.hashIndex("testHI")
+                                       .withColumns("A", "B", "C")
+                                       .withHints(Collections.singletonMap("param", "value"));
+        HashIndexDefinition idx = builder.build();
 
         getTbl().change(ch -> SchemaConfigurationConverter.addIndex(idx, ch)).get();
 
-        SchemaTable tbl = SchemaConfigurationConverter.convert(getTbl().value());
+        TableDefinition tbl = SchemaConfigurationConverter.convert(getTbl().value());
 
-        HashIndex idx2 = (HashIndex)getIdx(idx.name(), tbl.indices());
+        HashIndexDefinition idx2 = (HashIndexDefinition)getIdx(idx.name(), tbl.indices());
 
         assertNotNull(idx2);
         assertEquals("HASH", idx2.type());
@@ -129,50 +130,80 @@
      */
     @Test
     public void testConvertSortedIndex() throws ExecutionException, InterruptedException {
-        SortedIndexBuilder builder = SchemaBuilders.sortedIndex("SIDX");
+        SortedIndexDefinitionBuilder builder = SchemaBuilders.sortedIndex("SIDX");
 
         builder.addIndexColumn("A").asc().done();
         builder.addIndexColumn("B").desc().done();
 
-        builder.unique();
-
-        SortedIndex idx = builder.build();
+        SortedIndexDefinition idx = builder.build();
 
         getTbl().change(ch -> SchemaConfigurationConverter.addIndex(idx, ch)).get();
 
-        SchemaTable tbl = SchemaConfigurationConverter.convert(getTbl().value());
+        TableDefinition tbl = SchemaConfigurationConverter.convert(getTbl().value());
 
-        SortedIndex idx2 = (SortedIndex)getIdx(idx.name(), tbl.indices());
+        SortedIndexDefinition idx2 = (SortedIndexDefinition)getIdx(idx.name(), tbl.indices());
 
         assertNotNull(idx2);
         assertEquals("SORTED", idx2.type());
         assertEquals(2, idx2.columns().size());
+        assertEquals("A", idx2.columns().get(0).name());
+        assertEquals("B", idx2.columns().get(1).name());
+        assertEquals(SortOrder.ASC, idx2.columns().get(0).sortOrder());
+        assertEquals(SortOrder.DESC, idx2.columns().get(1).sortOrder());
     }
 
     /**
-     * Add/remove PrimaryIndex into configuration and read it back.
+     * Add/remove index on primary key into configuration and read it back.
      */
     @Test
-    public void testPKIndex() throws ExecutionException, InterruptedException {
-        PrimaryIndexBuilder builder = SchemaBuilders.pkIndex();
-        builder.addIndexColumn("COL1").desc().done();
-        builder.addIndexColumn("A").desc().done();
-        builder.addIndexColumn("B").asc().done();
-        builder.withAffinityColumns("COL1");
-
-        PrimaryIndex idx = builder.build();
+    public void testUniqIndex() throws ExecutionException, InterruptedException {
+        SortedIndexDefinition idx = SchemaBuilders.sortedIndex("pk_sorted")
+                              .addIndexColumn("COL1").desc().done()
+                              .unique(true)
+                              .build();
 
         getTbl().change(ch -> SchemaConfigurationConverter.addIndex(idx, ch)).get();
 
-        SchemaTable tbl = SchemaConfigurationConverter.convert(getTbl().value());
+        TableDefinition tbl = SchemaConfigurationConverter.convert(getTbl().value());
 
-        PrimaryIndex idx2 = (PrimaryIndex)getIdx(idx.name(), tbl.indices());
+        SortedIndexDefinition idx2 = (SortedIndexDefinition)getIdx(idx.name(), tbl.indices());
 
         assertNotNull(idx2);
-        assertEquals("PK", idx2.type());
-        assertEquals(idx.columns().stream().map(SortedIndexColumn::name).collect(Collectors.toList()),
-            idx2.columns().stream().map(SortedIndexColumn::name).collect(Collectors.toList()));
-        assertEquals(idx.affinityColumns(), idx2.affinityColumns());
+        assertEquals("pk_sorted", idx2.name());
+        assertEquals("SORTED", idx2.type());
+        assertEquals(idx.columns().stream().map(IndexColumnDefinition::name).collect(Collectors.toList()),
+            idx2.columns().stream().map(IndexColumnDefinition::name).collect(Collectors.toList()));
+        assertTrue(idx2.unique());
+    }
+
+    /**
+     * Detect an index containing affinity key as unique one.
+     */
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-15483")
+    @Test
+    public void testUniqueIndexDetection() throws ExecutionException, InterruptedException {
+        SortedIndexDefinition idx = SchemaBuilders.sortedIndex("uniq_sorted")
+                              .addIndexColumn("A").done()
+                              .addIndexColumn("COL1").desc().done()
+                              .build();
+
+        getTbl().change(ch -> SchemaConfigurationConverter.addIndex(idx, ch)).get();
+
+        TableDefinition tbl = SchemaConfigurationConverter.convert(getTbl().value());
+
+        SortedIndexDefinition idx2 = (SortedIndexDefinition)getIdx(idx.name(), tbl.indices());
+
+        assertNotNull(idx2);
+        assertEquals("uniq_sorted", idx2.name());
+        assertEquals("SORTED", idx2.type());
+
+        assertTrue(idx2.unique());
+
+        assertEquals(2, idx2.columns().size());
+        assertEquals("A", idx2.columns().get(0).name());
+        assertEquals("COL1", idx2.columns().get(1).name());
+        assertEquals(SortOrder.ASC, idx2.columns().get(0).sortOrder());
+        assertEquals(SortOrder.DESC, idx2.columns().get(1).sortOrder());
     }
 
     /**
@@ -180,18 +211,18 @@
      */
     @Test
     public void testPartialIndex() throws ExecutionException, InterruptedException {
-        PartialIndexBuilder builder = SchemaBuilders.partialIndex("TEST");
+        PartialIndexDefinitionBuilder builder = SchemaBuilders.partialIndex("TEST");
 
         builder.addIndexColumn("A").done();
         builder.withExpression("WHERE A > 0");
 
-        PartialIndex idx = builder.build();
+        PartialIndexDefinition idx = builder.build();
 
         getTbl().change(ch -> SchemaConfigurationConverter.addIndex(idx, ch)).get();
 
-        SchemaTable tbl = SchemaConfigurationConverter.convert(getTbl().value());
+        TableDefinition tbl = SchemaConfigurationConverter.convert(getTbl().value());
 
-        PartialIndex idx2 = (PartialIndex) getIdx(idx.name(), tbl.indices());
+        PartialIndexDefinition idx2 = (PartialIndexDefinition)getIdx(idx.name(), tbl.indices());
 
         assertNotNull(idx2);
         assertEquals("PARTIAL", idx2.type());
@@ -203,12 +234,12 @@
      */
     @Test
     public void testConvertTable() {
-        SchemaTable tbl = tblBuilder.build();
+        TableDefinition tbl = tblBuilder.build();
 
         TableConfiguration tblCfg = confRegistry.getConfiguration(TablesConfiguration.KEY).tables()
-            .get(tbl.canonicalName());
+                                        .get(tbl.canonicalName());
 
-        SchemaTable tbl2 = SchemaConfigurationConverter.convert(tblCfg);
+        TableDefinition tbl2 = SchemaConfigurationConverter.convert(tblCfg);
 
         assertEquals(tbl.canonicalName(), tbl2.canonicalName());
         assertEquals(tbl.indices().size(), tbl2.indices().size());
@@ -233,7 +264,7 @@
      * @param idxs Table indexes.
      * @return Index or {@code null} if there are no index with such name.
      */
-    private TableIndex getIdx(String name, Collection<TableIndex> idxs) {
+    private IndexDefinition getIdx(String name, Collection<IndexDefinition> idxs) {
         return idxs.stream().filter(idx -> name.equals(idx.name())).findAny().orElse(null);
     }
 }
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverterTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverterTest.java
index c51ec21..33fce5a 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverterTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverterTest.java
@@ -22,11 +22,12 @@
 import org.apache.ignite.internal.schema.Columns;
 import org.apache.ignite.internal.schema.NativeTypeSpec;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
-import org.apache.ignite.schema.builder.SchemaTableBuilder;
-import org.apache.ignite.schema.builder.TableColumnBuilder;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
+import org.apache.ignite.schema.definition.builder.ColumnDefinitionBuilder;
+import org.apache.ignite.schema.definition.builder.TableSchemaBuilder;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -43,12 +44,12 @@
      * Convert table with complex primary key and check it.
      */
     @Test
-    public void testComplexPrimaryIndex() {
-        SchemaTableBuilder bldr = getBuilder(false, false);
-        SchemaTable tblSchm = bldr.withIndex(SchemaBuilders.pkIndex()
-            .addIndexColumn("INT8").done()
-            .addIndexColumn("ID").done()
-            .build()
+    public void testComplexPrimaryKey() {
+        TableSchemaBuilder bldr = getBuilder(false, false);
+        TableDefinition tblSchm = bldr.withPrimaryKey(
+            SchemaBuilders.primaryKey()
+                .withColumns("INT8", "ID")
+                .build()
         ).build();
 
         SchemaDescriptor tblDscr = SchemaDescriptorConverter.convert(1, tblSchm);
@@ -62,13 +63,13 @@
      * Convert table with complex primary key with affinity column configured and check it.
      */
     @Test
-    public void testComplexPrimaryIndexWithAffinity() {
-        SchemaTableBuilder bldr = getBuilder(false, false);
-        SchemaTable tblSchm = bldr.withIndex(SchemaBuilders.pkIndex()
-            .addIndexColumn("INT8").done()
-            .addIndexColumn("ID").done()
-            .withAffinityColumns("INT8")
-            .build()
+    public void testComplexPrimaryKeyWithAffinity() {
+        TableSchemaBuilder bldr = getBuilder(false, false);
+        TableDefinition tblSchm = bldr.withPrimaryKey(
+            SchemaBuilders.primaryKey()
+                .withColumns("INT8", "ID")
+                .withAffinityColumns("INT8")
+                .build()
         ).build();
 
         SchemaDescriptor tblDscr = SchemaDescriptorConverter.convert(1, tblSchm);
@@ -100,7 +101,7 @@
      * @param nullable Nullable flag.
      */
     private void testConvert(boolean nullable) {
-        SchemaTable tblSchm = getBuilder(nullable, true).build();
+        TableDefinition tblSchm = getBuilder(nullable, true).build();
 
         SchemaDescriptor tblDscr = SchemaDescriptorConverter.convert(1, tblSchm);
 
@@ -125,14 +126,14 @@
     }
 
     /**
-     * Get SchemaTableBuilder with default table.
+     * Get TableSchemaBuilder with default table.
      *
      * @param nullable If all columns should be nullable.
      * @param withPk If builder should contains primary key index.
-     * @return SchemaTableBuilder.
+     * @return TableSchemaBuilder.
      */
-    private SchemaTableBuilder getBuilder(boolean nullable, boolean withPk) {
-        Function<TableColumnBuilder, org.apache.ignite.schema.Column> postProcess = builder -> {
+    private TableSchemaBuilder getBuilder(boolean nullable, boolean withPk) {
+        Function<ColumnDefinitionBuilder, ColumnDefinition> postProcess = builder -> {
             if (nullable)
                 builder.asNullable();
             else
@@ -140,7 +141,7 @@
             return builder.build();
         };
 
-        SchemaTableBuilder res = SchemaBuilders.tableBuilder("SCHEMA", "TABLE")
+        TableSchemaBuilder res = SchemaBuilders.tableBuilder("SCHEMA", "TABLE")
             .columns(
                 postProcess.apply(SchemaBuilders.column("ID", ColumnType.UUID)),
                 postProcess.apply(SchemaBuilders.column("INT8", ColumnType.INT8)),
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java b/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java
index b821f69..f6faafb 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java
@@ -21,7 +21,7 @@
 import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.lang.IgniteUuid;
-import org.apache.ignite.schema.SchemaMode;
+import org.apache.ignite.schema.definition.SchemaManagementMode;
 import org.apache.ignite.tx.Transaction;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -50,12 +50,12 @@
      *
      * @return Schema mode.
      */
-    @NotNull SchemaMode schemaMode();
+    @NotNull SchemaManagementMode schemaMode();
 
     /**
      * Sets schema mode for the table.
      */
-    void schema(SchemaMode schemaMode);
+    void schema(SchemaManagementMode schemaMode);
 
     /**
      * Asynchronously gets a row with same key columns values as given one from the table.
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java
index 11afe10..3cca8b2 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java
@@ -30,7 +30,7 @@
 import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.table.distributed.TableManager;
 import org.apache.ignite.lang.IgniteUuid;
-import org.apache.ignite.schema.SchemaMode;
+import org.apache.ignite.schema.definition.SchemaManagementMode;
 import org.apache.ignite.table.InvokeProcessor;
 import org.apache.ignite.table.KeyValueBinaryView;
 import org.apache.ignite.table.KeyValueView;
@@ -423,7 +423,7 @@
     /**
      * @param schemaMode New schema type.
      */
-    public void schemaType(SchemaMode schemaMode) {
+    public void schemaType(SchemaManagementMode schemaMode) {
         this.tbl.schema(schemaMode);
     }
 }
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 b0272e2..336768c 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
@@ -34,9 +34,10 @@
 import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.table.distributed.TableManager;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaMode;
+import org.apache.ignite.schema.definition.ColumnDefinition;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.SchemaManagementMode;
 import org.apache.ignite.table.Tuple;
 import org.jetbrains.annotations.NotNull;
 
@@ -80,7 +81,7 @@
         InternalTuple valTuple0 = toInternalTuple(schema, tuple, false);
 
         while (valTuple0.knownColumns() + keyTuple0.knownColumns() != tuple.columnCount()) {
-            if (tbl.schemaMode() == SchemaMode.STRICT_SCHEMA)
+            if (tbl.schemaMode() == SchemaManagementMode.STRICT)
                 throw new SchemaMismatchException("Value doesn't match schema.");
 
             createColumns(extractColumnsType(tuple, extraColumnNames(tuple, schema)));
@@ -110,7 +111,7 @@
             if (valTuple == null || valTuple0.knownColumns() == valTuple.columnCount())
                 break; // Nothing to do.
 
-            if (tbl.schemaMode() == SchemaMode.STRICT_SCHEMA)
+            if (tbl.schemaMode() == SchemaManagementMode.STRICT)
                 throw new SchemaMismatchException("Value doesn't match schema.");
 
             createColumns(extractColumnsType(valTuple, extraColumnNames(valTuple, false, schema)));
@@ -292,8 +293,8 @@
      * @param colNames Column names that type info to be extracted.
      * @return Column types.
      */
-    private Set<org.apache.ignite.schema.Column> extractColumnsType(Tuple tuple, Set<String> colNames) {
-        Set<org.apache.ignite.schema.Column> extraColumns = new HashSet<>();
+    private Set<ColumnDefinition> extractColumnsType(Tuple tuple, Set<String> colNames) {
+        Set<ColumnDefinition> extraColumns = new HashSet<>();
 
         for (String colName : colNames) {
             Object colValue = tuple.value(colName);
@@ -343,12 +344,12 @@
      *
      * @param newCols Columns to add.
      */
-    private void createColumns(Set<org.apache.ignite.schema.Column> newCols) {
+    private void createColumns(Set<ColumnDefinition> newCols) {
         tblMgr.alterTable(tbl.tableName(), chng -> chng.changeColumns(cols -> {
             int colIdx = chng.columns().size();
             //TODO: IGNITE-15096 avoid 'colIdx' or replace with correct last colIdx.
 
-            for (org.apache.ignite.schema.Column column : newCols) {
+            for (ColumnDefinition column : newCols) {
                 cols.create(String.valueOf(colIdx), colChg -> convert(column, colChg));
                 colIdx++;
             }
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java
index 313cb45..b6b2fb1 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java
@@ -370,12 +370,12 @@
     }
 
     /** {@inheritDoc} */
-    @Override public Table getOrCreateTable(String name, Consumer<TableChange> tableInitChange) {
-        return getOrCreateTableAsync(name, tableInitChange).join();
+    @Override public Table createTableIfNotExists(String name, Consumer<TableChange> tableInitChange) {
+        return createTableIfNotExistsAsync(name, tableInitChange).join();
     }
 
     /** {@inheritDoc} */
-    @Override public CompletableFuture<Table> getOrCreateTableAsync(String name, Consumer<TableChange> tableInitChange) {
+    @Override public CompletableFuture<Table> createTableIfNotExistsAsync(String name, Consumer<TableChange> tableInitChange) {
         return createTableAsync(name, tableInitChange, false);
     }
 
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java
index c4e6fca..ef4ad90 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java
@@ -46,7 +46,7 @@
 import org.apache.ignite.internal.table.distributed.command.response.SingleRowResponse;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.raft.client.service.RaftGroupService;
-import org.apache.ignite.schema.SchemaMode;
+import org.apache.ignite.schema.definition.SchemaManagementMode;
 import org.apache.ignite.tx.Transaction;
 import org.jetbrains.annotations.NotNull;
 
@@ -68,7 +68,7 @@
     private IgniteUuid tableId;
 
     /** Table schema mode. */
-    private volatile SchemaMode schemaMode;
+    private volatile SchemaManagementMode schemaMode;
 
     /**
      * @param tableName Table name.
@@ -87,7 +87,7 @@
         this.partitionMap = partMap;
         this.partitions = partitions;
 
-        this.schemaMode = SchemaMode.STRICT_SCHEMA;
+        this.schemaMode = SchemaManagementMode.STRICT;
     }
 
     /** {@inheritDoc} */
@@ -101,12 +101,12 @@
     }
 
     /** {@inheritDoc} */
-    @Override public SchemaMode schemaMode() {
+    @Override public SchemaManagementMode schemaMode() {
         return schemaMode;
     }
 
     /** {@inheritDoc} */
-    @Override public void schema(SchemaMode schemaMode) {
+    @Override public void schema(SchemaManagementMode schemaMode) {
         this.schemaMode = schemaMode;
     }
 
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java
index dc68ea4..7f29074 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java
@@ -39,7 +39,7 @@
 import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.table.impl.DummySchemaManagerImpl;
 import org.apache.ignite.internal.testframework.IgniteTestUtils;
-import org.apache.ignite.schema.SchemaMode;
+import org.apache.ignite.schema.definition.SchemaManagementMode;
 import org.apache.ignite.table.Tuple;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
@@ -70,7 +70,7 @@
  */
 public class MutableRowTupleAdapterTest {
     /** Mocked table. */
-    private InternalTable tbl = Mockito.when(Mockito.mock(InternalTable.class).schemaMode()).thenReturn(SchemaMode.STRICT_SCHEMA).getMock();
+    private InternalTable tbl = Mockito.when(Mockito.mock(InternalTable.class).schemaMode()).thenReturn(SchemaManagementMode.STRICT).getMock();
 
     /** Schema descriptor. */
     private SchemaDescriptor schema = new SchemaDescriptor(
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java
index d824a1c..dfade1a 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java
@@ -52,9 +52,9 @@
 import org.apache.ignite.lang.NodeStoppingException;
 import org.apache.ignite.network.ClusterNode;
 import org.apache.ignite.network.NetworkAddress;
-import org.apache.ignite.schema.ColumnType;
 import org.apache.ignite.schema.SchemaBuilders;
-import org.apache.ignite.schema.SchemaTable;
+import org.apache.ignite.schema.definition.ColumnType;
+import org.apache.ignite.schema.definition.TableDefinition;
 import org.apache.ignite.table.Table;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.AfterEach;
@@ -208,7 +208,7 @@
     public void testCreateTable() {
         CompletableFuture<TableManager> tblManagerFut = new CompletableFuture<>();
 
-        SchemaTable scmTbl = SchemaBuilders.tableBuilder("PUBLIC", DYNAMIC_TABLE_NAME).columns(
+        TableDefinition scmTbl = SchemaBuilders.tableBuilder("PUBLIC", DYNAMIC_TABLE_NAME).columns(
             SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(),
             SchemaBuilders.column("val", ColumnType.INT64).asNullable().build()
         ).withPrimaryKey("key").build();
@@ -227,7 +227,7 @@
     public void testDropTable() {
         CompletableFuture<TableManager> tblManagerFut = new CompletableFuture<>();
 
-        SchemaTable scmTbl = SchemaBuilders.tableBuilder("PUBLIC", DYNAMIC_TABLE_FOR_DROP_NAME).columns(
+        TableDefinition scmTbl = SchemaBuilders.tableBuilder("PUBLIC", DYNAMIC_TABLE_FOR_DROP_NAME).columns(
             SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(),
             SchemaBuilders.column("val", ColumnType.INT64).asNullable().build()
         ).withPrimaryKey("key").build();
@@ -250,7 +250,7 @@
     public void testGetTableDuringCreation() throws Exception {
         CompletableFuture<TableManager> tblManagerFut = new CompletableFuture<>();
 
-        SchemaTable scmTbl = SchemaBuilders.tableBuilder("PUBLIC", DYNAMIC_TABLE_FOR_DROP_NAME).columns(
+        TableDefinition scmTbl = SchemaBuilders.tableBuilder("PUBLIC", DYNAMIC_TABLE_FOR_DROP_NAME).columns(
             SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(),
             SchemaBuilders.column("val", ColumnType.INT64).asNullable().build()
         ).withPrimaryKey("key").build();
@@ -291,7 +291,7 @@
     public void testDoubledCreateTable() {
         CompletableFuture<TableManager> tblManagerFut = new CompletableFuture<>();
 
-        SchemaTable scmTbl = SchemaBuilders.tableBuilder("PUBLIC", DYNAMIC_TABLE_NAME)
+        TableDefinition scmTbl = SchemaBuilders.tableBuilder("PUBLIC", DYNAMIC_TABLE_NAME)
             .columns(
                 SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(),
                 SchemaBuilders.column("val", ColumnType.INT64).asNullable().build())
@@ -306,7 +306,7 @@
             .changeReplicas(1)
             .changePartitions(10)));
 
-        assertSame(table, tblManagerFut.join().getOrCreateTable(scmTbl.canonicalName(), tblCh -> SchemaConfigurationConverter.convert(scmTbl, tblCh)
+        assertSame(table, tblManagerFut.join().createTableIfNotExists(scmTbl.canonicalName(), tblCh -> SchemaConfigurationConverter.convert(scmTbl, tblCh)
             .changeReplicas(1)
             .changePartitions(10)));
     }
@@ -314,27 +314,27 @@
     /**
      * Instantiates Table manager and creates a table in it.
      *
-     * @param schemaTable Configuration schema for a table.
+     * @param tableDefinition Configuration schema for a table.
      * @param tblManagerFut Future for table manager.
      * @return Table.
      */
     private TableImpl mockManagersAndCreateTable(
-        SchemaTable schemaTable,
+        TableDefinition tableDefinition,
         CompletableFuture<TableManager> tblManagerFut
     ) {
-        return mockManagersAndCreateTableWithDelay(schemaTable, tblManagerFut, null);
+        return mockManagersAndCreateTableWithDelay(tableDefinition, tblManagerFut, null);
     }
 
     /**
      * Instantiates a table and prepares Table manager. When the latch would open, the method completes.
      *
-     * @param schemaTable Configuration schema for a table.
+     * @param tableDefinition Configuration schema for a table.
      * @param tblManagerFut Future for table manager.
      * @param phaser Phaser for the wait.
      * @return Table manager.
      */
     @NotNull private TableImpl mockManagersAndCreateTableWithDelay(
-        SchemaTable schemaTable,
+        TableDefinition tableDefinition,
         CompletableFuture<TableManager> tblManagerFut,
         Phaser phaser
     ) {
@@ -383,11 +383,11 @@
             int tablesBeforeCreation = tableManager.tables().size();
 
             clusterCfgMgr.configurationRegistry().getConfiguration(TablesConfiguration.KEY).tables().listen(ctx -> {
-                boolean createTbl = ctx.newValue().get(schemaTable.canonicalName()) != null &&
-                    ctx.oldValue().get(schemaTable.canonicalName()) == null;
+                boolean createTbl = ctx.newValue().get(tableDefinition.canonicalName()) != null &&
+                    ctx.oldValue().get(tableDefinition.canonicalName()) == null;
 
-                boolean dropTbl = ctx.oldValue().get(schemaTable.canonicalName()) != null &&
-                    ctx.newValue().get(schemaTable.canonicalName()) == null;
+                boolean dropTbl = ctx.oldValue().get(tableDefinition.canonicalName()) != null &&
+                    ctx.newValue().get(tableDefinition.canonicalName()) == null;
 
                 if (!createTbl && !dropTbl)
                     return CompletableFuture.completedFuture(null);
@@ -407,7 +407,7 @@
 
                         when(mockEntry.key()).thenReturn(new ByteArray(PUBLIC_PREFIX + "uuid." + NamedListNode.NAME));
 
-                        when(mockEntry.value()).thenReturn(ByteUtils.toBytes(schemaTable.canonicalName()));
+                        when(mockEntry.value()).thenReturn(ByteUtils.toBytes(tableDefinition.canonicalName()));
 
                         when(cursor.next()).thenReturn(mockEntry);
 
@@ -426,7 +426,7 @@
                 return CompletableFuture.completedFuture(null);
             });
 
-            tbl2 = (TableImpl)tableManager.createTable(schemaTable.canonicalName(), tblCh -> SchemaConfigurationConverter.convert(schemaTable, tblCh)
+            tbl2 = (TableImpl)tableManager.createTable(tableDefinition.canonicalName(), tblCh -> SchemaConfigurationConverter.convert(tableDefinition, tblCh)
                 .changeReplicas(1)
                 .changePartitions(10)
             );
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummyInternalTableImpl.java b/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummyInternalTableImpl.java
index 660467d..eceb875 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummyInternalTableImpl.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummyInternalTableImpl.java
@@ -29,7 +29,7 @@
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.table.InternalTable;
 import org.apache.ignite.lang.IgniteUuid;
-import org.apache.ignite.schema.SchemaMode;
+import org.apache.ignite.schema.definition.SchemaManagementMode;
 import org.apache.ignite.tx.Transaction;
 import org.jetbrains.annotations.NotNull;
 
@@ -91,12 +91,12 @@
     }
 
     /** {@inheritDoc} */
-    @Override public @NotNull SchemaMode schemaMode() {
-        return SchemaMode.STRICT_SCHEMA;
+    @Override public @NotNull SchemaManagementMode schemaMode() {
+        return SchemaManagementMode.STRICT;
     }
 
     /** {@inheritDoc} */
-    @Override public void schema(SchemaMode schemaMode) {
+    @Override public void schema(SchemaManagementMode schemaMode) {
     }
 
     /** {@inheritDoc} */
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/type/NumericTypesSerializerTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/type/NumericTypesSerializerTest.java
index 3271612..56346af 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/type/NumericTypesSerializerTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/type/NumericTypesSerializerTest.java
@@ -35,7 +35,7 @@
 import org.apache.ignite.internal.table.TupleMarshallerImpl;
 import org.apache.ignite.internal.table.impl.DummySchemaManagerImpl;
 import org.apache.ignite.internal.util.Pair;
-import org.apache.ignite.schema.SchemaMode;
+import org.apache.ignite.schema.definition.SchemaManagementMode;
 import org.apache.ignite.table.Tuple;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.BeforeEach;
@@ -59,7 +59,7 @@
     private SchemaDescriptor schema;
 
     /** Mocked table. */
-    private InternalTable tbl = Mockito.when(Mockito.mock(InternalTable.class).schemaMode()).thenReturn(SchemaMode.STRICT_SCHEMA).getMock();
+    private InternalTable tbl = Mockito.when(Mockito.mock(InternalTable.class).schemaMode()).thenReturn(SchemaManagementMode.STRICT).getMock();
 
     /**
      * @return List of BigInteger pairs for test.