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 83224d76e3 IGNITE-21862 Rename PK index when renaming a table (#3518)
83224d76e3 is described below
commit 83224d76e35a736c8dd754550432ecf0cdfd4f8b
Author: Alexander Polovtcev <[email protected]>
AuthorDate: Fri Mar 29 13:08:26 2024 +0200
IGNITE-21862 Rename PK index when renaming a table (#3518)
---
.../internal/catalog/commands/CatalogUtils.java | 38 +++++-
.../catalog/commands/RenameTableCommand.java | 15 ++-
.../internal/catalog/storage/RenameIndexEntry.java | 139 +++++++++++++++++++++
.../CatalogEntrySerializerProvider.java | 2 +
.../serialization/MarshallableEntryType.java | 3 +-
.../internal/catalog/CatalogManagerSelfTest.java | 20 +++
.../commands/RenameTableCommandValidationTest.java | 22 ++++
.../storage/CatalogEntrySerializationTest.java | 12 ++
8 files changed, 247 insertions(+), 4 deletions(-)
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 5864113624..84d397f97e 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
@@ -413,6 +413,23 @@ public class CatalogUtils {
return schema;
}
+ /**
+ * Returns a schema descriptor of the schema with the a given ID.
+ *
+ * @param catalog Catalog to look up the schema in.
+ * @param schemaId Schema ID.
+ * @throws CatalogValidationException If schema does not exist.
+ */
+ public static CatalogSchemaDescriptor schemaOrThrow(Catalog catalog, int
schemaId) throws CatalogValidationException {
+ CatalogSchemaDescriptor schema = catalog.schema(schemaId);
+
+ if (schema == null) {
+ throw new CatalogValidationException(format("Schema with ID '{}'
not found", schemaId));
+ }
+
+ return schema;
+ }
+
/**
* Returns table with given name, or throws {@link
TableNotFoundValidationException} if table with given name not exists.
*
@@ -433,15 +450,32 @@ public class CatalogUtils {
return table;
}
+ /**
+ * Returns a table descriptor of the table with the a given ID.
+ *
+ * @param catalog Catalog to look up the table in.
+ * @param tableId Table ID.
+ * @throws TableNotFoundValidationException If table does not exist.
+ */
+ public static CatalogTableDescriptor tableOrThrow(Catalog catalog, int
tableId) throws TableNotFoundValidationException {
+ CatalogTableDescriptor table = catalog.table(tableId);
+
+ if (table == null) {
+ throw new TableNotFoundValidationException(format("Table with ID
'{}' not found", tableId));
+ }
+
+ return table;
+ }
+
/**
* Returns zone with given name, or throws {@link
CatalogValidationException} if zone with given name not exists.
*
* @param catalog Catalog to look up zone in.
* @param name Name of the zone of interest.
* @return Zone with given name. Never null.
- * @throws CatalogValidationException If zone with given name is not
exists.
+ * @throws DistributionZoneNotFoundValidationException If zone with given
name is not exists.
*/
- public static CatalogZoneDescriptor zoneOrThrow(Catalog catalog, String
name) throws CatalogValidationException {
+ public static CatalogZoneDescriptor zoneOrThrow(Catalog catalog, String
name) throws DistributionZoneNotFoundValidationException {
name = Objects.requireNonNull(name, "zoneName");
CatalogZoneDescriptor zone = catalog.zone(name);
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
index 8bd014cc05..fdb9e1f7e8 100644
---
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
@@ -19,6 +19,8 @@ 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.pkIndexName;
import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.schemaOrThrow;
import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.tableOrThrow;
@@ -26,8 +28,10 @@ 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.descriptors.CatalogTableDescriptor;
+import org.apache.ignite.internal.catalog.storage.RenameIndexEntry;
import org.apache.ignite.internal.catalog.storage.RenameTableEntry;
import org.apache.ignite.internal.catalog.storage.UpdateEntry;
@@ -58,7 +62,16 @@ public class RenameTableCommand extends AbstractTableCommand
{
CatalogTableDescriptor table = tableOrThrow(schema, tableName);
- return List.of(new RenameTableEntry(table.id(), newTableName));
+ String newPkIndexName = pkIndexName(newTableName);
+
+ ensureNoTableIndexOrSysViewExistsWithGivenName(schema, newPkIndexName);
+
+ CatalogIndexDescriptor pkIndex = indexOrThrow(catalog,
table.primaryKeyIndexId());
+
+ return List.of(
+ new RenameTableEntry(table.id(), newTableName),
+ new RenameIndexEntry(pkIndex.id(), newPkIndexName)
+ );
}
private static class Builder implements RenameTableCommandBuilder {
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/RenameIndexEntry.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/RenameIndexEntry.java
new file mode 100644
index 0000000000..dabf422815
--- /dev/null
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/RenameIndexEntry.java
@@ -0,0 +1,139 @@
+/*
+ * 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
org.apache.ignite.internal.catalog.commands.CatalogUtils.indexOrThrow;
+import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.replaceIndex;
+import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.replaceSchema;
+import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.schemaOrThrow;
+import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.tableOrThrow;
+import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
+
+import java.io.IOException;
+import org.apache.ignite.internal.catalog.Catalog;
+import org.apache.ignite.internal.catalog.CatalogValidationException;
+import
org.apache.ignite.internal.catalog.descriptors.CatalogHashIndexDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
+import
org.apache.ignite.internal.catalog.descriptors.CatalogSortedIndexDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
+import
org.apache.ignite.internal.catalog.storage.serialization.CatalogObjectSerializer;
+import
org.apache.ignite.internal.catalog.storage.serialization.MarshallableEntryType;
+import org.apache.ignite.internal.tostring.S;
+import org.apache.ignite.internal.util.io.IgniteDataInput;
+import org.apache.ignite.internal.util.io.IgniteDataOutput;
+
+/** Entry representing a rename of an index. */
+public class RenameIndexEntry implements UpdateEntry {
+ public static final CatalogObjectSerializer<RenameIndexEntry> SERIALIZER =
new RenameIndexEntrySerializer();
+
+ private final int indexId;
+
+ private final String newIndexName;
+
+ public RenameIndexEntry(int indexId, String newIndexName) {
+ this.indexId = indexId;
+ this.newIndexName = newIndexName;
+ }
+
+ @Override
+ public int typeId() {
+ return MarshallableEntryType.RENAME_INDEX.id();
+ }
+
+ @Override
+ public Catalog applyUpdate(Catalog catalog, long causalityToken) {
+ CatalogIndexDescriptor indexDescriptor = indexOrThrow(catalog,
indexId);
+
+ CatalogTableDescriptor tableDescriptor = tableOrThrow(catalog,
indexDescriptor.tableId());
+
+ CatalogSchemaDescriptor schemaDescriptor = schemaOrThrow(catalog,
tableDescriptor.schemaId());
+
+ CatalogIndexDescriptor newIndexDescriptor =
changeIndexName(indexDescriptor, causalityToken);
+
+ return new Catalog(
+ catalog.version(),
+ catalog.time(),
+ catalog.objectIdGenState(),
+ catalog.zones(),
+ replaceSchema(replaceIndex(schemaDescriptor,
newIndexDescriptor), catalog.schemas())
+ );
+ }
+
+ private CatalogIndexDescriptor changeIndexName(CatalogIndexDescriptor
indexDescriptor, long causalityToken) {
+ CatalogIndexDescriptor newIndexDescriptor;
+
+ if (indexDescriptor instanceof CatalogHashIndexDescriptor) {
+ newIndexDescriptor =
changeHashIndexName((CatalogHashIndexDescriptor) indexDescriptor);
+ } else if (indexDescriptor instanceof CatalogSortedIndexDescriptor) {
+ newIndexDescriptor =
changeSortedIndexName((CatalogSortedIndexDescriptor) indexDescriptor);
+ } else {
+ throw new CatalogValidationException(format("Unsupported index
type '{}' {}", indexDescriptor.id(), indexDescriptor));
+ }
+
+ newIndexDescriptor.updateToken(causalityToken);
+
+ return newIndexDescriptor;
+ }
+
+ private CatalogIndexDescriptor
changeHashIndexName(CatalogHashIndexDescriptor index) {
+ return new CatalogHashIndexDescriptor(
+ index.id(),
+ newIndexName,
+ index.tableId(),
+ index.unique(),
+ index.status(),
+ index.txWaitCatalogVersion(),
+ index.columns()
+ );
+ }
+
+ private CatalogIndexDescriptor
changeSortedIndexName(CatalogSortedIndexDescriptor index) {
+ return new CatalogSortedIndexDescriptor(
+ index.id(),
+ newIndexName,
+ index.tableId(),
+ index.unique(),
+ index.status(),
+ index.txWaitCatalogVersion(),
+ index.columns()
+ );
+ }
+
+ @Override
+ public String toString() {
+ return S.toString(this);
+ }
+
+ private static class RenameIndexEntrySerializer implements
CatalogObjectSerializer<RenameIndexEntry> {
+ @Override
+ public RenameIndexEntry readFrom(IgniteDataInput input) throws
IOException {
+ int indexId = input.readInt();
+
+ String newIndexName = input.readUTF();
+
+ return new RenameIndexEntry(indexId, newIndexName);
+ }
+
+ @Override
+ public void writeTo(RenameIndexEntry entry, IgniteDataOutput out)
throws IOException {
+ out.writeInt(entry.indexId);
+ out.writeUTF(entry.newIndexName);
+ }
+ }
+}
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/CatalogEntrySerializerProvider.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/CatalogEntrySerializerProvider.java
index 4b11f1af2b..4ab86fcb45 100644
---
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/CatalogEntrySerializerProvider.java
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/CatalogEntrySerializerProvider.java
@@ -33,6 +33,7 @@ import
org.apache.ignite.internal.catalog.storage.NewTableEntry;
import org.apache.ignite.internal.catalog.storage.NewZoneEntry;
import org.apache.ignite.internal.catalog.storage.ObjectIdGenUpdateEntry;
import org.apache.ignite.internal.catalog.storage.RemoveIndexEntry;
+import org.apache.ignite.internal.catalog.storage.RenameIndexEntry;
import org.apache.ignite.internal.catalog.storage.RenameTableEntry;
import org.apache.ignite.internal.catalog.storage.SnapshotEntry;
import org.apache.ignite.internal.catalog.storage.StartBuildingIndexEntry;
@@ -75,6 +76,7 @@ public interface CatalogEntrySerializerProvider {
serializers[MarshallableEntryType.RENAME_TABLE.id()] =
RenameTableEntry.SERIALIZER;
serializers[MarshallableEntryType.ID_GENERATOR.id()] =
ObjectIdGenUpdateEntry.SERIALIZER;
serializers[MarshallableEntryType.SNAPSHOT.id()] =
SnapshotEntry.SERIALIZER;
+ serializers[MarshallableEntryType.RENAME_INDEX.id()] =
RenameIndexEntry.SERIALIZER;
//noinspection ThisEscapedInObjectConstruction
serializers[MarshallableEntryType.VERSIONED_UPDATE.id()] = new
VersionedUpdateSerializer(this);
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/MarshallableEntryType.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/MarshallableEntryType.java
index 19f3b75d64..c18175d437 100644
---
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/MarshallableEntryType.java
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/MarshallableEntryType.java
@@ -38,7 +38,8 @@ public enum MarshallableEntryType {
RENAME_TABLE(14),
ID_GENERATOR(15),
SNAPSHOT(16),
- VERSIONED_UPDATE(17);
+ VERSIONED_UPDATE(17),
+ RENAME_INDEX(18);
/** Type ID. */
private final int id;
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 d469b4eb2b..6b885f03e6 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
@@ -2386,6 +2386,26 @@ public class CatalogManagerSelfTest extends
BaseCatalogManagerTest {
assertThat(curDescriptor.schemaId(), is(prevDescriptor.schemaId()));
}
+ @Test
+ void testTableRenameAndCreateTableWithSameName() {
+ createSomeTable(TABLE_NAME);
+
+ CatalogCommand command = RenameTableCommand.builder()
+ .schemaName(SCHEMA_NAME)
+ .tableName(TABLE_NAME)
+ .newTableName(TABLE_NAME_2)
+ .build();
+
+ assertThat(manager.execute(command), willCompleteSuccessfully());
+
+ createSomeTable(TABLE_NAME);
+
+ int catalogVersion = manager.latestCatalogVersion();
+
+ assertThat(table(catalogVersion, TABLE_NAME), is(notNullValue()));
+ assertThat(table(catalogVersion, TABLE_NAME_2), is(notNullValue()));
+ }
+
@Test
void testTableRenameFiresEvent() {
createSomeTable(TABLE_NAME);
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
index 891a8f2d76..ee13d1f194 100644
---
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
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.catalog.commands;
+import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.pkIndexName;
import static
org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrows;
import static
org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrowsWithCause;
@@ -144,4 +145,25 @@ public class RenameTableCommandValidationTest extends
AbstractCommandValidationT
"Operations with reserved schemas are not allowed"
);
}
+
+ @Test
+ void exceptionIsThrownIfPkIndexWithNewNameExists() {
+ Catalog catalog = catalog(
+ createTableCommand("TEST"),
+ createTableCommand("TEST3"),
+ createIndexCommand("TEST3", pkIndexName("TEST2"))
+ );
+
+ CatalogCommand command = RenameTableCommand.builder()
+ .schemaName(SCHEMA_NAME)
+ .tableName("TEST")
+ .newTableName("TEST2")
+ .build();
+
+ assertThrows(
+ CatalogValidationException.class,
+ () -> command.get(catalog),
+ String.format("Index with name 'PUBLIC.%s' already exists",
pkIndexName("TEST2"))
+ );
+ }
}
diff --git
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
index 899413dac1..ca881e1784 100644
---
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
+++
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
@@ -130,6 +130,10 @@ public class CatalogEntrySerializationTest extends
BaseIgniteAbstractTest {
snapshotEntry();
break;
+ case RENAME_INDEX:
+ renameIndexEntry();
+ break;
+
default:
throw new UnsupportedOperationException("Test not implemented
" + type);
}
@@ -337,6 +341,14 @@ public class CatalogEntrySerializationTest extends
BaseIgniteAbstractTest {
BDDAssertions.assertThat(deserialized).usingRecursiveComparison().isEqualTo(entry);
}
+ private void renameIndexEntry() {
+ var entry = new RenameIndexEntry(1, "newName");
+
+ VersionedUpdate update = newVersionedUpdate(entry);
+
+ assertVersionedUpdate(update, serialize(update));
+ }
+
private VersionedUpdate serialize(VersionedUpdate update) {
byte[] bytes = marshaller.marshall(update);
return (VersionedUpdate) marshaller.unmarshall(bytes);