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 2024/08/20 15:51:01 UTC
(ignite-3) branch ignite-18747 created (now ce29481bdd)
This is an automated email from the ASF dual-hosted git repository.
amashenkov pushed a change to branch ignite-18747
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
at ce29481bdd Support index renaming.
This branch includes the following new commits:
new ce29481bdd Support index renaming.
The 1 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.
(ignite-3) 01/01: Support index renaming.
Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
amashenkov pushed a commit to branch ignite-18747
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit ce29481bdd02abed4d4484d542dc5dd2a3542848
Author: amashenkov <an...@gmail.com>
AuthorDate: Tue Aug 20 18:50:50 2024 +0300
Support index renaming.
---
.../catalog/commands/RenameIndexCommand.java | 116 ++++++++++++++++
.../commands/RenameIndexCommandBuilder.java | 35 +++++
.../ignite/internal/catalog/CatalogIndexTest.java | 80 +++++++++++
.../commands/RenameIndexCommandValidationTest.java | 153 +++++++++++++++++++++
.../internal/catalog/BaseCatalogManagerTest.java | 9 ++
.../prepare/ddl/DdlSqlToCommandConverter.java | 2 +
6 files changed, 395 insertions(+)
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameIndexCommand.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameIndexCommand.java
new file mode 100644
index 0000000000..f4327eb6ac
--- /dev/null
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameIndexCommand.java
@@ -0,0 +1,116 @@
+/*
+ * 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 static org.apache.ignite.internal.catalog.CatalogParamsValidationUtils.ensureNoTableIndexOrSysViewExistsWithGivenName;
+import static org.apache.ignite.internal.catalog.CatalogParamsValidationUtils.validateIdentifier;
+import static org.apache.ignite.internal.catalog.commands.CatalogUtils.indexOrThrow;
+import static org.apache.ignite.internal.catalog.commands.CatalogUtils.schemaOrThrow;
+
+import java.util.List;
+import org.apache.ignite.internal.catalog.Catalog;
+import org.apache.ignite.internal.catalog.CatalogCommand;
+import org.apache.ignite.internal.catalog.CatalogValidationException;
+import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
+import org.apache.ignite.internal.catalog.storage.RenameIndexEntry;
+import org.apache.ignite.internal.catalog.storage.UpdateEntry;
+
+/**
+ * A command that changes the name of an index.
+ */
+public class RenameIndexCommand extends AbstractIndexCommand {
+ /** Returns a builder to create a command to rename an index. */
+ public static RenameIndexCommandBuilder builder() {
+ return new Builder();
+ }
+
+ private final String newIndexName;
+
+ private final boolean ifIndexExists;
+
+ private RenameIndexCommand(String schemaName, String indexName, boolean ifIndexExists, String newIndexName)
+ throws CatalogValidationException {
+ super(schemaName, indexName);
+
+ validateIdentifier(newIndexName, "New index name");
+
+ this.newIndexName = newIndexName;
+ this.ifIndexExists = ifIndexExists;
+ }
+
+ @Override
+ public List<UpdateEntry> get(Catalog catalog) {
+ CatalogSchemaDescriptor schema = schemaOrThrow(catalog, schemaName);
+
+ CatalogIndexDescriptor index = indexOrThrow(schema, indexName);
+
+ ensureNoTableIndexOrSysViewExistsWithGivenName(schema, newIndexName);
+
+ return List.of(
+ new RenameIndexEntry(index.id(), newIndexName)
+ );
+ }
+
+ public boolean ifIndexExists() {
+ return ifIndexExists;
+ }
+
+ private static class Builder implements RenameIndexCommandBuilder {
+ private String schemaName;
+
+ private String indexName;
+
+ private boolean ifExists;
+
+ private String newIndexName;
+
+ @Override
+ public RenameIndexCommandBuilder schemaName(String schemaName) {
+ this.schemaName = schemaName;
+
+ return this;
+ }
+
+ @Override
+ public RenameIndexCommandBuilder indexName(String indexName) {
+ this.indexName = indexName;
+
+ return this;
+ }
+
+ @Override
+ public RenameIndexCommandBuilder ifIndexExists(boolean ifExists) {
+ this.ifExists = ifExists;
+
+ return this;
+ }
+
+ @Override
+ public RenameIndexCommandBuilder newIndexName(String newIndexName) {
+ this.newIndexName = newIndexName;
+
+ return this;
+ }
+
+ @Override
+ public CatalogCommand build() {
+ return new RenameIndexCommand(schemaName, indexName, ifExists, newIndexName);
+ }
+ }
+}
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameIndexCommandBuilder.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameIndexCommandBuilder.java
new file mode 100644
index 0000000000..d8ab00f03d
--- /dev/null
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameIndexCommandBuilder.java
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+/** Builder for {@link RenameIndexCommand}s. */
+public interface RenameIndexCommandBuilder extends AbstractIndexCommandBuilder<RenameIndexCommandBuilder> {
+ /**
+ * Sets the new name of the target index.
+ *
+ * <p>The new name must not be {@code null}, empty or blank. It is also required that an index with the same name does not already exist
+ * in the schema that the target index belongs to.
+ *
+ * @param newIndexName New name of the target index.
+ * @return this instance (for chaining).
+ */
+ RenameIndexCommandBuilder newIndexName(String newIndexName);
+
+ /** Sets a flag indicating whether the {@code IF EXISTS} was specified. */
+ RenameIndexCommandBuilder ifIndexExists(boolean ifExists);
+}
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogIndexTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogIndexTest.java
index 2194262b91..668bd9dc8f 100644
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogIndexTest.java
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogIndexTest.java
@@ -35,6 +35,7 @@ import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -59,6 +60,7 @@ import java.util.concurrent.CompletableFuture;
import org.apache.ignite.internal.catalog.commands.DropIndexCommand;
import org.apache.ignite.internal.catalog.commands.MakeIndexAvailableCommand;
import org.apache.ignite.internal.catalog.commands.RemoveIndexCommand;
+import org.apache.ignite.internal.catalog.commands.RenameIndexCommand;
import org.apache.ignite.internal.catalog.commands.StartBuildingIndexCommand;
import org.apache.ignite.internal.catalog.descriptors.CatalogHashIndexDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
@@ -521,6 +523,8 @@ public class CatalogIndexTest extends BaseCatalogManagerTest {
verify(eventListener).notify(any(RemoveIndexEventParameters.class));
verifyNoMoreInteractions(eventListener);
clearInvocations(eventListener);
+
+
}
@Test
@@ -764,6 +768,75 @@ public class CatalogIndexTest extends BaseCatalogManagerTest {
assertThat(tableIndexIds(catalogVersion, tableId(TABLE_NAME)), equalTo(List.of(indexId0, indexId1, indexId2)));
}
+ @Test
+ public void testRenameIndex() {
+ createSomeTable(TABLE_NAME);
+ createSomeIndex(TABLE_NAME, INDEX_NAME);
+
+ long beforeRename = clock.nowLong();
+
+ CatalogIndexDescriptor index = manager.aliveIndex(INDEX_NAME, clock.nowLong());
+ assertThat(index, is(notNullValue()));
+
+ int indexId = index.id();
+
+ // Rename index.
+ renameIndex(INDEX_NAME, INDEX_NAME_2);
+
+ // Ensure index is available by new name.
+ assertThat(manager.aliveIndex(INDEX_NAME, clock.nowLong()), is(nullValue()));
+
+ index = manager.aliveIndex(INDEX_NAME_2, clock.nowLong());
+ assertThat(index, is(notNullValue()));
+ assertThat(index.id(), is(indexId));
+ assertThat(index.name(), is(INDEX_NAME_2));
+
+ // Ensure renamed index is available for historical queries.
+ CatalogIndexDescriptor oldDescriptor = manager.aliveIndex(INDEX_NAME, beforeRename);
+ assertThat(oldDescriptor, is(notNullValue()));
+ assertThat(oldDescriptor.id(), is(indexId));
+
+ // Ensure can create new index with same name.
+ createSomeIndex(TABLE_NAME, INDEX_NAME);
+
+ index = manager.aliveIndex(INDEX_NAME, clock.nowLong());
+ assertThat(index, is(notNullValue()));
+ assertThat(index.id(), not(indexId));
+ }
+
+ @Test
+ public void testRenamePkIndex() {
+ createSomeTable(TABLE_NAME);
+
+ CatalogTableDescriptor table = manager.table(TABLE_NAME, clock.nowLong());
+ assertThat(table, is(notNullValue()));
+
+ assertThat(manager.aliveIndex(INDEX_NAME, clock.nowLong()), is(nullValue()));
+ assertThat(manager.aliveIndex(pkIndexName(TABLE_NAME), clock.nowLong()), is(notNullValue()));
+
+ int primaryKeyIndexId = table.primaryKeyIndexId();
+
+ // Rename index.
+ renameIndex(pkIndexName(TABLE_NAME), INDEX_NAME);
+
+ CatalogIndexDescriptor index = manager.aliveIndex(INDEX_NAME, clock.nowLong());
+ assertThat(index, is(notNullValue()));
+ assertThat(index.id(), is(primaryKeyIndexId));
+ assertThat(index.name(), is(INDEX_NAME));
+
+ assertThat(manager.aliveIndex(pkIndexName(TABLE_NAME), clock.nowLong()), is(nullValue()));
+ }
+
+ @Test
+ public void testRenameNonExistingIndex() {
+ createSomeTable(TABLE_NAME);
+
+ assertThat(
+ manager.execute(RenameIndexCommand.builder().schemaName(SCHEMA_NAME).indexName(INDEX_NAME).newIndexName("TEST").build()),
+ willThrowFast(IndexNotFoundValidationException.class)
+ );
+ }
+
private @Nullable CatalogIndexDescriptor index(int catalogVersion, String indexName) {
return manager.schema(catalogVersion).aliveIndex(indexName);
}
@@ -801,4 +874,11 @@ public class CatalogIndexTest extends BaseCatalogManagerTest {
willCompleteSuccessfully()
);
}
+
+ private void renameIndex(String indexName, String newIndexName) {
+ assertThat(
+ manager.execute(renameIndexCommand(indexName, newIndexName)),
+ willCompleteSuccessfully()
+ );
+ }
}
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/RenameIndexCommandValidationTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/RenameIndexCommandValidationTest.java
new file mode 100644
index 0000000000..04c45885f2
--- /dev/null
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/RenameIndexCommandValidationTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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 static org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrows;
+
+import org.apache.ignite.internal.catalog.Catalog;
+import org.apache.ignite.internal.catalog.CatalogCommand;
+import org.apache.ignite.internal.catalog.CatalogValidationException;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+/**
+ * Test suite for validating parameters of {@link RenameIndexCommand}s.
+ */
+public class RenameIndexCommandValidationTest extends AbstractCommandValidationTest {
+ @ParameterizedTest(name = "[{index}] ''{argumentsWithNames}''")
+ @MethodSource("nullAndBlankStrings")
+ void schemaNameMustNotBeNullOrBlank(String name) {
+ RenameIndexCommandBuilder builder = RenameIndexCommand.builder()
+ .schemaName(name)
+ .indexName("TEST")
+ .newIndexName("TEST2");
+
+ assertThrows(
+ CatalogValidationException.class,
+ builder::build,
+ "Name of the schema can't be null or blank"
+ );
+ }
+
+ @ParameterizedTest(name = "[{index}] ''{argumentsWithNames}''")
+ @MethodSource("nullAndBlankStrings")
+ void indexNameMustNotBeNullOrBlank(String name) {
+ RenameIndexCommandBuilder builder = RenameIndexCommand.builder()
+ .schemaName("TEST")
+ .indexName(name)
+ .newIndexName("TEST2");
+
+ assertThrows(
+ CatalogValidationException.class,
+ builder::build,
+ "Name of the index can't be null or blank"
+ );
+ }
+
+ @ParameterizedTest(name = "[{index}] ''{argumentsWithNames}''")
+ @MethodSource("nullAndBlankStrings")
+ void newIndexNameMustNotBeNullOrBlank(String name) {
+ RenameIndexCommandBuilder builder = RenameIndexCommand.builder()
+ .schemaName("TEST")
+ .indexName("TEST")
+ .newIndexName(name);
+
+ assertThrows(
+ CatalogValidationException.class,
+ builder::build,
+ "New index name can't be null or blank"
+ );
+ }
+
+ @Test
+ void exceptionIsThrownIfSchemaDoesNotExist() {
+ Catalog catalog = catalogWithDefaultZone();
+
+ CatalogCommand command = RenameIndexCommand.builder()
+ .schemaName("TEST")
+ .indexName("TEST")
+ .newIndexName("TEST2")
+ .build();
+
+ assertThrows(
+ CatalogValidationException.class,
+ () -> command.get(catalog),
+ "Schema with name 'TEST' not found"
+ );
+ }
+
+ @Test
+ void exceptionIsThrownIfIndexWithGivenNameNotFound() {
+ Catalog catalog = catalogWithDefaultZone();
+
+ CatalogCommand command = RenameIndexCommand.builder()
+ .schemaName(SCHEMA_NAME)
+ .indexName("TEST")
+ .newIndexName("TEST2")
+ .build();
+
+ assertThrows(
+ CatalogValidationException.class,
+ () -> command.get(catalog),
+ "Index with name 'PUBLIC.TEST' not found"
+ );
+ }
+
+ @Test
+ void exceptionIsThrownIfIndexWithNewNameExists() {
+ Catalog catalog = catalog(
+ createTableCommand("TABLE1"),
+ createTableCommand("TABLE2"),
+ createIndexCommand("TABLE1", "TEST1"),
+ createIndexCommand("TABLE2", "TEST2")
+ );
+
+ CatalogCommand command = RenameIndexCommand.builder()
+ .schemaName(SCHEMA_NAME)
+ .indexName("TEST1")
+ .newIndexName("TEST2")
+ .build();
+
+ assertThrows(
+ CatalogValidationException.class,
+ () -> command.get(catalog),
+ "Index with name 'PUBLIC.TEST2' already exists"
+ );
+ }
+
+ @Test
+ void exceptionIsThrownIfTableWithNewNameExists() {
+ Catalog catalog = catalog(
+ createTableCommand("TABLE1"),
+ createIndexCommand("TABLE1", "TEST")
+ );
+
+ CatalogCommand command = RenameIndexCommand.builder()
+ .schemaName(SCHEMA_NAME)
+ .indexName("TEST")
+ .newIndexName("TABLE1")
+ .build();
+
+ assertThrows(
+ CatalogValidationException.class,
+ () -> command.get(catalog),
+ "Table with name 'PUBLIC.TABLE1' already exists"
+ );
+ }
+}
diff --git a/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/BaseCatalogManagerTest.java b/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/BaseCatalogManagerTest.java
index a14949b398..fe0f9c4450 100644
--- a/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/BaseCatalogManagerTest.java
+++ b/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/BaseCatalogManagerTest.java
@@ -44,6 +44,7 @@ import org.apache.ignite.internal.catalog.commands.CreateTableCommand;
import org.apache.ignite.internal.catalog.commands.CreateTableCommandBuilder;
import org.apache.ignite.internal.catalog.commands.DropIndexCommand;
import org.apache.ignite.internal.catalog.commands.DropTableCommand;
+import org.apache.ignite.internal.catalog.commands.RenameIndexCommand;
import org.apache.ignite.internal.catalog.commands.StartBuildingIndexCommand;
import org.apache.ignite.internal.catalog.commands.TableHashPrimaryKey;
import org.apache.ignite.internal.catalog.commands.TablePrimaryKey;
@@ -278,6 +279,14 @@ public abstract class BaseCatalogManagerTest extends BaseIgniteAbstractTest {
.build();
}
+ protected static CatalogCommand renameIndexCommand(String indexName, String newIndexName) {
+ return RenameIndexCommand.builder()
+ .schemaName(SqlCommon.DEFAULT_SCHEMA_NAME)
+ .indexName(indexName)
+ .newIndexName(newIndexName)
+ .build();
+ }
+
protected static <T extends CatalogEventParameters> EventListener<T> fromConsumer(
CompletableFuture<Void> fireEventFuture,
Consumer<T> consumer
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
index 53974370e7..78ac71efd1 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
@@ -630,6 +630,8 @@ public class DdlSqlToCommandConverter {
.build();
}
+
+
/**
* Converts the given '{@code CREATE ZONE}' AST to the {@link CreateZoneCommand} catalog command.
*/