You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2023/05/18 10:16:55 UTC

[ignite-3] branch ignite-19460 updated (59e66e2156 -> da3bb2a6de)

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

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


 discard 59e66e2156 Add create index command. Add drop index command.
     new de2f6f45a5 Add create index command. Add drop index command.
     new 60e9006f66 Styles
     new da3bb2a6de Add create/drop index events.

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (59e66e2156)
            \
             N -- N -- N   refs/heads/ignite-19460 (da3bb2a6de)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../ignite/internal/catalog/CatalogService.java    |   2 +
 .../internal/catalog/CatalogServiceImpl.java       |  47 ++++-
 .../commands/AbstractIndexCommandParams.java       |  33 ++++
 .../commands/AbstractTableCommandParams.java       |  21 +++
 .../internal/catalog/commands/CatalogUtils.java    |   3 +-
 .../catalog/commands/CreateIndexParams.java        |  28 ++-
 .../catalog/descriptors/HashIndexDescriptor.java   |   5 +-
 .../catalog/descriptors/IndexDescriptor.java       |   2 +-
 .../catalog/descriptors/SortedIndexDescriptor.java |   5 +-
 .../internal/catalog/events/CatalogEvent.java      |   8 +-
 ...meters.java => CreateIndexEventParameters.java} |  20 +--
 ...rameters.java => DropIndexEventParameters.java} |  18 +-
 .../internal/catalog/storage/DropIndexEntry.java   |   6 +-
 .../internal/catalog/storage/NewIndexEntry.java    |  51 ------
 .../internal/catalog/CatalogServiceSelfTest.java   | 200 ++++++++++++++++++++-
 .../distributed/schema/FullTableSchemaTest.java    |   2 +-
 16 files changed, 358 insertions(+), 93 deletions(-)
 copy modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/{CreateTableEventParameters.java => CreateIndexEventParameters.java} (63%)
 copy modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/{DropTableEventParameters.java => DropIndexEventParameters.java} (71%)


[ignite-3] 01/03: Add create index command. Add drop index command.

Posted by am...@apache.org.
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 <an...@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


[ignite-3] 03/03: Add create/drop index events.

Posted by am...@apache.org.
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 da3bb2a6decfef6220a8206a2d43b88fe6cceef6
Author: amashenkov <an...@gmail.com>
AuthorDate: Thu May 18 12:37:38 2023 +0300

    Add create/drop index events.
---
 .../internal/catalog/CatalogServiceImpl.java       | 14 +++-
 .../internal/catalog/events/CatalogEvent.java      |  8 ++-
 .../internal/catalog/CatalogServiceSelfTest.java   | 80 +++++++++++++++++++---
 3 files changed, 91 insertions(+), 11 deletions(-)

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 5a780ec72a..7bd2965cbf 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
@@ -41,7 +41,9 @@ import org.apache.ignite.internal.catalog.descriptors.SchemaDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.TableDescriptor;
 import org.apache.ignite.internal.catalog.events.CatalogEvent;
 import org.apache.ignite.internal.catalog.events.CatalogEventParameters;
+import org.apache.ignite.internal.catalog.events.CreateIndexEventParameters;
 import org.apache.ignite.internal.catalog.events.CreateTableEventParameters;
+import org.apache.ignite.internal.catalog.events.DropIndexEventParameters;
 import org.apache.ignite.internal.catalog.events.DropTableEventParameters;
 import org.apache.ignite.internal.catalog.storage.DropIndexEntry;
 import org.apache.ignite.internal.catalog.storage.DropTableEntry;
@@ -125,7 +127,7 @@ public class CatalogServiceImpl extends Producer<CatalogEvent, CatalogEventParam
     /** {@inheritDoc} */
     @Override
     public IndexDescriptor index(String indexName, long timestamp) {
-        return catalogAt(timestamp).schema(PUBLIC).index(indexName);
+        return catalogAt(timestamp).schema(CatalogService.PUBLIC).index(indexName);
     }
 
     /** {@inheritDoc} */
@@ -379,6 +381,11 @@ public class CatalogServiceImpl extends Producer<CatalogEvent, CatalogEventParam
                                     ArrayUtils.concat(schema.indexes(), ((NewIndexEntry) entry).descriptor())
                             )
                     );
+
+                    eventFutures.add(fireEvent(
+                            CatalogEvent.INDEX_CREATE,
+                            new CreateIndexEventParameters(version, ((NewIndexEntry) entry).descriptor())
+                    ));
                 } else if (entry instanceof DropIndexEntry) {
                     int indexId = ((DropIndexEntry) entry).indexId();
 
@@ -394,6 +401,11 @@ public class CatalogServiceImpl extends Producer<CatalogEvent, CatalogEventParam
                                     Arrays.stream(schema.indexes()).filter(t -> t.id() != indexId).toArray(IndexDescriptor[]::new)
                             )
                     );
+
+                    eventFutures.add(fireEvent(
+                            CatalogEvent.INDEX_DROP,
+                            new DropIndexEventParameters(version, indexId)
+                    ));
                 } else if (entry instanceof ObjectIdGenUpdateEntry) {
                     catalog = new Catalog(
                             version,
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/CatalogEvent.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/CatalogEvent.java
index d88347aeca..dfae89507b 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/CatalogEvent.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/CatalogEvent.java
@@ -27,5 +27,11 @@ public enum CatalogEvent implements Event {
     TABLE_CREATE,
 
     /** This event is fired, when a table was dropped in Catalog. */
-    TABLE_DROP
+    TABLE_DROP,
+
+    /** This event is fired, when a index was created in Catalog. */
+    INDEX_CREATE,
+
+    /** This event is fired, when a index was dropped in Catalog. */
+    INDEX_DROP
 }
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 a108bd4e6b..a152c6abb0 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
@@ -34,6 +34,7 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
@@ -44,6 +45,7 @@ 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.DropIndexParams;
 import org.apache.ignite.internal.catalog.commands.DropTableParams;
 import org.apache.ignite.internal.catalog.descriptors.ColumnCollation;
 import org.apache.ignite.internal.catalog.descriptors.HashIndexDescriptor;
@@ -52,7 +54,9 @@ 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;
+import org.apache.ignite.internal.catalog.events.CreateIndexEventParameters;
 import org.apache.ignite.internal.catalog.events.CreateTableEventParameters;
+import org.apache.ignite.internal.catalog.events.DropIndexEventParameters;
 import org.apache.ignite.internal.catalog.events.DropTableEventParameters;
 import org.apache.ignite.internal.catalog.storage.ObjectIdGenUpdateEntry;
 import org.apache.ignite.internal.catalog.storage.UpdateLog;
@@ -67,6 +71,7 @@ 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.IndexNotFoundException;
 import org.apache.ignite.lang.NodeStoppingException;
 import org.apache.ignite.lang.TableAlreadyExistsException;
 import org.apache.ignite.lang.TableNotFoundException;
@@ -243,12 +248,14 @@ public class CatalogServiceSelfTest {
     }
 
     @Test
-    public void testDropTable() {
+    public void testDropTable() throws InterruptedException {
         assertThat(service.createTable(simpleTable(TABLE_NAME)), willBe((Object) null));
         assertThat(service.createTable(simpleTable(TABLE_NAME_2)), willBe((Object) null));
 
         long beforeDropTimestamp = System.currentTimeMillis();
 
+        Thread.sleep(5);
+
         DropTableParams dropTableParams = DropTableParams.builder().schemaName("PUBLIC").tableName(TABLE_NAME).build();
 
         assertThat(service.dropTable(dropTableParams), willBe((Object) null));
@@ -477,8 +484,8 @@ public class CatalogServiceSelfTest {
 
     @Test
     public void testCreateTableEvents() {
-        CreateTableParams params = CreateTableParams.builder()
-                .schemaName("PUBLIC")
+        CreateTableParams createTableParams = CreateTableParams.builder()
+                .schemaName(CatalogService.PUBLIC)
                 .tableName(TABLE_NAME)
                 .ifTableExists(true)
                 .zone("ZONE")
@@ -491,25 +498,80 @@ public class CatalogServiceSelfTest {
                 .colocationColumns(List.of("key2"))
                 .build();
 
+        DropTableParams dropTableparams = DropTableParams.builder().tableName(TABLE_NAME).build();
+
         EventListener<CatalogEventParameters> eventListener = Mockito.mock(EventListener.class);
         when(eventListener.notify(any(), any())).thenReturn(completedFuture(false));
 
         service.listen(CatalogEvent.TABLE_CREATE, eventListener);
         service.listen(CatalogEvent.TABLE_DROP, eventListener);
 
-        CompletableFuture<Void> fut = service.createTable(params);
+        assertThat(service.createTable(createTableParams), willBe((Object) null));
+        verify(eventListener).notify(any(CreateTableEventParameters.class), ArgumentMatchers.isNull());
 
-        assertThat(fut, willBe((Object) null));
+        assertThat(service.dropTable(dropTableparams), willBe((Object) null));
+        verify(eventListener).notify(any(DropTableEventParameters.class), ArgumentMatchers.isNull());
 
-        verify(eventListener).notify(any(CreateTableEventParameters.class), ArgumentMatchers.isNull());
+        verifyNoMoreInteractions(eventListener);
+    }
+
+    @Test
+    public void testCreateIndexEvents() {
+        CreateTableParams createTableParams = CreateTableParams.builder()
+                .schemaName(CatalogService.PUBLIC)
+                .tableName(TABLE_NAME)
+                .ifTableExists(true)
+                .zone("ZONE")
+                .columns(List.of(
+                        new ColumnParams("key1", ColumnType.INT32, DefaultValue.constant(null), false),
+                        new ColumnParams("key2", ColumnType.INT32, DefaultValue.constant(null), false),
+                        new ColumnParams("val", ColumnType.INT32, DefaultValue.constant(null), true)
+                ))
+                .primaryKeyColumns(List.of("key1", "key2"))
+                .colocationColumns(List.of("key2"))
+                .build();
 
         DropTableParams dropTableparams = DropTableParams.builder().tableName(TABLE_NAME).build();
 
-        fut = service.dropTable(dropTableparams);
+        CreateIndexParams createIndexParams = CreateIndexParams.builder()
+                .schemaName(CatalogService.PUBLIC)
+                .indexName(INDEX_NAME)
+                .tableName(TABLE_NAME)
+                .ifIndexExists(true)
+                .type(Type.HASH)
+                .unique()
+                .columns(List.of("key2"))
+                .build();
 
-        assertThat(fut, willBe((Object) null));
+        DropIndexParams dropIndexParams = DropIndexParams.builder().indexName(INDEX_NAME).build();
+
+        EventListener<CatalogEventParameters> eventListener = Mockito.mock(EventListener.class);
+        when(eventListener.notify(any(), any())).thenReturn(completedFuture(false));
+
+        service.listen(CatalogEvent.INDEX_CREATE, eventListener);
+        service.listen(CatalogEvent.INDEX_DROP, eventListener);
+
+        // Try to create index without table.
+        assertThat(service.createIndex(createIndexParams), willThrow(TableNotFoundException.class));
+        verifyNoInteractions(eventListener);
+
+        // Create table.
+        assertThat(service.createTable(createTableParams), willBe((Object) null));
+
+        // Create index.
+        assertThat(service.createIndex(createIndexParams), willBe((Object) null));
+        verify(eventListener).notify(any(CreateIndexEventParameters.class), ArgumentMatchers.isNull());
+
+        // Drop index.
+        assertThat(service.dropIndex(dropIndexParams), willBe((Object) null));
+        verify(eventListener).notify(any(DropIndexEventParameters.class), ArgumentMatchers.isNull());
+
+        // Drop table.
+        assertThat(service.dropTable(dropTableparams), willBe((Object) null));
+
+        // Try drop index once again.
+        assertThat(service.dropIndex(dropIndexParams), willThrow(IndexNotFoundException.class));
 
-        verify(eventListener).notify(any(DropTableEventParameters.class), ArgumentMatchers.isNull());
         verifyNoMoreInteractions(eventListener);
     }
 


[ignite-3] 02/03: Styles

Posted by am...@apache.org.
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 60e9006f666a16385a476faafcb15746d44afe2b
Author: amashenkov <an...@gmail.com>
AuthorDate: Thu May 18 12:17:48 2023 +0300

    Styles
---
 .../main/java/org/apache/ignite/internal/catalog/CatalogServiceImpl.java | 1 -
 1 file changed, 1 deletion(-)

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 d3570ec8c3..5a780ec72a 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
@@ -67,7 +67,6 @@ import org.jetbrains.annotations.Nullable;
 
 /**
  * Catalog service implementation.
- * TODO: IGNITE-19081 Introduce catalog events and make CatalogServiceImpl extends Producer.
  */
 public class CatalogServiceImpl extends Producer<CatalogEvent, CatalogEventParameters> implements CatalogManager {
     private static final int MAX_RETRY_COUNT = 10;