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

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

commit de2f6f45a5f84ea44dd010fcec70244a20f5c6db
Author: amashenkov <andrey.mashen...@gmail.com>
AuthorDate: Wed May 17 22:39:25 2023 +0300

    Add create index command.
    Add drop index command.
---
 .../ignite/internal/catalog/CatalogManager.java    |  18 ++++
 .../ignite/internal/catalog/CatalogService.java    |   2 +
 .../internal/catalog/CatalogServiceImpl.java       |  87 +++++++++++++++
 ...Params.java => AbstractIndexCommandParams.java} |  60 +++++++----
 .../commands/AbstractTableCommandParams.java       |  10 +-
 .../internal/catalog/commands/CatalogUtils.java    |  34 ++++++
 .../catalog/commands/CreateIndexParams.java        | 118 ++++++++++++++++++++
 .../internal/catalog/commands/DropIndexParams.java |  36 +++++++
 .../catalog/descriptors/HashIndexDescriptor.java   |   5 +-
 .../catalog/descriptors/IndexDescriptor.java       |   2 +-
 .../catalog/descriptors/SortedIndexDescriptor.java |   5 +-
 .../catalog/events/CreateIndexEventParameters.java |  47 ++++++++
 .../catalog/events/DropIndexEventParameters.java   |  43 ++++++++
 .../DropIndexEntry.java}                           |  45 +++-----
 .../NewIndexEntry.java}                            |  46 ++++----
 .../internal/catalog/CatalogServiceSelfTest.java   | 120 +++++++++++++++++++++
 .../engine/exec/ddl/DdlCommandHandlerWrapper.java  |  14 +++
 .../exec/ddl/DdlToCatalogCommandConverter.java     |  45 ++++++++
 .../distributed/schema/FullTableSchemaTest.java    |   2 +-
 19 files changed, 654 insertions(+), 85 deletions(-)

diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogManager.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogManager.java
index 2724d5d965..72da2432d1 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogManager.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogManager.java
@@ -20,7 +20,9 @@ package org.apache.ignite.internal.catalog;
 import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.catalog.commands.AlterTableAddColumnParams;
 import org.apache.ignite.internal.catalog.commands.AlterTableDropColumnParams;
+import org.apache.ignite.internal.catalog.commands.CreateIndexParams;
 import org.apache.ignite.internal.catalog.commands.CreateTableParams;
+import org.apache.ignite.internal.catalog.commands.DropIndexParams;
 import org.apache.ignite.internal.catalog.commands.DropTableParams;
 import org.apache.ignite.internal.manager.IgniteComponent;
 
@@ -59,4 +61,20 @@ public interface CatalogManager extends IgniteComponent, 
CatalogService {
      * @return Operation future.
      */
     CompletableFuture<Void> dropColumn(AlterTableDropColumnParams params);
+
+    /**
+     * Creates new index.
+     *
+     * @param params Parameters.
+     * @return Operation future.
+     */
+    CompletableFuture<Void> createIndex(CreateIndexParams params);
+
+    /**
+     * Drops index.
+     *
+     * @param params Parameters.
+     * @return Operation future.
+     */
+    CompletableFuture<Void> dropIndex(DropIndexParams params);
 }
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
index 70e70aaf38..629078cdfc 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
@@ -41,6 +41,8 @@ public interface CatalogService {
 
     TableDescriptor table(int tableId, long timestamp);
 
+    IndexDescriptor index(String indexName, long timestamp);
+
     IndexDescriptor index(int indexId, long timestamp);
 
     Collection<IndexDescriptor> tableIndexes(int tableId, long timestamp);
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogServiceImpl.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogServiceImpl.java
index 4920647d4a..d3570ec8c3 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogServiceImpl.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogServiceImpl.java
@@ -32,7 +32,9 @@ import java.util.concurrent.ConcurrentSkipListMap;
 import org.apache.ignite.internal.catalog.commands.AlterTableAddColumnParams;
 import org.apache.ignite.internal.catalog.commands.AlterTableDropColumnParams;
 import org.apache.ignite.internal.catalog.commands.CatalogUtils;
+import org.apache.ignite.internal.catalog.commands.CreateIndexParams;
 import org.apache.ignite.internal.catalog.commands.CreateTableParams;
+import org.apache.ignite.internal.catalog.commands.DropIndexParams;
 import org.apache.ignite.internal.catalog.commands.DropTableParams;
 import org.apache.ignite.internal.catalog.descriptors.IndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.SchemaDescriptor;
@@ -41,7 +43,9 @@ import org.apache.ignite.internal.catalog.events.CatalogEvent;
 import org.apache.ignite.internal.catalog.events.CatalogEventParameters;
 import org.apache.ignite.internal.catalog.events.CreateTableEventParameters;
 import org.apache.ignite.internal.catalog.events.DropTableEventParameters;
+import org.apache.ignite.internal.catalog.storage.DropIndexEntry;
 import org.apache.ignite.internal.catalog.storage.DropTableEntry;
+import org.apache.ignite.internal.catalog.storage.NewIndexEntry;
 import org.apache.ignite.internal.catalog.storage.NewTableEntry;
 import org.apache.ignite.internal.catalog.storage.ObjectIdGenUpdateEntry;
 import org.apache.ignite.internal.catalog.storage.UpdateEntry;
@@ -55,6 +59,8 @@ import org.apache.ignite.internal.util.ArrayUtils;
 import org.apache.ignite.internal.util.PendingComparableValuesTracker;
 import org.apache.ignite.lang.ErrorGroups.Common;
 import org.apache.ignite.lang.IgniteInternalException;
+import org.apache.ignite.lang.IndexAlreadyExistsException;
+import org.apache.ignite.lang.IndexNotFoundException;
 import org.apache.ignite.lang.TableAlreadyExistsException;
 import org.apache.ignite.lang.TableNotFoundException;
 import org.jetbrains.annotations.Nullable;
@@ -117,6 +123,12 @@ public class CatalogServiceImpl extends 
Producer<CatalogEvent, CatalogEventParam
         return catalogAt(timestamp).table(tableId);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public IndexDescriptor index(String indexName, long timestamp) {
+        return catalogAt(timestamp).schema(PUBLIC).index(indexName);
+    }
+
     /** {@inheritDoc} */
     @Override
     public IndexDescriptor index(int indexId, long timestamp) {
@@ -214,6 +226,53 @@ public class CatalogServiceImpl extends 
Producer<CatalogEvent, CatalogEventParam
         return failedFuture(new UnsupportedOperationException("Not implemented 
yet."));
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public CompletableFuture<Void> createIndex(CreateIndexParams params) {
+        return saveUpdate(catalog -> {
+            String schemaName = 
Objects.requireNonNullElse(params.schemaName(), CatalogService.PUBLIC);
+
+            SchemaDescriptor schema = 
Objects.requireNonNull(catalog.schema(schemaName), "No schema found: " + 
schemaName);
+
+            if (schema.index(params.indexName()) != null) {
+                throw new IndexAlreadyExistsException(schemaName, 
params.indexName());
+            }
+
+            TableDescriptor table = schema.table(params.tableName());
+
+            if (table == null) {
+                throw new TableNotFoundException(schemaName, 
params.tableName());
+            }
+
+            IndexDescriptor index = 
CatalogUtils.fromParams(catalog.objectIdGenState(), table.id(), params);
+
+            return List.of(
+                    new NewIndexEntry(index),
+                    new ObjectIdGenUpdateEntry(1)
+            );
+        });
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public CompletableFuture<Void> dropIndex(DropIndexParams params) {
+        return saveUpdate(catalog -> {
+            String schemaName = 
Objects.requireNonNullElse(params.schemaName(), CatalogService.PUBLIC);
+
+            SchemaDescriptor schema = 
Objects.requireNonNull(catalog.schema(schemaName), "No schema found: " + 
schemaName);
+
+            IndexDescriptor index = schema.index(params.indexName());
+
+            if (index == null) {
+                throw new IndexNotFoundException(schemaName, 
params.indexName());
+            }
+
+            return List.of(
+                    new DropIndexEntry(index.id())
+            );
+        });
+    }
+
     private void registerCatalog(Catalog newCatalog) {
         catalogByVer.put(newCatalog.version(), newCatalog);
         catalogByTs.put(newCatalog.time(), newCatalog);
@@ -308,6 +367,34 @@ public class CatalogServiceImpl extends 
Producer<CatalogEvent, CatalogEventParam
                             new DropTableEventParameters(version, tableId)
                     ));
 
+                } else if (entry instanceof NewIndexEntry) {
+                    catalog = new Catalog(
+                            version,
+                            System.currentTimeMillis(),
+                            catalog.objectIdGenState(),
+                            new SchemaDescriptor(
+                                    schema.id(),
+                                    schema.name(),
+                                    version,
+                                    schema.tables(),
+                                    ArrayUtils.concat(schema.indexes(), 
((NewIndexEntry) entry).descriptor())
+                            )
+                    );
+                } else if (entry instanceof DropIndexEntry) {
+                    int indexId = ((DropIndexEntry) entry).indexId();
+
+                    catalog = new Catalog(
+                            version,
+                            System.currentTimeMillis(),
+                            catalog.objectIdGenState(),
+                            new SchemaDescriptor(
+                                    schema.id(),
+                                    schema.name(),
+                                    version,
+                                    schema.tables(),
+                                    Arrays.stream(schema.indexes()).filter(t 
-> t.id() != indexId).toArray(IndexDescriptor[]::new)
+                            )
+                    );
                 } else if (entry instanceof ObjectIdGenUpdateEntry) {
                     catalog = new Catalog(
                             version,
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AbstractTableCommandParams.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AbstractIndexCommandParams.java
similarity index 62%
copy from 
modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AbstractTableCommandParams.java
copy to 
modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AbstractIndexCommandParams.java
index 0aa2b8ecfc..681fb51293 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AbstractTableCommandParams.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AbstractIndexCommandParams.java
@@ -18,37 +18,46 @@
 package org.apache.ignite.internal.catalog.commands;
 
 /**
- * Abstract table ddl command.
+ * Abstract index ddl command.
  */
-public class AbstractTableCommandParams implements DdlCommandParams {
-    /** Table name. */
-    protected String tableName;
+public class AbstractIndexCommandParams implements DdlCommandParams {
+    /** Index name. */
+    protected String indexName;
 
-    /** Quietly ignore this command if table is not exists. */
-    protected boolean ifTableExists;
-
-    /** Schema name where this new table will be created. */
+    /** Schema name where this new index will be created. */
     protected String schema;
 
-    public String tableName() {
-        return tableName;
+    /** Unique index flag. */
+    protected boolean unique;
+
+    /** Quietly ignore this command if index existence check failed. */
+    protected boolean ifIndexExists;
+
+    /**
+     * Returns index simple name.
+     */
+    public String indexName() {
+        return indexName;
     }
 
+    /**
+     * Returns schema name.
+     */
     public String schemaName() {
         return schema;
     }
 
     /**
-     * Quietly ignore if table is not exist.
+     * Returns {@code true} if index is unique, {@code false} otherwise.
      */
-    public boolean ifTableExists() {
-        return ifTableExists;
+    public boolean isUnique() {
+        return unique;
     }
 
     /**
      * Parameters builder.
      */
-    protected abstract static class AbstractBuilder<ParamT extends 
AbstractTableCommandParams, BuilderT> {
+    protected abstract static class AbstractBuilder<ParamT extends 
AbstractIndexCommandParams, BuilderT> {
         protected ParamT params;
 
         AbstractBuilder(ParamT params) {
@@ -67,23 +76,32 @@ public class AbstractTableCommandParams implements 
DdlCommandParams {
         }
 
         /**
-         * Sets table schema.
+         * Sets index simple name.
          *
-         * @param tableName Table name.
+         * @param indexName Index simple name.
          * @return {@code this}.
          */
-        public BuilderT tableName(String tableName) {
-            params.tableName = tableName;
+        public BuilderT indexName(String indexName) {
+            params.indexName = indexName;
             return (BuilderT) this;
         }
 
         /**
          * Set quietly ignore flag.
          *
-         * @param ifTableNotExists Flag.
+         * @param ifIndexExists Flag.
+         */
+        public BuilderT ifIndexExists(boolean ifIndexExists) {
+            params.ifIndexExists = ifIndexExists;
+
+            return (BuilderT) this;
+        }
+
+        /**
+         * Sets unique flag.
          */
-        public BuilderT ifTableExists(boolean ifTableNotExists) {
-            params.ifTableExists = ifTableNotExists;
+        public BuilderT unique() {
+            params.unique = true;
 
             return (BuilderT) this;
         }
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AbstractTableCommandParams.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AbstractTableCommandParams.java
index 0aa2b8ecfc..d42f6b2463 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AbstractTableCommandParams.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AbstractTableCommandParams.java
@@ -30,10 +30,16 @@ public class AbstractTableCommandParams implements 
DdlCommandParams {
     /** Schema name where this new table will be created. */
     protected String schema;
 
+    /**
+     * Returns table simple name.
+     */
     public String tableName() {
         return tableName;
     }
 
+    /**
+     * Returns schema name.
+     */
     public String schemaName() {
         return schema;
     }
@@ -67,9 +73,9 @@ public class AbstractTableCommandParams implements 
DdlCommandParams {
         }
 
         /**
-         * Sets table schema.
+         * Sets table simple name.
          *
-         * @param tableName Table name.
+         * @param tableName Table simple name.
          * @return {@code this}.
          */
         public BuilderT tableName(String tableName) {
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
index 1ead944291..991c90f2ae 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
@@ -17,7 +17,13 @@
 
 package org.apache.ignite.internal.catalog.commands;
 
+import java.util.List;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import org.apache.ignite.internal.catalog.descriptors.HashIndexDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.IndexColumnDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.IndexDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.SortedIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.TableColumnDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.TableDescriptor;
 
@@ -41,6 +47,34 @@ public class CatalogUtils {
         );
     }
 
+    /**
+     * Converts CreateIndex command params to descriptor.
+     *
+     * @param id Index id.
+     * @param tableId Table id.
+     * @param params Parameters.
+     * @return Index descriptor.
+     */
+    public static IndexDescriptor fromParams(int id, int tableId, 
CreateIndexParams params) {
+        switch (params.type()) {
+            case HASH:
+                return new HashIndexDescriptor(id,
+                        params.indexName(),
+                        tableId,
+                        params.isUnique(),
+                        params.columns()
+                );
+            case SORTED:
+                List<IndexColumnDescriptor> columnDescriptors = 
IntStream.range(0, params.collations().size())
+                        .mapToObj(i -> new 
IndexColumnDescriptor(params.columns().get(i), params.collations().get(i)))
+                        .collect(Collectors.toList());
+                return new SortedIndexDescriptor(id, params.indexName(), 
tableId, params.isUnique(), columnDescriptors);
+            default:
+                throw new IllegalArgumentException("Unsupported index type: " 
+ params.type());
+        }
+
+    }
+
     private static TableColumnDescriptor fromParams(ColumnParams params) {
         return new TableColumnDescriptor(params.name(), params.type(), 
params.nullable(), params.defaultValueDefinition());
     }
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateIndexParams.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateIndexParams.java
new file mode 100644
index 0000000000..c3212cf338
--- /dev/null
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateIndexParams.java
@@ -0,0 +1,118 @@
+/*
+ * 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.catalog.commands;
+
+import java.util.List;
+import org.apache.ignite.internal.catalog.descriptors.ColumnCollation;
+
+/**
+ * CREATE INDEX statement.
+ */
+public class CreateIndexParams extends AbstractIndexCommandParams {
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /** Type of the index to create. */
+    public enum Type {
+        SORTED, HASH
+    }
+
+    /** Table name. */
+    private String tableName;
+
+    private Type type;
+
+    private List<String> columns;
+
+    private List<ColumnCollation> collations;
+
+    public List<String> columns() {
+        return columns;
+    }
+
+    public List<ColumnCollation> collations() {
+        return collations;
+    }
+
+    public Type type() {
+        return type;
+    }
+
+    public String tableName() {
+        return tableName;
+    }
+
+    /**
+     * Parameters builder.
+     */
+    public static class Builder extends 
AbstractIndexCommandParams.AbstractBuilder<CreateIndexParams, 
CreateIndexParams.Builder> {
+        private Builder() {
+            super(new CreateIndexParams());
+        }
+
+        /**
+         * Set index type.
+         *
+         * @param type Index type.
+         * @return {@code this}.
+         */
+        public Builder type(Type type) {
+            params.type = type;
+
+            return this;
+        }
+
+        /**
+         * Set table name.
+         *
+         * @param tableName Table name.
+         * @return {@code this}.
+         */
+        public Builder tableName(String tableName) {
+            params.tableName = tableName;
+
+            return this;
+        }
+
+        /**
+         * Set columns names.
+         *
+         * @param columns Columns names.
+         * @return {@code this}.
+         */
+        public Builder columns(List<String> columns) {
+            params.columns = columns;
+
+            return this;
+        }
+
+        /**
+         * Set columns collations.
+         *
+         * @param collations Columns collations.
+         * @return {@code this}.
+         */
+        public Builder collations(List<ColumnCollation> collations) {
+            params.collations = collations;
+
+            return this;
+        }
+
+    }
+}
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DropIndexParams.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DropIndexParams.java
new file mode 100644
index 0000000000..aeefaabb1c
--- /dev/null
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DropIndexParams.java
@@ -0,0 +1,36 @@
+/*
+ * 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.catalog.commands;
+
+/**
+ * DROP INDEX statement.
+ */
+public class DropIndexParams extends AbstractIndexCommandParams {
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Parameters builder.
+     */
+    public static class Builder extends AbstractBuilder<DropIndexParams, 
Builder> {
+        Builder() {
+            super(new DropIndexParams());
+        }
+    }
+}
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/HashIndexDescriptor.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/HashIndexDescriptor.java
index 8e2d96c3da..f486a5bdfc 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/HashIndexDescriptor.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/HashIndexDescriptor.java
@@ -36,11 +36,12 @@ public class HashIndexDescriptor extends IndexDescriptor {
      * @param id Id of the index.
      * @param name Name of the index.
      * @param tableId Id of the table index belongs to.
+     * @param unique Unique flag.
      * @param columns A list of indexed columns. Must not contains duplicates.
      * @throws IllegalArgumentException If columns list contains duplicates.
      */
-    public HashIndexDescriptor(int id, String name, int tableId, List<String> 
columns) {
-        super(id, name, tableId, true);
+    public HashIndexDescriptor(int id, String name, int tableId, boolean 
unique, List<String> columns) {
+        super(id, name, tableId, unique);
 
         this.columns = List.copyOf(Objects.requireNonNull(columns, "columns"));
 
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/IndexDescriptor.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/IndexDescriptor.java
index 99feaf15e3..cf9609162d 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/IndexDescriptor.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/IndexDescriptor.java
@@ -29,7 +29,7 @@ public abstract class IndexDescriptor extends 
ObjectDescriptor {
     private final int tableId;
 
     /** Unique constraint flag. */
-    private boolean unique;
+    private final boolean unique;
 
     /** Write only flag. {@code True} when index is building. */
     private boolean writeOnly;
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/SortedIndexDescriptor.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/SortedIndexDescriptor.java
index cfc59ee4c4..c2fb6016ec 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/SortedIndexDescriptor.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/SortedIndexDescriptor.java
@@ -36,11 +36,12 @@ public class SortedIndexDescriptor extends IndexDescriptor {
      * @param id Id of the index.
      * @param name Name of the index.
      * @param tableId Id of the table index belongs to.
+     * @param unique Unique flag.
      * @param columns A list of columns descriptors.
      * @throws IllegalArgumentException If columns list contains duplicates or 
columns size doesn't match the collations size.
      */
-    public SortedIndexDescriptor(int id, String name, int tableId, 
List<IndexColumnDescriptor> columns) {
-        super(id, name, tableId, false);
+    public SortedIndexDescriptor(int id, String name, int tableId, boolean 
unique, List<IndexColumnDescriptor> columns) {
+        super(id, name, tableId, unique);
 
         this.columns = Objects.requireNonNull(columns, "columns");
     }
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/CreateIndexEventParameters.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/CreateIndexEventParameters.java
new file mode 100644
index 0000000000..673834eac7
--- /dev/null
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/CreateIndexEventParameters.java
@@ -0,0 +1,47 @@
+/*
+ * 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.catalog.events;
+
+import org.apache.ignite.internal.catalog.descriptors.IndexDescriptor;
+
+/**
+ * Create index event parameters contains a index descriptor for newly created 
index.
+ */
+public class CreateIndexEventParameters extends CatalogEventParameters {
+
+    private final IndexDescriptor indexDescriptor;
+
+    /**
+     * Constructor.
+     *
+     * @param causalityToken Causality token.
+     * @param indexDescriptor Newly created index descriptor.
+     */
+    public CreateIndexEventParameters(long causalityToken, IndexDescriptor 
indexDescriptor) {
+        super(causalityToken);
+
+        this.indexDescriptor = indexDescriptor;
+    }
+
+    /**
+     * Gets index descriptor for newly created index.
+     */
+    public IndexDescriptor indexDescriptor() {
+        return indexDescriptor;
+    }
+}
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/DropIndexEventParameters.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/DropIndexEventParameters.java
new file mode 100644
index 0000000000..0a79fe625e
--- /dev/null
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/DropIndexEventParameters.java
@@ -0,0 +1,43 @@
+/*
+ * 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.catalog.events;
+
+/**
+ * Drop index event parameters contains an id of dropped index.
+ */
+public class DropIndexEventParameters extends CatalogEventParameters {
+
+    private final int indexId;
+
+    /**
+     * Constructor.
+     *
+     * @param causalityToken Causality token.
+     * @param indexId An id of dropped index.
+     */
+    public DropIndexEventParameters(long causalityToken, int indexId) {
+        super(causalityToken);
+
+        this.indexId = indexId;
+    }
+
+    /** Returns an id of dropped index. */
+    public int indexId() {
+        return indexId;
+    }
+}
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/IndexDescriptor.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/DropIndexEntry.java
similarity index 55%
copy from 
modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/IndexDescriptor.java
copy to 
modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/DropIndexEntry.java
index 99feaf15e3..4336b74a9e 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/IndexDescriptor.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/DropIndexEntry.java
@@ -15,41 +15,30 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.catalog.descriptors;
+package org.apache.ignite.internal.catalog.storage;
 
 import org.apache.ignite.internal.tostring.S;
 
 /**
- * Index descriptor base class.
+ * Describes deletion of a index.
  */
-public abstract class IndexDescriptor extends ObjectDescriptor {
-    private static final long serialVersionUID = -8045949593661301287L;
-
-    /** Table id. */
-    private final int tableId;
-
-    /** Unique constraint flag. */
-    private boolean unique;
-
-    /** Write only flag. {@code True} when index is building. */
-    private boolean writeOnly;
-
-    IndexDescriptor(int id, String name, int tableId, boolean unique) {
-        super(id, Type.INDEX, name);
-        this.tableId = tableId;
-        this.unique = unique;
-    }
-
-    public int tableId() {
-        return tableId;
-    }
-
-    public boolean unique() {
-        return unique;
+public class DropIndexEntry implements UpdateEntry {
+    private static final long serialVersionUID = -604729846502020728L;
+
+    private final int indexId;
+
+    /**
+     * Constructs the object.
+     *
+     * @param indexId An id of a index to drop.
+     */
+    public DropIndexEntry(int indexId) {
+        this.indexId = indexId;
     }
 
-    public boolean writeOnly() {
-        return writeOnly;
+    /** Returns an id of a index to drop. */
+    public int indexId() {
+        return indexId;
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/IndexDescriptor.java
 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/NewIndexEntry.java
similarity index 55%
copy from 
modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/IndexDescriptor.java
copy to 
modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/NewIndexEntry.java
index 99feaf15e3..1d67e7631a 100644
--- 
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/IndexDescriptor.java
+++ 
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/NewIndexEntry.java
@@ -15,41 +15,31 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.catalog.descriptors;
+package org.apache.ignite.internal.catalog.storage;
 
+import org.apache.ignite.internal.catalog.descriptors.IndexDescriptor;
 import org.apache.ignite.internal.tostring.S;
 
 /**
- * Index descriptor base class.
+ * Describes addition of a new index.
  */
-public abstract class IndexDescriptor extends ObjectDescriptor {
-    private static final long serialVersionUID = -8045949593661301287L;
-
-    /** Table id. */
-    private final int tableId;
-
-    /** Unique constraint flag. */
-    private boolean unique;
-
-    /** Write only flag. {@code True} when index is building. */
-    private boolean writeOnly;
-
-    IndexDescriptor(int id, String name, int tableId, boolean unique) {
-        super(id, Type.INDEX, name);
-        this.tableId = tableId;
-        this.unique = unique;
-    }
-
-    public int tableId() {
-        return tableId;
-    }
-
-    public boolean unique() {
-        return unique;
+public class NewIndexEntry implements UpdateEntry {
+    private static final long serialVersionUID = 6717363577013237711L;
+
+    private final IndexDescriptor descriptor;
+
+    /**
+     * Constructs the object.
+     *
+     * @param descriptor A descriptor of a index to add.
+     */
+    public NewIndexEntry(IndexDescriptor descriptor) {
+        this.descriptor = descriptor;
     }
 
-    public boolean writeOnly() {
-        return writeOnly;
+    /** Returns descriptor of a index to add. */
+    public IndexDescriptor descriptor() {
+        return descriptor;
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogServiceSelfTest.java
 
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogServiceSelfTest.java
index 003ab864f1..a108bd4e6b 100644
--- 
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogServiceSelfTest.java
+++ 
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogServiceSelfTest.java
@@ -23,11 +23,13 @@ import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutur
 import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willBe;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNotSame;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.times;
@@ -38,10 +40,15 @@ import static org.mockito.Mockito.when;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.catalog.commands.ColumnParams;
+import org.apache.ignite.internal.catalog.commands.CreateIndexParams;
+import org.apache.ignite.internal.catalog.commands.CreateIndexParams.Type;
 import org.apache.ignite.internal.catalog.commands.CreateTableParams;
 import org.apache.ignite.internal.catalog.commands.DefaultValue;
 import org.apache.ignite.internal.catalog.commands.DropTableParams;
+import org.apache.ignite.internal.catalog.descriptors.ColumnCollation;
+import org.apache.ignite.internal.catalog.descriptors.HashIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.SchemaDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.SortedIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.TableDescriptor;
 import org.apache.ignite.internal.catalog.events.CatalogEvent;
 import org.apache.ignite.internal.catalog.events.CatalogEventParameters;
@@ -59,6 +66,7 @@ import 
org.apache.ignite.internal.metastorage.server.SimpleInMemoryKeyValueStora
 import org.apache.ignite.internal.vault.VaultManager;
 import org.apache.ignite.internal.vault.inmemory.InMemoryVaultService;
 import org.apache.ignite.lang.IgniteInternalException;
+import org.apache.ignite.lang.IndexAlreadyExistsException;
 import org.apache.ignite.lang.NodeStoppingException;
 import org.apache.ignite.lang.TableAlreadyExistsException;
 import org.apache.ignite.lang.TableNotFoundException;
@@ -76,6 +84,7 @@ import org.mockito.Mockito;
 public class CatalogServiceSelfTest {
     private static final String TABLE_NAME = "myTable";
     private static final String TABLE_NAME_2 = "myTable2";
+    private static final String INDEX_NAME = "myIndex";
 
     private MetaStorageManager metastore;
 
@@ -305,6 +314,117 @@ public class CatalogServiceSelfTest {
         assertThat(service.dropTable(params), 
willThrowFast(TableNotFoundException.class));
     }
 
+    @Test
+    public void testCreateHashIndex() {
+        assertThat(service.createTable(simpleTable(TABLE_NAME)), 
willBe((Object) null));
+
+        CreateIndexParams params = CreateIndexParams.builder()
+                .indexName(INDEX_NAME)
+                .tableName(TABLE_NAME)
+                .type(Type.HASH)
+                .columns(List.of("VAL", "ID"))
+                .build();
+
+        assertThat(service.createIndex(params), willBe((Object) null));
+
+        // Validate catalog version from the past.
+        SchemaDescriptor schema = service.schema(1);
+
+        assertNotNull(schema);
+        assertNull(schema.index(INDEX_NAME));
+        assertNull(service.index(INDEX_NAME, 123L));
+        assertNull(service.index(2, 123L));
+
+        // Validate actual catalog
+        schema = service.schema(2);
+
+        assertNotNull(schema);
+        assertNull(service.index(1, System.currentTimeMillis()));
+        assertSame(schema.index(INDEX_NAME), service.index(INDEX_NAME, 
System.currentTimeMillis()));
+        assertSame(schema.index(INDEX_NAME), service.index(2, 
System.currentTimeMillis()));
+
+        // Validate newly created hash index
+        HashIndexDescriptor index = (HashIndexDescriptor) 
schema.index(INDEX_NAME);
+
+        assertEquals(2L, index.id());
+        assertEquals(INDEX_NAME, index.name());
+        assertEquals(schema.table(TABLE_NAME).id(), index.tableId());
+        assertEquals(List.of("VAL", "ID"), index.columns());
+        assertFalse(index.unique());
+        assertFalse(index.writeOnly());
+    }
+
+    @Test
+    public void testCreateSortedIndex() {
+        assertThat(service.createTable(simpleTable(TABLE_NAME)), 
willBe((Object) null));
+
+        CreateIndexParams params = CreateIndexParams.builder()
+                .indexName(INDEX_NAME)
+                .tableName(TABLE_NAME)
+                .type(Type.SORTED)
+                .unique()
+                .columns(List.of("VAL", "ID"))
+                .collations(List.of(ColumnCollation.DESC_NULLS_FIRST, 
ColumnCollation.ASC_NULLS_LAST))
+                .build();
+
+        assertThat(service.createIndex(params), willBe((Object) null));
+
+        // Validate catalog version from the past.
+        SchemaDescriptor schema = service.schema(1);
+
+        assertNotNull(schema);
+        assertNull(schema.index(INDEX_NAME));
+        assertNull(service.index(INDEX_NAME, 123L));
+        assertNull(service.index(2, 123L));
+
+        // Validate actual catalog
+        schema = service.schema(2);
+
+        assertNotNull(schema);
+        assertNull(service.index(1, System.currentTimeMillis()));
+        assertSame(schema.index(INDEX_NAME), service.index(INDEX_NAME, 
System.currentTimeMillis()));
+        assertSame(schema.index(INDEX_NAME), service.index(2, 
System.currentTimeMillis()));
+
+        // Validate newly created sorted index
+        SortedIndexDescriptor index = (SortedIndexDescriptor) 
schema.index(INDEX_NAME);
+
+        assertEquals(2L, index.id());
+        assertEquals(INDEX_NAME, index.name());
+        assertEquals(schema.table(TABLE_NAME).id(), index.tableId());
+        assertEquals("VAL", index.columns().get(0).name());
+        assertEquals("ID", index.columns().get(1).name());
+        assertEquals(ColumnCollation.DESC_NULLS_FIRST, 
index.columns().get(0).collation());
+        assertEquals(ColumnCollation.ASC_NULLS_LAST, 
index.columns().get(1).collation());
+        assertTrue(index.unique());
+        assertFalse(index.writeOnly());
+    }
+
+    @Test
+    public void testCreateIndexIfExistsFlag() {
+        assertThat(service.createTable(simpleTable(TABLE_NAME)), 
willBe((Object) null));
+
+        CreateIndexParams params = CreateIndexParams.builder()
+                .indexName(INDEX_NAME)
+                .tableName(TABLE_NAME)
+                .type(Type.HASH)
+                .columns(List.of("VAL"))
+                .ifIndexExists(true)
+                .build();
+
+        assertThat(service.createIndex(params), willBe((Object) null));
+        assertThat(service.createIndex(params), 
willThrow(IndexAlreadyExistsException.class));
+
+        params = CreateIndexParams.builder()
+                .indexName(INDEX_NAME)
+                .tableName(TABLE_NAME)
+                .type(Type.HASH)
+                .columns(List.of("VAL"))
+                .ifIndexExists(false)
+                .build();
+
+        assertThat(service.createIndex(params), 
willThrow(IndexAlreadyExistsException.class));
+    }
+
     @Test
     public void operationWillBeRetriedFiniteAmountOfTimes() {
         UpdateLog updateLogMock = Mockito.mock(UpdateLog.class);
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandlerWrapper.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandlerWrapper.java
index 21f39ea169..2a427d4619 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandlerWrapper.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandlerWrapper.java
@@ -22,11 +22,15 @@ import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.catalog.CatalogManager;
 import org.apache.ignite.internal.distributionzones.DistributionZoneManager;
 import org.apache.ignite.internal.index.IndexManager;
+import org.apache.ignite.internal.sql.engine.prepare.ddl.CreateIndexCommand;
 import org.apache.ignite.internal.sql.engine.prepare.ddl.CreateTableCommand;
 import org.apache.ignite.internal.sql.engine.prepare.ddl.DdlCommand;
+import org.apache.ignite.internal.sql.engine.prepare.ddl.DropIndexCommand;
 import org.apache.ignite.internal.sql.engine.prepare.ddl.DropTableCommand;
 import org.apache.ignite.internal.storage.DataStorageManager;
 import org.apache.ignite.internal.table.distributed.TableManager;
+import org.apache.ignite.lang.IndexAlreadyExistsException;
+import org.apache.ignite.lang.IndexNotFoundException;
 import org.apache.ignite.lang.TableAlreadyExistsException;
 import org.apache.ignite.lang.TableNotFoundException;
 
@@ -70,6 +74,16 @@ public class DdlCommandHandlerWrapper extends 
DdlCommandHandler {
                     .thenCompose(res -> 
catalogManager.dropTable(DdlToCatalogCommandConverter.convert((DropTableCommand)
 cmd))
                             
.handle(handleModificationResult(((DropTableCommand) cmd).ifTableExists(), 
TableNotFoundException.class))
                     );
+        } else if (cmd instanceof CreateIndexCommand) {
+            return ddlCommandFuture
+                    .thenCompose(res -> 
catalogManager.createIndex(DdlToCatalogCommandConverter.convert((CreateIndexCommand)
 cmd))
+                            
.handle(handleModificationResult(((CreateIndexCommand) cmd).ifNotExists(), 
IndexAlreadyExistsException.class))
+                    );
+        } else if (cmd instanceof DropIndexCommand) {
+            return ddlCommandFuture
+                    .thenCompose(res -> 
catalogManager.dropIndex(DdlToCatalogCommandConverter.convert((DropIndexCommand)
 cmd))
+                            
.handle(handleModificationResult(((DropIndexCommand) cmd).ifNotExists(), 
IndexNotFoundException.class))
+                    );
         }
 
         return ddlCommandFuture;
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlToCatalogCommandConverter.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlToCatalogCommandConverter.java
index e0e9f4f520..4a4cc96d82 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlToCatalogCommandConverter.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlToCatalogCommandConverter.java
@@ -20,13 +20,20 @@ package org.apache.ignite.internal.sql.engine.exec.ddl;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.catalog.commands.ColumnParams;
+import org.apache.ignite.internal.catalog.commands.CreateIndexParams;
 import org.apache.ignite.internal.catalog.commands.CreateTableParams;
 import org.apache.ignite.internal.catalog.commands.DefaultValue;
+import org.apache.ignite.internal.catalog.commands.DropIndexParams;
 import org.apache.ignite.internal.catalog.commands.DropTableParams;
+import org.apache.ignite.internal.catalog.descriptors.ColumnCollation;
 import org.apache.ignite.internal.sql.engine.prepare.ddl.ColumnDefinition;
+import org.apache.ignite.internal.sql.engine.prepare.ddl.CreateIndexCommand;
+import 
org.apache.ignite.internal.sql.engine.prepare.ddl.CreateIndexCommand.Type;
 import org.apache.ignite.internal.sql.engine.prepare.ddl.CreateTableCommand;
 import 
org.apache.ignite.internal.sql.engine.prepare.ddl.DefaultValueDefinition;
+import org.apache.ignite.internal.sql.engine.prepare.ddl.DropIndexCommand;
 import org.apache.ignite.internal.sql.engine.prepare.ddl.DropTableCommand;
+import org.apache.ignite.internal.sql.engine.schema.IgniteIndex;
 import org.apache.ignite.internal.sql.engine.util.TypeUtils;
 
 /**
@@ -56,6 +63,29 @@ class DdlToCatalogCommandConverter {
                 .build();
     }
 
+    static CreateIndexParams convert(CreateIndexCommand cmd) {
+        List<ColumnCollation> collations = cmd.collations() == null ? null
+                : 
cmd.collations().stream().map(DdlToCatalogCommandConverter::convert).collect(Collectors.toList());
+
+        return CreateIndexParams.builder()
+                .schemaName(cmd.schemaName())
+                .indexName(cmd.indexName())
+
+                .tableName(cmd.tableName())
+                .type(convert(cmd.type()))
+                .columns(cmd.columns())
+                .collations(collations)
+
+                .build();
+    }
+
+    static DropIndexParams convert(DropIndexCommand cmd) {
+        return DropIndexParams.builder()
+                .schemaName(cmd.schemaName())
+                .indexName(cmd.indexName())
+                .build();
+    }
+
     private static ColumnParams convert(ColumnDefinition def) {
         return new ColumnParams(def.name(), TypeUtils.columnType(def.type()), 
convert(def.defaultValueDefinition()), def.nullable());
     }
@@ -72,4 +102,19 @@ class DdlToCatalogCommandConverter {
                 throw new IllegalArgumentException("Default value definition: 
" + def.type());
         }
     }
+
+    private static CreateIndexParams.Type convert(Type type) {
+        switch (type) {
+            case SORTED:
+                return CreateIndexParams.Type.SORTED;
+            case HASH:
+                return CreateIndexParams.Type.HASH;
+            default:
+                throw new IllegalArgumentException("Unsupported index type: " 
+ type);
+        }
+    }
+
+    private static ColumnCollation convert(IgniteIndex.Collation collation) {
+        return ColumnCollation.get(collation.asc, collation.nullsFirst);
+    }
 }
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/schema/FullTableSchemaTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/schema/FullTableSchemaTest.java
index fbe2ce2830..ae1bd9276c 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/schema/FullTableSchemaTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/schema/FullTableSchemaTest.java
@@ -47,7 +47,7 @@ class FullTableSchemaTest {
 
     @NotNull
     private static HashIndexDescriptor someIndex(int id, String name) {
-        return new HashIndexDescriptor(id, name, 1, List.of("a"));
+        return new HashIndexDescriptor(id, name, 1, true, List.of("a"));
     }
 
     @NotNull

Reply via email to