This is an automated email from the ASF dual-hosted git repository. apolovtsev pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push: new 642918794c IGNITE-21215 Add Catalog API for renaming a table (#3029) 642918794c is described below commit 642918794c2d8c74506b3ae3c71d8c21c765d1c2 Author: Alexander Polovtcev <alex.polovt...@gmail.com> AuthorDate: Fri Jan 12 09:29:44 2024 +0200 IGNITE-21215 Add Catalog API for renaming a table (#3029) --- .../catalog/commands/RenameTableCommand.java | 97 +++++++++++++++ .../commands/RenameTableCommandBuilder.java | 32 +++++ .../internal/catalog/events/CatalogEvent.java | 2 +- .../catalog/events/RenameTableEventParameters.java | 46 +++++++ .../internal/catalog/storage/RenameTableEntry.java | 107 +++++++++++++++++ .../internal/catalog/CatalogManagerSelfTest.java | 79 ++++++++++++ .../commands/RenameTableCommandValidationTest.java | 132 +++++++++++++++++++++ .../ignite/internal/client/table/ClientTable.java | 1 + .../ignite/client/fakes/FakeInternalTable.java | 5 + .../ignite/internal/table/InternalTable.java | 8 ++ .../apache/ignite/internal/table/TableImpl.java | 5 + .../internal/table/distributed/TableManager.java | 30 ++++- .../distributed/storage/InternalTableImpl.java | 7 +- 13 files changed, 548 insertions(+), 3 deletions(-) diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameTableCommand.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameTableCommand.java new file mode 100644 index 0000000000..8bd014cc05 --- /dev/null +++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameTableCommand.java @@ -0,0 +1,97 @@ +/* + * 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.schemaOrThrow; +import static org.apache.ignite.internal.catalog.commands.CatalogUtils.tableOrThrow; + +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.CatalogSchemaDescriptor; +import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor; +import org.apache.ignite.internal.catalog.storage.RenameTableEntry; +import org.apache.ignite.internal.catalog.storage.UpdateEntry; + +/** + * A command that changes the name of a table. + */ +public class RenameTableCommand extends AbstractTableCommand { + /** Returns a builder to create a command to rename a table. */ + public static RenameTableCommandBuilder builder() { + return new Builder(); + } + + private final String newTableName; + + private RenameTableCommand(String schemaName, String tableName, String newTableName) throws CatalogValidationException { + super(schemaName, tableName); + + validateIdentifier(newTableName, "New table name"); + + this.newTableName = newTableName; + } + + @Override + public List<UpdateEntry> get(Catalog catalog) { + CatalogSchemaDescriptor schema = schemaOrThrow(catalog, schemaName); + + ensureNoTableIndexOrSysViewExistsWithGivenName(schema, newTableName); + + CatalogTableDescriptor table = tableOrThrow(schema, tableName); + + return List.of(new RenameTableEntry(table.id(), newTableName)); + } + + private static class Builder implements RenameTableCommandBuilder { + private String schemaName; + + private String tableName; + + private String newTableName; + + @Override + public RenameTableCommandBuilder schemaName(String schemaName) { + this.schemaName = schemaName; + + return this; + } + + @Override + public RenameTableCommandBuilder tableName(String tableName) { + this.tableName = tableName; + + return this; + } + + @Override + public RenameTableCommandBuilder newTableName(String newTableName) { + this.newTableName = newTableName; + + return this; + } + + @Override + public CatalogCommand build() { + return new RenameTableCommand(schemaName, tableName, newTableName); + } + } +} diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameTableCommandBuilder.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameTableCommandBuilder.java new file mode 100644 index 0000000000..223739972e --- /dev/null +++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameTableCommandBuilder.java @@ -0,0 +1,32 @@ +/* + * 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 RenameTableCommand}s. */ +public interface RenameTableCommandBuilder extends AbstractTableCommandBuilder<RenameTableCommandBuilder> { + /** + * Sets the new name of the target table. + * + * <p>The new name must not be {@code null}, empty or blank. It is also required that a table with the same name does not already exist + * in the schema that the target table belongs to. + * + * @param newTableName New name of the target table. + * @return this instance (for chaining). + */ + RenameTableCommandBuilder newTableName(String newTableName); +} 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 444aa30ffd..91c2ed325c 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 @@ -29,7 +29,7 @@ public enum CatalogEvent implements Event { /** This event is fired, when a table was dropped in Catalog. */ TABLE_DROP, - /** This event is fired when a column has been modified, added to, or removed from a table. */ + /** This event is fired when a table has been renamed or a column has been modified, added to, or removed from a table. */ TABLE_ALTER, /** This event is fired, when an index was created in Catalog. */ diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/RenameTableEventParameters.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/RenameTableEventParameters.java new file mode 100644 index 0000000000..41749f2cf1 --- /dev/null +++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/events/RenameTableEventParameters.java @@ -0,0 +1,46 @@ +/* + * 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; + +/** + * Parameters for events that get produced when a table is renamed. + */ +public class RenameTableEventParameters extends TableEventParameters { + private final String newTableName; + + /** + * Constructor. + * + * @param causalityToken Causality token for the event. + * @param catalogVersion New catalog version. + * @param tableId ID of the altered table. + * @param newTableName New name of the table. + */ + public RenameTableEventParameters(long causalityToken, int catalogVersion, int tableId, String newTableName) { + super(causalityToken, catalogVersion, tableId); + + this.newTableName = newTableName; + } + + /** + * Returns the new name of the updated table. + */ + public String newTableName() { + return newTableName; + } +} diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/RenameTableEntry.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/RenameTableEntry.java new file mode 100644 index 0000000000..ed0e89c80c --- /dev/null +++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/RenameTableEntry.java @@ -0,0 +1,107 @@ +/* + * 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.storage; + +import static java.util.Objects.requireNonNull; +import static org.apache.ignite.internal.catalog.commands.CatalogUtils.replaceSchema; + +import org.apache.ignite.internal.catalog.Catalog; +import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor; +import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor; +import org.apache.ignite.internal.catalog.events.CatalogEvent; +import org.apache.ignite.internal.catalog.events.CatalogEventParameters; +import org.apache.ignite.internal.catalog.events.RenameTableEventParameters; + +/** Entry representing a rename of a table. */ +public class RenameTableEntry implements UpdateEntry, Fireable { + private static final long serialVersionUID = 4841281816270322196L; + + private final int tableId; + + private final String newTableName; + + public RenameTableEntry(int tableId, String newTableName) { + this.tableId = tableId; + this.newTableName = newTableName; + } + + @Override + public CatalogEvent eventType() { + return CatalogEvent.TABLE_ALTER; + } + + @Override + public CatalogEventParameters createEventParameters(long causalityToken, int catalogVersion) { + return new RenameTableEventParameters(causalityToken, catalogVersion, tableId, newTableName); + } + + @Override + public Catalog applyUpdate(Catalog catalog, long causalityToken) { + CatalogTableDescriptor tableDescriptor = requireNonNull(catalog.table(tableId)); + + CatalogSchemaDescriptor schemaDescriptor = requireNonNull(catalog.schema(tableDescriptor.schemaId())); + + CatalogTableDescriptor newTableDescriptor = tableDescriptor.newDescriptor( + newTableName, + tableDescriptor.tableVersion() + 1, + tableDescriptor.columns(), + causalityToken + ); + + CatalogSchemaDescriptor newSchemaDescriptor = replaceTableDescriptor(schemaDescriptor, newTableDescriptor, causalityToken); + + return new Catalog( + catalog.version(), + catalog.time(), + catalog.objectIdGenState(), + catalog.zones(), + replaceSchema(newSchemaDescriptor, catalog.schemas()) + ); + } + + private static CatalogSchemaDescriptor replaceTableDescriptor( + CatalogSchemaDescriptor schemaDescriptor, + CatalogTableDescriptor newTableDescriptor, + long causalityToken + ) { + CatalogTableDescriptor[] tableDescriptors = schemaDescriptor.tables().clone(); + + tableDescriptors[indexOf(tableDescriptors, newTableDescriptor)] = newTableDescriptor; + + return new CatalogSchemaDescriptor( + schemaDescriptor.id(), + schemaDescriptor.name(), + tableDescriptors, + schemaDescriptor.indexes(), + schemaDescriptor.systemViews(), + causalityToken + ); + } + + private static int indexOf(CatalogTableDescriptor[] tableDescriptors, CatalogTableDescriptor newTableDescriptor) { + for (int i = 0; i < tableDescriptors.length; i++) { + if (tableDescriptors[i].id() == newTableDescriptor.id()) { + return i; + } + } + + throw new IllegalStateException(String.format( + "Table with ID %d has not been found in schema with ID %d", newTableDescriptor.id(), newTableDescriptor.schemaId() + )); + } +} diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerSelfTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerSelfTest.java index adeeb24f0c..e383f9bee7 100644 --- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerSelfTest.java +++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerSelfTest.java @@ -61,6 +61,7 @@ import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; @@ -104,6 +105,7 @@ import org.apache.ignite.internal.catalog.commands.DefaultValue; import org.apache.ignite.internal.catalog.commands.DropIndexCommand; import org.apache.ignite.internal.catalog.commands.DropZoneCommand; import org.apache.ignite.internal.catalog.commands.MakeIndexAvailableCommand; +import org.apache.ignite.internal.catalog.commands.RenameTableCommand; import org.apache.ignite.internal.catalog.commands.RenameZoneCommand; import org.apache.ignite.internal.catalog.descriptors.CatalogHashIndexDescriptor; import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor; @@ -124,6 +126,7 @@ import org.apache.ignite.internal.catalog.events.DropIndexEventParameters; import org.apache.ignite.internal.catalog.events.DropTableEventParameters; import org.apache.ignite.internal.catalog.events.DropZoneEventParameters; import org.apache.ignite.internal.catalog.events.MakeIndexAvailableEventParameters; +import org.apache.ignite.internal.catalog.events.RenameTableEventParameters; import org.apache.ignite.internal.catalog.storage.ObjectIdGenUpdateEntry; import org.apache.ignite.internal.catalog.storage.UpdateLog; import org.apache.ignite.internal.catalog.storage.UpdateLog.OnUpdateHandler; @@ -2067,6 +2070,82 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest { assertThat(tableIndexIds(catalogVersion, tableId(TABLE_NAME)), equalTo(List.of(indexId0, indexId1, indexId2))); } + @Test + void testTableRename() { + createSomeTable(TABLE_NAME); + + int prevVersion = manager.latestCatalogVersion(); + + CatalogCommand command = RenameTableCommand.builder() + .schemaName(SCHEMA_NAME) + .tableName(TABLE_NAME) + .newTableName(TABLE_NAME_2) + .build(); + + assertThat(manager.execute(command), willCompleteSuccessfully()); + + int curVersion = manager.latestCatalogVersion(); + + CatalogTableDescriptor prevDescriptor = table(prevVersion, TABLE_NAME); + CatalogTableDescriptor curDescriptor = table(curVersion, TABLE_NAME_2); + + assertThat(prevDescriptor, is(notNullValue())); + assertThat(prevDescriptor.name(), is(TABLE_NAME)); + + assertThat(curDescriptor, is(notNullValue())); + assertThat(curDescriptor.name(), is(TABLE_NAME_2)); + + assertThat(table(prevVersion, TABLE_NAME_2), is(nullValue())); + assertThat(table(curVersion, TABLE_NAME), is(nullValue())); + + assertThat(curDescriptor.tableVersion(), is(prevDescriptor.tableVersion() + 1)); + + // Assert that all other properties have been left intact. + assertThat(curDescriptor.id(), is(prevDescriptor.id())); + assertThat(curDescriptor.columns(), is(prevDescriptor.columns())); + assertThat(curDescriptor.colocationColumns(), is(prevDescriptor.colocationColumns())); + assertThat(curDescriptor.creationToken(), is(prevDescriptor.creationToken())); + assertThat(curDescriptor.primaryKeyColumns(), is(prevDescriptor.primaryKeyColumns())); + assertThat(curDescriptor.primaryKeyIndexId(), is(prevDescriptor.primaryKeyIndexId())); + assertThat(curDescriptor.schemaId(), is(prevDescriptor.schemaId())); + } + + @Test + void testTableRenameFiresEvent() { + createSomeTable(TABLE_NAME); + + var eventFuture = new CompletableFuture<CatalogEventParameters>(); + + manager.listen(CatalogEvent.TABLE_ALTER, (parameters, e) -> { + if (e != null) { + eventFuture.completeExceptionally(e); + } else { + eventFuture.complete(parameters); + } + + return trueCompletedFuture(); + }); + + CatalogCommand command = RenameTableCommand.builder() + .schemaName(SCHEMA_NAME) + .tableName(TABLE_NAME) + .newTableName(TABLE_NAME_2) + .build(); + + assertThat(manager.execute(command), willCompleteSuccessfully()); + assertThat(eventFuture, willCompleteSuccessfully()); + + CatalogTableDescriptor tableDescriptor = table(manager.latestCatalogVersion(), TABLE_NAME_2); + + assertThat(tableDescriptor, is(notNullValue())); + + CatalogEventParameters eventParameters = eventFuture.join(); + + assertThat(eventParameters, is(instanceOf(RenameTableEventParameters.class))); + assertThat(((RenameTableEventParameters) eventParameters).tableId(), is(tableDescriptor.id())); + assertThat(((RenameTableEventParameters) eventParameters).newTableName(), is(tableDescriptor.name())); + } + private CompletableFuture<Void> changeColumn( String tab, String col, diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/RenameTableCommandValidationTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/RenameTableCommandValidationTest.java new file mode 100644 index 0000000000..0a983adbf0 --- /dev/null +++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/RenameTableCommandValidationTest.java @@ -0,0 +1,132 @@ +/* + * 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 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.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +/** + * Test suite for validating parameters of {@link RenameTableCommand}s. + */ +public class RenameTableCommandValidationTest extends AbstractCommandValidationTest { + @ParameterizedTest(name = "[{index}] ''{argumentsWithNames}''") + @MethodSource("nullAndBlankStrings") + void schemaNameMustNotBeNullOrBlank(String name) { + RenameTableCommandBuilder builder = RenameTableCommand.builder() + .schemaName(name) + .tableName("TEST") + .newTableName("TEST2"); + + assertThrows( + CatalogValidationException.class, + builder::build, + "Name of the schema can't be null or blank" + ); + } + + @ParameterizedTest(name = "[{index}] ''{argumentsWithNames}''") + @MethodSource("nullAndBlankStrings") + void tableNameMustNotBeNullOrBlank(String name) { + RenameTableCommandBuilder builder = RenameTableCommand.builder() + .schemaName("TEST") + .tableName(name) + .newTableName("TEST2"); + + assertThrows( + CatalogValidationException.class, + builder::build, + "Name of the table can't be null or blank" + ); + } + + @ParameterizedTest(name = "[{index}] ''{argumentsWithNames}''") + @MethodSource("nullAndBlankStrings") + void newTableNameMustNotBeNullOrBlank(String name) { + RenameTableCommandBuilder builder = RenameTableCommand.builder() + .schemaName("TEST") + .tableName("TEST") + .newTableName(name); + + assertThrows( + CatalogValidationException.class, + builder::build, + "New table name can't be null or blank" + ); + } + + @Test + void exceptionIsThrownIfSchemaDoesNotExist() { + Catalog catalog = emptyCatalog(); + + CatalogCommand command = RenameTableCommand.builder() + .schemaName("TEST") + .tableName("TEST") + .newTableName("TEST2") + .build(); + + assertThrows( + CatalogValidationException.class, + () -> command.get(catalog), + "Schema with name 'TEST' not found" + ); + } + + @Test + void exceptionIsThrownIfTableWithGivenNameNotFound() { + Catalog catalog = emptyCatalog(); + + CatalogCommand command = RenameTableCommand.builder() + .schemaName(SCHEMA_NAME) + .tableName("TEST") + .newTableName("TEST2") + .build(); + + assertThrows( + CatalogValidationException.class, + () -> command.get(catalog), + "Table with name 'PUBLIC.TEST' not found" + ); + } + + @Test + void exceptionIsThrownIfTableWithNewNameExists() { + Catalog catalog = catalog(List.of( + createTableCommand("TEST"), + createTableCommand("TEST2") + )); + + CatalogCommand command = RenameTableCommand.builder() + .schemaName(SCHEMA_NAME) + .tableName("TEST") + .newTableName("TEST2") + .build(); + + assertThrows( + CatalogValidationException.class, + () -> command.get(catalog), + "Table with name 'PUBLIC.TEST2' already exists" + ); + } +} diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTable.java b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTable.java index faee18b10c..69df134d0b 100644 --- a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTable.java +++ b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTable.java @@ -60,6 +60,7 @@ import org.jetbrains.annotations.Nullable; public class ClientTable implements Table { private final int id; + // TODO: table name can change, this approach should probably be reworked, see https://issues.apache.org/jira/browse/IGNITE-21237. private final String name; private final ReliableChannel ch; diff --git a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java index 770204fd04..faf2db5484 100644 --- a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java +++ b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java @@ -105,6 +105,11 @@ public class FakeInternalTable implements InternalTable { return tableName; } + @Override + public void name(String newName) { + throw new UnsupportedOperationException("Should not be called"); + } + @Override public int partitionId(BinaryRowEx row) { return 0; diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java b/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java index c631642a69..d0bc67282c 100644 --- a/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java +++ b/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java @@ -68,6 +68,14 @@ public interface InternalTable extends ManuallyCloseable { */ String name(); + /** + * Sets the name of the table. + * + * @param newName New name. + */ + // TODO: revisit this approach, see https://issues.apache.org/jira/browse/IGNITE-21235. + void name(String newName); + /** * Extracts an identifier of a partition from a given row. * diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java index 6a5c316a5a..f12ddf0b31 100644 --- a/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java +++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java @@ -133,6 +133,11 @@ public class TableImpl implements TableViewInternal { return tbl.name(); } + // TODO: revisit this approach, see https://issues.apache.org/jira/browse/IGNITE-21235. + public void name(String newName) { + tbl.name(newName); + } + @Override public SchemaRegistry schemaView() { return schemaReg; diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java index ca770df651..976e0f2ae1 100644 --- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java +++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java @@ -88,6 +88,7 @@ import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor; import org.apache.ignite.internal.catalog.events.CatalogEvent; import org.apache.ignite.internal.catalog.events.CreateTableEventParameters; import org.apache.ignite.internal.catalog.events.DropTableEventParameters; +import org.apache.ignite.internal.catalog.events.RenameTableEventParameters; import org.apache.ignite.internal.causality.CompletionListener; import org.apache.ignite.internal.causality.IncrementalVersionedValue; import org.apache.ignite.internal.close.ManuallyCloseable; @@ -535,6 +536,16 @@ public class TableManager implements IgniteTablesInternal, IgniteComponent { return onTableDelete(((DropTableEventParameters) parameters)).thenApply(unused -> false); }); + catalogService.listen(CatalogEvent.TABLE_ALTER, (parameters, exception) -> { + assert exception == null : parameters; + + if (parameters instanceof RenameTableEventParameters) { + return onTableRename((RenameTableEventParameters) parameters).thenApply(unused -> false); + } else { + return falseCompletedFuture(); + } + }); + partitionReplicatorNodeRecovery.start(); }); @@ -584,7 +595,6 @@ public class TableManager implements IgniteTablesInternal, IgniteComponent { }) .toArray(CompletableFuture[]::new); - return allOf(futures) // Simply log any errors, we don't want to block watch processing. .exceptionally(e -> { @@ -643,6 +653,24 @@ public class TableManager implements IgniteTablesInternal, IgniteComponent { }); } + private CompletableFuture<?> onTableRename(RenameTableEventParameters parameters) { + return inBusyLockAsync(busyLock, () -> tablesByIdVv.update( + parameters.causalityToken(), + (tablesById, e) -> { + if (e != null) { + return failedFuture(e); + } + + TableImpl table = tablesById.get(parameters.tableId()); + + // TODO: revisit this approach, see https://issues.apache.org/jira/browse/IGNITE-21235. + table.name(parameters.newTableName()); + + return completedFuture(tablesById); + }) + ); + } + /** * Updates or creates partition raft groups and storages. * diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java index f2b37329f4..6d35322694 100644 --- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java +++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java @@ -136,7 +136,7 @@ public class InternalTableImpl implements InternalTable { private final int partitions; /** Table name. */ - private final String tableName; + private volatile String tableName; /** Table identifier. */ private final int tableId; @@ -244,6 +244,11 @@ public class InternalTableImpl implements InternalTable { return tableName; } + @Override + public void name(String newName) { + this.tableName = newName; + } + /** * Enlists a single row into a transaction. *