From 12885d21d270effe70498e87bbea109f974dbca4 Mon Sep 17 00:00:00 2001 From: Kodai Doki Date: Sun, 21 Sep 2025 16:48:11 +0900 Subject: [PATCH 1/6] Add rename table --- ...raAdminCaseSensitivityIntegrationTest.java | 12 ++ .../CassandraAdminIntegrationTest.java | 12 ++ ...mmitAdminIntegrationTestWithCassandra.java | 12 ++ ...tionAdminIntegrationTestWithCassandra.java | 12 ++ ...sCommitAdminIntegrationTestWithCosmos.java | 12 ++ ...osAdminCaseSensitivityIntegrationTest.java | 12 ++ .../cosmos/CosmosAdminIntegrationTest.java | 12 ++ ...sactionAdminIntegrationTestWithCosmos.java | 12 ++ ...sCommitAdminIntegrationTestWithDynamo.java | 12 ++ ...moAdminCaseSensitivityIntegrationTest.java | 12 ++ .../dynamo/DynamoAdminIntegrationTest.java | 12 ++ ...sactionAdminIntegrationTestWithDynamo.java | 12 ++ .../main/java/com/scalar/db/api/Admin.java | 13 ++ .../common/CommonDistributedStorageAdmin.java | 27 +++ .../java/com/scalar/db/common/CoreError.java | 12 ++ .../DecoratedDistributedTransactionAdmin.java | 6 + .../com/scalar/db/service/AdminService.java | 6 + .../db/storage/cassandra/CassandraAdmin.java | 7 + .../scalar/db/storage/cosmos/CosmosAdmin.java | 7 + .../scalar/db/storage/dynamo/DynamoAdmin.java | 7 + .../com/scalar/db/storage/jdbc/JdbcAdmin.java | 21 +++ .../scalar/db/storage/jdbc/RdbEngineDb2.java | 8 + .../db/storage/jdbc/RdbEngineMysql.java | 8 + .../db/storage/jdbc/RdbEngineOracle.java | 8 + .../db/storage/jdbc/RdbEnginePostgresql.java | 8 + .../db/storage/jdbc/RdbEngineSqlServer.java | 11 +- .../db/storage/jdbc/RdbEngineSqlite.java | 8 + .../db/storage/jdbc/RdbEngineStrategy.java | 2 + .../multistorage/MultiStorageAdmin.java | 6 + .../consensuscommit/ConsensusCommitAdmin.java | 14 ++ .../jdbc/JdbcTransactionAdmin.java | 6 + .../SingleCrudOperationTransactionAdmin.java | 6 + .../storage/cassandra/CassandraAdminTest.java | 3 + .../db/storage/cosmos/CosmosAdminTest.java | 2 + .../storage/dynamo/DynamoAdminTestBase.java | 2 + .../scalar/db/storage/jdbc/JdbcAdminTest.java | 155 +++++++++++++++++- .../multistorage/MultiStorageAdminTest.java | 60 +++++++ .../ConsensusCommitAdminTestBase.java | 18 ++ .../jdbc/JdbcTransactionAdminTest.java | 14 ++ ...ngleCrudOperationTransactionAdminTest.java | 14 ++ ...ibutedStorageAdminIntegrationTestBase.java | 61 +++++++ ...ageAdminPermissionIntegrationTestBase.java | 12 ++ ...edTransactionAdminIntegrationTestBase.java | 61 +++++++ 43 files changed, 735 insertions(+), 2 deletions(-) diff --git a/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminCaseSensitivityIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminCaseSensitivityIntegrationTest.java index c596f503bd..85aab1817a 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminCaseSensitivityIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminCaseSensitivityIntegrationTest.java @@ -76,4 +76,16 @@ public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() admin.dropTable(getNamespace1(), getTable4(), true); } } + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminIntegrationTest.java index 6c0ffc90a2..db4bfc1ebf 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminIntegrationTest.java @@ -75,4 +75,16 @@ public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() admin.dropTable(getNamespace1(), getTable4(), true); } } + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cassandra/ConsensusCommitAdminIntegrationTestWithCassandra.java b/core/src/integration-test/java/com/scalar/db/storage/cassandra/ConsensusCommitAdminIntegrationTestWithCassandra.java index b4b0cdf60f..f1f0ad298c 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cassandra/ConsensusCommitAdminIntegrationTestWithCassandra.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cassandra/ConsensusCommitAdminIntegrationTestWithCassandra.java @@ -75,4 +75,16 @@ public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() admin.dropTable(namespace1, TABLE4, true); } } + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cassandra/SingleCrudOperationTransactionAdminIntegrationTestWithCassandra.java b/core/src/integration-test/java/com/scalar/db/storage/cassandra/SingleCrudOperationTransactionAdminIntegrationTestWithCassandra.java index 89c268425e..2c69a7c26d 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cassandra/SingleCrudOperationTransactionAdminIntegrationTestWithCassandra.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cassandra/SingleCrudOperationTransactionAdminIntegrationTestWithCassandra.java @@ -70,4 +70,16 @@ public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() admin.dropTable(namespace1, TABLE4, true); } } + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cosmos/ConsensusCommitAdminIntegrationTestWithCosmos.java b/core/src/integration-test/java/com/scalar/db/storage/cosmos/ConsensusCommitAdminIntegrationTestWithCosmos.java index c164a406c5..89ce2a32df 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cosmos/ConsensusCommitAdminIntegrationTestWithCosmos.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cosmos/ConsensusCommitAdminIntegrationTestWithCosmos.java @@ -67,4 +67,16 @@ public void renameColumn_ForPrimaryKeyColumn_ShouldRenameColumnCorrectly() {} @Override @Disabled("Cosmos DB does not support renaming columns") public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminCaseSensitivityIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminCaseSensitivityIntegrationTest.java index f0b4f67010..b4db8450ad 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminCaseSensitivityIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminCaseSensitivityIntegrationTest.java @@ -67,4 +67,16 @@ public void renameColumn_ForPrimaryKeyColumn_ShouldRenameColumnCorrectly() {} @Override @Disabled("Cosmos DB does not support renaming columns") public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminIntegrationTest.java index 1b44f8a619..cf7861c1b0 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminIntegrationTest.java @@ -66,4 +66,16 @@ public void renameColumn_ForPrimaryKeyColumn_ShouldRenameColumnCorrectly() {} @Override @Disabled("Cosmos DB does not support renaming columns") public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cosmos/SingleCrudOperationTransactionAdminIntegrationTestWithCosmos.java b/core/src/integration-test/java/com/scalar/db/storage/cosmos/SingleCrudOperationTransactionAdminIntegrationTestWithCosmos.java index e8c66ac747..06e0cd5972 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cosmos/SingleCrudOperationTransactionAdminIntegrationTestWithCosmos.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cosmos/SingleCrudOperationTransactionAdminIntegrationTestWithCosmos.java @@ -61,4 +61,16 @@ public void renameColumn_ForPrimaryKeyColumn_ShouldRenameColumnCorrectly() {} @Override @Disabled("Cosmos DB does not support renaming columns") public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/dynamo/ConsensusCommitAdminIntegrationTestWithDynamo.java b/core/src/integration-test/java/com/scalar/db/storage/dynamo/ConsensusCommitAdminIntegrationTestWithDynamo.java index f9e91e6f48..7a2d15a5c9 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/dynamo/ConsensusCommitAdminIntegrationTestWithDynamo.java +++ b/core/src/integration-test/java/com/scalar/db/storage/dynamo/ConsensusCommitAdminIntegrationTestWithDynamo.java @@ -72,4 +72,16 @@ public void renameColumn_ForPrimaryKeyColumn_ShouldRenameColumnCorrectly() {} @Override @Disabled("DynamoDB does not support renaming columns") public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminCaseSensitivityIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminCaseSensitivityIntegrationTest.java index d04d2eb196..e133aac658 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminCaseSensitivityIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminCaseSensitivityIntegrationTest.java @@ -72,4 +72,16 @@ public void renameColumn_ForPrimaryKeyColumn_ShouldRenameColumnCorrectly() {} @Override @Disabled("DynamoDB does not support renaming columns") public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminIntegrationTest.java index ec8c49b585..fbdf73dd97 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminIntegrationTest.java @@ -71,4 +71,16 @@ public void renameColumn_ForPrimaryKeyColumn_ShouldRenameColumnCorrectly() {} @Override @Disabled("DynamoDB does not support renaming columns") public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/dynamo/SingleCrudOperationTransactionAdminIntegrationTestWithDynamo.java b/core/src/integration-test/java/com/scalar/db/storage/dynamo/SingleCrudOperationTransactionAdminIntegrationTestWithDynamo.java index e92a5e1888..f8f2b9b210 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/dynamo/SingleCrudOperationTransactionAdminIntegrationTestWithDynamo.java +++ b/core/src/integration-test/java/com/scalar/db/storage/dynamo/SingleCrudOperationTransactionAdminIntegrationTestWithDynamo.java @@ -66,4 +66,16 @@ public void renameColumn_ForPrimaryKeyColumn_ShouldRenameColumnCorrectly() {} @Override @Disabled("DynamoDB does not support renaming columns") public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} } diff --git a/core/src/main/java/com/scalar/db/api/Admin.java b/core/src/main/java/com/scalar/db/api/Admin.java index 729853d06a..5c6f39822d 100644 --- a/core/src/main/java/com/scalar/db/api/Admin.java +++ b/core/src/main/java/com/scalar/db/api/Admin.java @@ -534,6 +534,19 @@ default void dropColumnFromTable( void renameColumn(String namespace, String table, String oldColumnName, String newColumnName) throws ExecutionException; + /** + * Renames an existing table. + * + * @param namespace the table namespace + * @param oldTableName the current name of the table to rename + * @param newTableName the new name of the table + * @throws IllegalArgumentException if the table to rename does not exist or the new table already + * exists + * @throws ExecutionException if the operation fails + */ + void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException; + /** * Imports an existing table that is not managed by ScalarDB. * diff --git a/core/src/main/java/com/scalar/db/common/CommonDistributedStorageAdmin.java b/core/src/main/java/com/scalar/db/common/CommonDistributedStorageAdmin.java index 1758c297ae..73dc9a4c35 100644 --- a/core/src/main/java/com/scalar/db/common/CommonDistributedStorageAdmin.java +++ b/core/src/main/java/com/scalar/db/common/CommonDistributedStorageAdmin.java @@ -363,6 +363,33 @@ public void renameColumn( } } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + TableMetadata tableMetadata = getTableMetadata(namespace, oldTableName); + if (tableMetadata == null) { + throw new IllegalArgumentException( + CoreError.TABLE_NOT_FOUND.buildMessage( + ScalarDbUtils.getFullTableName(namespace, oldTableName))); + } + + if (tableExists(namespace, newTableName)) { + throw new IllegalArgumentException( + CoreError.TABLE_ALREADY_EXISTS.buildMessage( + ScalarDbUtils.getFullTableName(namespace, newTableName))); + } + + try { + admin.renameTable(namespace, oldTableName, newTableName); + } catch (ExecutionException e) { + throw new ExecutionException( + CoreError.RENAMING_TABLE_FAILED.buildMessage( + ScalarDbUtils.getFullTableName(namespace, oldTableName), + ScalarDbUtils.getFullTableName(namespace, newTableName)), + e); + } + } + @Override public Set getNamespaceNames() throws ExecutionException { try { diff --git a/core/src/main/java/com/scalar/db/common/CoreError.java b/core/src/main/java/com/scalar/db/common/CoreError.java index 4137040b22..9fedb991d5 100644 --- a/core/src/main/java/com/scalar/db/common/CoreError.java +++ b/core/src/main/java/com/scalar/db/common/CoreError.java @@ -736,6 +736,12 @@ public enum CoreError implements ScalarDbError { "The BOOLEAN type is not supported for index columns in DynamoDB. Column: %s", "", ""), + CASSANDRA_RENAME_TABLE_NOT_SUPPORTED( + Category.USER_ERROR, "0227", "Renaming tables is not supported in Cassandra", "", ""), + COSMOS_RENAME_TABLE_NOT_SUPPORTED( + Category.USER_ERROR, "0228", "Renaming tables is not supported in Cosmos DB", "", ""), + DYNAMO_RENAME_TABLE_NOT_SUPPORTED( + Category.USER_ERROR, "0229", "Renaming tables is not supported in DynamoDB", "", ""), // // Errors for the concurrency error category @@ -1030,6 +1036,12 @@ public enum CoreError implements ScalarDbError { "Renaming a column failed. Table: %s; Old column name: %s; New column name: %s", "", ""), + RENAMING_TABLE_FAILED( + Category.INTERNAL_ERROR, + "0061", + "Renaming a table failed. Old table name: %s; New table name: %s", + "", + ""), // // Errors for the unknown transaction status error category diff --git a/core/src/main/java/com/scalar/db/common/DecoratedDistributedTransactionAdmin.java b/core/src/main/java/com/scalar/db/common/DecoratedDistributedTransactionAdmin.java index e8954c002b..e0206f6c83 100644 --- a/core/src/main/java/com/scalar/db/common/DecoratedDistributedTransactionAdmin.java +++ b/core/src/main/java/com/scalar/db/common/DecoratedDistributedTransactionAdmin.java @@ -228,6 +228,12 @@ public void renameColumn( distributedTransactionAdmin.renameColumn(namespace, table, oldColumnName, newColumnName); } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + distributedTransactionAdmin.renameTable(namespace, oldTableName, newTableName); + } + @Override public void importTable(String namespace, String table, Map options) throws ExecutionException { diff --git a/core/src/main/java/com/scalar/db/service/AdminService.java b/core/src/main/java/com/scalar/db/service/AdminService.java index 9f198dde3b..863a73606f 100644 --- a/core/src/main/java/com/scalar/db/service/AdminService.java +++ b/core/src/main/java/com/scalar/db/service/AdminService.java @@ -107,6 +107,12 @@ public void renameColumn( admin.renameColumn(namespace, table, oldColumnName, newColumnName); } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + admin.renameTable(namespace, oldTableName, newTableName); + } + @Override public TableMetadata getImportTableMetadata( String namespace, String table, Map overrideColumnsType) diff --git a/core/src/main/java/com/scalar/db/storage/cassandra/CassandraAdmin.java b/core/src/main/java/com/scalar/db/storage/cassandra/CassandraAdmin.java index 63f7383fbf..4cfd364784 100644 --- a/core/src/main/java/com/scalar/db/storage/cassandra/CassandraAdmin.java +++ b/core/src/main/java/com/scalar/db/storage/cassandra/CassandraAdmin.java @@ -471,6 +471,13 @@ oldColumnName, newColumnName, getFullTableName(namespace, table)), } } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + throw new UnsupportedOperationException( + CoreError.CASSANDRA_RENAME_TABLE_NOT_SUPPORTED.buildMessage()); + } + @Override public Set getNamespaceNames() throws ExecutionException { try { diff --git a/core/src/main/java/com/scalar/db/storage/cosmos/CosmosAdmin.java b/core/src/main/java/com/scalar/db/storage/cosmos/CosmosAdmin.java index 9efa458369..c2d733e593 100644 --- a/core/src/main/java/com/scalar/db/storage/cosmos/CosmosAdmin.java +++ b/core/src/main/java/com/scalar/db/storage/cosmos/CosmosAdmin.java @@ -658,6 +658,13 @@ public void renameColumn( CoreError.COSMOS_RENAME_COLUMN_NOT_SUPPORTED.buildMessage()); } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + throw new UnsupportedOperationException( + CoreError.COSMOS_RENAME_TABLE_NOT_SUPPORTED.buildMessage()); + } + @Override public TableMetadata getImportTableMetadata( String namespace, String table, Map overrideColumnsType) { diff --git a/core/src/main/java/com/scalar/db/storage/dynamo/DynamoAdmin.java b/core/src/main/java/com/scalar/db/storage/dynamo/DynamoAdmin.java index b1415dda82..67b736c30e 100644 --- a/core/src/main/java/com/scalar/db/storage/dynamo/DynamoAdmin.java +++ b/core/src/main/java/com/scalar/db/storage/dynamo/DynamoAdmin.java @@ -1451,6 +1451,13 @@ public void renameColumn( CoreError.DYNAMO_RENAME_COLUMN_NOT_SUPPORTED.buildMessage()); } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + throw new UnsupportedOperationException( + CoreError.DYNAMO_RENAME_TABLE_NOT_SUPPORTED.buildMessage()); + } + @Override public TableMetadata getImportTableMetadata( String namespace, String table, Map overrideColumnsType) { diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java b/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java index dda73607e7..5f6ea70db9 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java @@ -927,6 +927,27 @@ oldColumnName, newColumnName, getFullTableName(namespace, table)), } } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + try { + TableMetadata tableMetadata = getTableMetadata(namespace, oldTableName); + assert tableMetadata != null; + String renameTableStatement = rdbEngine.renameTableSql(namespace, oldTableName, newTableName); + try (Connection connection = dataSource.getConnection()) { + execute(connection, renameTableStatement); + execute(connection, getDeleteTableMetadataStatement(namespace, oldTableName)); + addTableMetadata(connection, namespace, newTableName, tableMetadata, false, false); + } + } catch (SQLException e) { + throw new ExecutionException( + String.format( + "Renaming the %s table to %s failed", + getFullTableName(namespace, oldTableName), getFullTableName(namespace, newTableName)), + e); + } + } + @Override public void addRawColumnToTable( String namespace, String table, String columnName, DataType columnType) diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java index 882400cab3..ff67d0e048 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java @@ -257,6 +257,14 @@ public String[] dropColumnSql(String namespace, String table, String columnName) }; } + @Override + public String renameTableSql(String namespace, String oldTableName, String newTableName) { + return "RENAME " + + encloseFullTableName(namespace, oldTableName) + + " TO " + + enclose(newTableName); + } + @Override public String alterColumnTypeSql( String namespace, String table, String columnName, String columnType) { diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineMysql.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineMysql.java index a8c35b5f57..f0b209fb0d 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineMysql.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineMysql.java @@ -131,6 +131,14 @@ public String renameColumnSql( + columnType; } + @Override + public String renameTableSql(String namespace, String oldTableName, String newTableName) { + return "ALTER TABLE " + + encloseFullTableName(namespace, oldTableName) + + " RENAME TO " + + encloseFullTableName(namespace, newTableName); + } + @Override public String alterColumnTypeSql( String namespace, String table, String columnName, String columnType) { diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineOracle.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineOracle.java index 6b16df9684..2a5281d84e 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineOracle.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineOracle.java @@ -127,6 +127,14 @@ public void dropNamespaceTranslateSQLException(SQLException e, String namespace) throw new ExecutionException("Dropping the user failed: " + namespace, e); } + @Override + public String renameTableSql(String namespace, String oldTableName, String newTableName) { + return "ALTER TABLE " + + encloseFullTableName(namespace, oldTableName) + + " RENAME TO " + + enclose(newTableName); + } + @Override public String alterColumnTypeSql( String namespace, String table, String columnName, String columnType) { diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEnginePostgresql.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEnginePostgresql.java index fb76b2d48f..c767c4a886 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEnginePostgresql.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEnginePostgresql.java @@ -111,6 +111,14 @@ public void dropNamespaceTranslateSQLException(SQLException e, String namespace) throw new ExecutionException("Dropping the schema failed: " + namespace, e); } + @Override + public String renameTableSql(String namespace, String oldTableName, String newTableName) { + return "ALTER TABLE " + + encloseFullTableName(namespace, oldTableName) + + " RENAME TO " + + enclose(newTableName); + } + @Override public String alterColumnTypeSql( String namespace, String table, String columnName, String columnType) { diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java index 6bec004bba..27491820f0 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java @@ -113,10 +113,19 @@ public String renameColumnSql( + "." + enclose(oldColumnName) + "', '" - + newColumnName + + enclose(newColumnName) + "', 'COLUMN'"; } + @Override + public String renameTableSql(String namespace, String oldTableName, String newTableName) { + return "EXEC sp_rename '" + + encloseFullTableName(namespace, oldTableName) + + "', '" + + enclose(newTableName) + + "'"; + } + @Override public String alterColumnTypeSql( String namespace, String table, String columnName, String columnType) { diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlite.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlite.java index 4d04335b74..ca316b8fac 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlite.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlite.java @@ -249,6 +249,14 @@ public void dropNamespaceTranslateSQLException(SQLException e, String namespace) throw new AssertionError("DropNamespace never happen in SQLite implementation"); } + @Override + public String renameTableSql(String namespace, String oldTableName, String newTableName) { + return "ALTER TABLE " + + encloseFullTableName(namespace, oldTableName) + + " RENAME TO " + + encloseFullTableName(namespace, newTableName); + } + @Override public String alterColumnTypeSql( String namespace, String table, String columnName, String columnType) { diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java index b0826ceeb0..526c2452dc 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java @@ -121,6 +121,8 @@ default String renameColumnSql( + enclose(newColumnName); } + String renameTableSql(String namespace, String oldTableName, String newTableName); + String alterColumnTypeSql(String namespace, String table, String columnName, String columnType); String tableExistsInternalTableCheckSql(String fullTableName); diff --git a/core/src/main/java/com/scalar/db/storage/multistorage/MultiStorageAdmin.java b/core/src/main/java/com/scalar/db/storage/multistorage/MultiStorageAdmin.java index d04a58a6ea..b5175dbc36 100644 --- a/core/src/main/java/com/scalar/db/storage/multistorage/MultiStorageAdmin.java +++ b/core/src/main/java/com/scalar/db/storage/multistorage/MultiStorageAdmin.java @@ -218,6 +218,12 @@ public void renameColumn( getAdmin(namespace, table).renameColumn(namespace, table, oldColumnName, newColumnName); } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + getAdmin(namespace, oldTableName).renameTable(namespace, oldTableName, newTableName); + } + @Override public TableMetadata getImportTableMetadata( String namespace, String table, Map overrideColumnsType) diff --git a/core/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdmin.java b/core/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdmin.java index e25ec4eb97..99dc4f1dc3 100644 --- a/core/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdmin.java +++ b/core/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdmin.java @@ -277,6 +277,20 @@ public void renameColumn( } } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + checkNamespace(namespace); + + TableMetadata tableMetadata = getTableMetadata(namespace, oldTableName); + if (tableMetadata == null) { + throw new IllegalArgumentException( + CoreError.TABLE_NOT_FOUND.buildMessage( + ScalarDbUtils.getFullTableName(namespace, oldTableName))); + } + admin.renameTable(namespace, oldTableName, newTableName); + } + @Override public Set getNamespaceNames() throws ExecutionException { return admin.getNamespaceNames().stream() diff --git a/core/src/main/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdmin.java b/core/src/main/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdmin.java index ed9d9f5150..b5b3fa6799 100644 --- a/core/src/main/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdmin.java +++ b/core/src/main/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdmin.java @@ -173,6 +173,12 @@ public void renameColumn( jdbcAdmin.renameColumn(namespace, table, oldColumnName, newColumnName); } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + jdbcAdmin.renameTable(namespace, oldTableName, newTableName); + } + @Override public Set getNamespaceNames() throws ExecutionException { return jdbcAdmin.getNamespaceNames(); diff --git a/core/src/main/java/com/scalar/db/transaction/singlecrudoperation/SingleCrudOperationTransactionAdmin.java b/core/src/main/java/com/scalar/db/transaction/singlecrudoperation/SingleCrudOperationTransactionAdmin.java index 64d3e520aa..70c9b21507 100644 --- a/core/src/main/java/com/scalar/db/transaction/singlecrudoperation/SingleCrudOperationTransactionAdmin.java +++ b/core/src/main/java/com/scalar/db/transaction/singlecrudoperation/SingleCrudOperationTransactionAdmin.java @@ -122,6 +122,12 @@ public void renameColumn( distributedStorageAdmin.renameColumn(namespace, table, oldColumnName, newColumnName); } + @Override + public void renameTable(String namespace, String oldTableName, String newTableName) + throws ExecutionException { + distributedStorageAdmin.renameTable(namespace, oldTableName, newTableName); + } + @Override public Set getNamespaceNames() throws ExecutionException { return distributedStorageAdmin.getNamespaceNames(); diff --git a/core/src/test/java/com/scalar/db/storage/cassandra/CassandraAdminTest.java b/core/src/test/java/com/scalar/db/storage/cassandra/CassandraAdminTest.java index b1fdca6eff..abd5eef2cf 100644 --- a/core/src/test/java/com/scalar/db/storage/cassandra/CassandraAdminTest.java +++ b/core/src/test/java/com/scalar/db/storage/cassandra/CassandraAdminTest.java @@ -984,11 +984,14 @@ public void unsupportedOperations_ShouldThrowUnsupportedException() { () -> cassandraAdmin.importTable( namespace, table, Collections.emptyMap(), Collections.emptyMap())); + Throwable thrown4 = + catchThrowable(() -> cassandraAdmin.renameTable(namespace, table, "new_table")); // Assert assertThat(thrown1).isInstanceOf(UnsupportedOperationException.class); assertThat(thrown2).isInstanceOf(UnsupportedOperationException.class); assertThat(thrown3).isInstanceOf(UnsupportedOperationException.class); + assertThat(thrown4).isInstanceOf(UnsupportedOperationException.class); } @Test diff --git a/core/src/test/java/com/scalar/db/storage/cosmos/CosmosAdminTest.java b/core/src/test/java/com/scalar/db/storage/cosmos/CosmosAdminTest.java index c45f99fb1e..682e5c5a6c 100644 --- a/core/src/test/java/com/scalar/db/storage/cosmos/CosmosAdminTest.java +++ b/core/src/test/java/com/scalar/db/storage/cosmos/CosmosAdminTest.java @@ -1152,6 +1152,7 @@ public void unsupportedOperations_ShouldThrowUnsupportedException() { Throwable thrown4 = catchThrowable(() -> admin.dropColumnFromTable(namespace, table, column)); Throwable thrown5 = catchThrowable(() -> admin.renameColumn(namespace, table, column, "newCol")); + Throwable thrown6 = catchThrowable(() -> admin.renameTable(namespace, table, "newTable")); // Assert assertThat(thrown1).isInstanceOf(UnsupportedOperationException.class); @@ -1159,6 +1160,7 @@ public void unsupportedOperations_ShouldThrowUnsupportedException() { assertThat(thrown3).isInstanceOf(UnsupportedOperationException.class); assertThat(thrown4).isInstanceOf(UnsupportedOperationException.class); assertThat(thrown5).isInstanceOf(UnsupportedOperationException.class); + assertThat(thrown6).isInstanceOf(UnsupportedOperationException.class); } @Test diff --git a/core/src/test/java/com/scalar/db/storage/dynamo/DynamoAdminTestBase.java b/core/src/test/java/com/scalar/db/storage/dynamo/DynamoAdminTestBase.java index 9f48489cb8..50a221ff2b 100644 --- a/core/src/test/java/com/scalar/db/storage/dynamo/DynamoAdminTestBase.java +++ b/core/src/test/java/com/scalar/db/storage/dynamo/DynamoAdminTestBase.java @@ -1719,6 +1719,7 @@ public void unsupportedOperations_ShouldThrowUnsupportedException() { NAMESPACE, TABLE, Collections.emptyMap(), Collections.emptyMap())); Throwable thrown4 = catchThrowable(() -> admin.dropColumnFromTable(NAMESPACE, TABLE, "c1")); Throwable thrown5 = catchThrowable(() -> admin.renameColumn(NAMESPACE, TABLE, "c1", "c2")); + Throwable thrown6 = catchThrowable(() -> admin.renameTable(NAMESPACE, TABLE, "new_table")); // Assert assertThat(thrown1).isInstanceOf(UnsupportedOperationException.class); @@ -1726,6 +1727,7 @@ public void unsupportedOperations_ShouldThrowUnsupportedException() { assertThat(thrown3).isInstanceOf(UnsupportedOperationException.class); assertThat(thrown4).isInstanceOf(UnsupportedOperationException.class); assertThat(thrown5).isInstanceOf(UnsupportedOperationException.class); + assertThat(thrown6).isInstanceOf(UnsupportedOperationException.class); } @Test diff --git a/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java b/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java index ab22b91d7a..4e8c4918bb 100644 --- a/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java +++ b/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java @@ -3143,7 +3143,7 @@ public void renameColumn_ForSqlServer_ShouldWorkProperly() "SELECT [column_name],[data_type],[key_type],[clustering_order],[indexed] FROM [" + METADATA_SCHEMA + "].[metadata] WHERE [full_table_name]=? ORDER BY [ordinal_position] ASC", - "EXEC sp_rename '[ns].[table].[c2]', 'c3', 'COLUMN'", + "EXEC sp_rename '[ns].[table].[c2]', '[c3]', 'COLUMN'", "DELETE FROM [" + METADATA_SCHEMA + "].[metadata] WHERE [full_table_name] = 'ns.table'", "INSERT INTO [" + METADATA_SCHEMA @@ -3233,6 +3233,159 @@ private void renameColumn_ForX_ShouldWorkProperly( } } + @Test + public void renameTable_ForMysql_ShouldWorkProperly() throws SQLException, ExecutionException { + renameTable_ForX_ShouldWorkProperly( + RdbEngine.MYSQL, + "SELECT `column_name`,`data_type`,`key_type`,`clustering_order`,`indexed` FROM `" + + METADATA_SCHEMA + + "`.`metadata` WHERE `full_table_name`=? ORDER BY `ordinal_position` ASC", + "ALTER TABLE `ns`.`table` RENAME TO `ns`.`table_new`", + "DELETE FROM `" + METADATA_SCHEMA + "`.`metadata` WHERE `full_table_name` = 'ns.table'", + "INSERT INTO `" + + METADATA_SCHEMA + + "`.`metadata` VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,false,1)", + "INSERT INTO `" + + METADATA_SCHEMA + + "`.`metadata` VALUES ('ns.table_new','c2','INT',NULL,NULL,false,2)"); + } + + @Test + public void renameTable_ForOracle_ShouldWorkProperly() throws SQLException, ExecutionException { + renameTable_ForX_ShouldWorkProperly( + RdbEngine.ORACLE, + "SELECT \"column_name\",\"data_type\",\"key_type\",\"clustering_order\",\"indexed\" FROM \"" + + METADATA_SCHEMA + + "\".\"metadata\" WHERE \"full_table_name\"=? ORDER BY \"ordinal_position\" ASC", + "ALTER TABLE \"ns\".\"table\" RENAME TO \"table_new\"", + "DELETE FROM \"" + + METADATA_SCHEMA + + "\".\"metadata\" WHERE \"full_table_name\" = 'ns.table'", + "INSERT INTO \"" + + METADATA_SCHEMA + + "\".\"metadata\" VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,0,1)", + "INSERT INTO \"" + + METADATA_SCHEMA + + "\".\"metadata\" VALUES ('ns.table_new','c2','INT',NULL,NULL,0,2)"); + } + + @Test + public void renameTable_ForPostgresql_ShouldWorkProperly() + throws SQLException, ExecutionException { + renameTable_ForX_ShouldWorkProperly( + RdbEngine.POSTGRESQL, + "SELECT \"column_name\",\"data_type\",\"key_type\",\"clustering_order\",\"indexed\" FROM \"" + + METADATA_SCHEMA + + "\".\"metadata\" WHERE \"full_table_name\"=? ORDER BY \"ordinal_position\" ASC", + "ALTER TABLE \"ns\".\"table\" RENAME TO \"table_new\"", + "DELETE FROM \"" + + METADATA_SCHEMA + + "\".\"metadata\" WHERE \"full_table_name\" = 'ns.table'", + "INSERT INTO \"" + + METADATA_SCHEMA + + "\".\"metadata\" VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,false,1)", + "INSERT INTO \"" + + METADATA_SCHEMA + + "\".\"metadata\" VALUES ('ns.table_new','c2','INT',NULL,NULL,false,2)"); + } + + @Test + public void renameTable_ForSqlServer_ShouldWorkProperly() + throws SQLException, ExecutionException { + renameTable_ForX_ShouldWorkProperly( + RdbEngine.SQL_SERVER, + "SELECT [column_name],[data_type],[key_type],[clustering_order],[indexed] FROM [" + + METADATA_SCHEMA + + "].[metadata] WHERE [full_table_name]=? ORDER BY [ordinal_position] ASC", + "EXEC sp_rename '[ns].[table]', '[table_new]'", + "DELETE FROM [" + METADATA_SCHEMA + "].[metadata] WHERE [full_table_name] = 'ns.table'", + "INSERT INTO [" + + METADATA_SCHEMA + + "].[metadata] VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,0,1)", + "INSERT INTO [" + + METADATA_SCHEMA + + "].[metadata] VALUES ('ns.table_new','c2','INT',NULL,NULL,0,2)"); + } + + @Test + public void renameTable_ForSqlite_ShouldWorkProperly() throws SQLException, ExecutionException { + renameTable_ForX_ShouldWorkProperly( + RdbEngine.SQLITE, + "SELECT \"column_name\",\"data_type\",\"key_type\",\"clustering_order\",\"indexed\" FROM \"" + + METADATA_SCHEMA + + "$metadata\" WHERE \"full_table_name\"=? ORDER BY \"ordinal_position\" ASC", + "ALTER TABLE \"ns$table\" RENAME TO \"ns$table_new\"", + "DELETE FROM \"" + METADATA_SCHEMA + "$metadata\" WHERE \"full_table_name\" = 'ns.table'", + "INSERT INTO \"" + + METADATA_SCHEMA + + "$metadata\" VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,FALSE,1)", + "INSERT INTO \"" + + METADATA_SCHEMA + + "$metadata\" VALUES ('ns.table_new','c2','INT',NULL,NULL,FALSE,2)"); + } + + @Test + public void renameTable_ForDb2_ShouldWorkProperly() throws SQLException, ExecutionException { + renameTable_ForX_ShouldWorkProperly( + RdbEngine.DB2, + "SELECT \"column_name\",\"data_type\",\"key_type\",\"clustering_order\",\"indexed\" FROM \"" + + METADATA_SCHEMA + + "\".\"metadata\" WHERE \"full_table_name\"=? ORDER BY \"ordinal_position\" ASC", + "RENAME \"ns\".\"table\" TO \"table_new\"", + "DELETE FROM \"" + + METADATA_SCHEMA + + "\".\"metadata\" WHERE \"full_table_name\" = 'ns.table'", + "INSERT INTO \"" + + METADATA_SCHEMA + + "\".\"metadata\" VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,false,1)", + "INSERT INTO \"" + + METADATA_SCHEMA + + "\".\"metadata\" VALUES ('ns.table_new','c2','INT',NULL,NULL,false,2)"); + } + + private void renameTable_ForX_ShouldWorkProperly( + RdbEngine rdbEngine, String expectedGetMetadataStatement, String... expectedSqlStatements) + throws SQLException, ExecutionException { + // Arrange + String namespace = "ns"; + String table = "table"; + String columnName1 = "c1"; + String columnName2 = "c2"; + + PreparedStatement selectStatement = mock(PreparedStatement.class); + ResultSet resultSet = + mockResultSet( + new SelectAllFromMetadataTableResultSetMocker.Row( + columnName1, DataType.TEXT.toString(), "PARTITION", null, false), + new SelectAllFromMetadataTableResultSetMocker.Row( + columnName2, DataType.INT.toString(), null, null, false)); + when(selectStatement.executeQuery()).thenReturn(resultSet); + + when(connection.prepareStatement(any())).thenReturn(selectStatement); + List expectedStatements = new ArrayList<>(); + for (int i = 0; i < expectedSqlStatements.length; i++) { + Statement expectedStatement = mock(Statement.class); + expectedStatements.add(expectedStatement); + } + when(connection.createStatement()) + .thenReturn( + expectedStatements.get(0), + expectedStatements.subList(1, expectedStatements.size()).toArray(new Statement[0])); + + when(dataSource.getConnection()).thenReturn(connection); + JdbcAdmin admin = createJdbcAdminFor(rdbEngine); + + // Act + admin.renameTable(namespace, table, "table_new"); + + // Assert + verify(selectStatement).setString(1, getFullTableName(namespace, table)); + verify(connection).prepareStatement(expectedGetMetadataStatement); + for (int i = 0; i < expectedSqlStatements.length; i++) { + verify(expectedStatements.get(i)).execute(expectedSqlStatements[i]); + } + } + @Test public void getNamespaceNames_forMysql_ShouldReturnNamespaceNames() throws Exception { getNamespaceNames_forX_ShouldReturnNamespaceNames( diff --git a/core/src/test/java/com/scalar/db/storage/multistorage/MultiStorageAdminTest.java b/core/src/test/java/com/scalar/db/storage/multistorage/MultiStorageAdminTest.java index d084a0bafc..50461baeee 100644 --- a/core/src/test/java/com/scalar/db/storage/multistorage/MultiStorageAdminTest.java +++ b/core/src/test/java/com/scalar/db/storage/multistorage/MultiStorageAdminTest.java @@ -625,6 +625,66 @@ public void renameColumn_ForTable1InNamespace2_ShouldCallRenameColumnOfAdmin2() verify(admin2).renameColumn(namespace, table, column1, column2); } + @Test + public void renameTable_ForTable1InNamespace1_ShouldCallRenameTableOfAdmin1() + throws ExecutionException { + // Arrange + String namespace = NAMESPACE1; + String oldTableName = TABLE1; + String newTableName = "new_" + TABLE1; + + // Act + multiStorageAdmin.renameTable(namespace, oldTableName, newTableName); + + // Assert + verify(admin1).renameTable(namespace, oldTableName, newTableName); + } + + @Test + public void renameTable_ForTable2InNamespace1_ShouldShouldCallRenameTableOfAdmin2() + throws ExecutionException { + // Arrange + String namespace = NAMESPACE1; + String oldTableName = TABLE2; + String newTableName = "new_" + TABLE2; + + // Act + multiStorageAdmin.renameTable(namespace, oldTableName, newTableName); + + // Assert + verify(admin2).renameTable(namespace, oldTableName, newTableName); + } + + @Test + public void renameTable_ForTable3InNamespace1_ShouldCallRenameTableOfDefaultAdmin() + throws ExecutionException { + // Arrange + String namespace = NAMESPACE1; + String oldTableName = TABLE3; + String newTableName = "new_" + TABLE3; + + // Act + multiStorageAdmin.renameTable(namespace, oldTableName, newTableName); + + // Assert + verify(admin3).renameTable(namespace, oldTableName, newTableName); + } + + @Test + public void renameTable_ForTable1InNamespace2_ShouldCallRenameTableOfAdmin2() + throws ExecutionException { + // Arrange + String namespace = NAMESPACE2; + String oldTableName = TABLE1; + String newTableName = "new_" + TABLE1; + + // Act + multiStorageAdmin.renameTable(namespace, oldTableName, newTableName); + + // Assert + verify(admin2).renameTable(namespace, oldTableName, newTableName); + } + @Test public void getNamespaceNames_WithExistingNamespacesNotInMapping_ShouldReturnExistingNamespacesInMappingAndFromDefaultAdmin() diff --git a/core/src/test/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdminTestBase.java b/core/src/test/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdminTestBase.java index 670186c9d2..5ed75b3892 100644 --- a/core/src/test/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdminTestBase.java +++ b/core/src/test/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdminTestBase.java @@ -654,6 +654,24 @@ public void renameColumn_ShouldCallJdbcAdminProperly() throws ExecutionException Attribute.BEFORE_PREFIX + newColumnName); } + @Test + public void renameTable_ShouldCallJdbcAdminProperly() throws ExecutionException { + // Arrange + String existingTableName = "tbl1"; + String newTableName = "tbl2"; + TableMetadata tableMetadata = + TableMetadata.newBuilder().addColumn("col1", DataType.INT).addPartitionKey("col1").build(); + when(distributedStorageAdmin.getTableMetadata(NAMESPACE, existingTableName)) + .thenReturn(ConsensusCommitUtils.buildTransactionTableMetadata(tableMetadata)); + + // Act + admin.renameTable(NAMESPACE, existingTableName, newTableName); + + // Assert + verify(distributedStorageAdmin).getTableMetadata(NAMESPACE, existingTableName); + verify(distributedStorageAdmin).renameTable(NAMESPACE, existingTableName, newTableName); + } + @Test public void importTable_ShouldCallStorageAdminProperly() throws ExecutionException { // Arrange diff --git a/core/src/test/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdminTest.java b/core/src/test/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdminTest.java index fd05bdbaf9..b314a6cc31 100644 --- a/core/src/test/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdminTest.java +++ b/core/src/test/java/com/scalar/db/transaction/jdbc/JdbcTransactionAdminTest.java @@ -257,6 +257,20 @@ public void renameColumn_ShouldCallJdbcAdminProperly() throws ExecutionException verify(jdbcAdmin).renameColumn(namespace, table, columnName1, columnName2); } + @Test + public void renameTable_ShouldCallJdbcAdminProperly() throws ExecutionException { + // Arrange + String namespace = "ns"; + String tableName1 = "tbl1"; + String tableName2 = "tbl2"; + + // Act + admin.renameTable(namespace, tableName1, tableName2); + + // Assert + verify(jdbcAdmin).renameTable(namespace, tableName1, tableName2); + } + @Test public void importTable_ShouldCallJdbcAdminProperly() throws ExecutionException { // Arrange diff --git a/core/src/test/java/com/scalar/db/transaction/singlecrudoperation/SingleCrudOperationTransactionAdminTest.java b/core/src/test/java/com/scalar/db/transaction/singlecrudoperation/SingleCrudOperationTransactionAdminTest.java index c01ff28d4a..b3fe834914 100644 --- a/core/src/test/java/com/scalar/db/transaction/singlecrudoperation/SingleCrudOperationTransactionAdminTest.java +++ b/core/src/test/java/com/scalar/db/transaction/singlecrudoperation/SingleCrudOperationTransactionAdminTest.java @@ -263,6 +263,20 @@ public void renameColumn_ShouldCallDistributedStorageAdminProperly() throws Exec verify(distributedStorageAdmin).renameColumn(namespace, table, columnName1, columnName2); } + @Test + public void renameTable_ShouldCallDistributedStorageAdminProperly() throws ExecutionException { + // Arrange + String namespace = "ns"; + String oldTableName = "old_tbl"; + String newTableName = "new_tbl"; + + // Act + admin.renameTable(namespace, oldTableName, newTableName); + + // Assert + verify(distributedStorageAdmin).renameTable(namespace, oldTableName, newTableName); + } + @Test public void importTable_ShouldCallDistributedStorageAdminProperly() throws ExecutionException { // Arrange diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java index a4b3ac9284..33ad772093 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java @@ -1071,6 +1071,33 @@ public void renameColumn_ShouldRenameColumnCorrectly() throws ExecutionException } } + @Test + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() throws ExecutionException { + String newTableName = "new" + getTable4(); + try { + // Arrange + Map options = getCreationOptions(); + TableMetadata currentTableMetadata = + TableMetadata.newBuilder() + .addColumn(getColumnName1(), DataType.INT) + .addColumn(getColumnName2(), DataType.INT) + .addPartitionKey(getColumnName1()) + .build(); + admin.createTable(namespace1, getTable4(), currentTableMetadata, options); + + // Act + admin.renameTable(namespace1, getTable4(), newTableName); + + // Assert + assertThat(admin.tableExists(namespace1, getTable4())).isFalse(); + assertThat(admin.tableExists(namespace1, newTableName)).isTrue(); + assertThat(admin.getTableMetadata(namespace1, newTableName)).isEqualTo(currentTableMetadata); + } finally { + admin.dropTable(namespace1, getTable4(), true); + admin.dropTable(namespace1, newTableName, true); + } + } + @Test public void getNamespaceNames_ShouldReturnCreatedNamespaces() throws ExecutionException { // Arrange @@ -1297,6 +1324,40 @@ public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() } } + @Test + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() { + // Arrange + + // Act Assert + assertThatThrownBy(() -> admin.renameTable(namespace1, getTable4(), "newTableName")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() + throws ExecutionException { + String newTableName = "new" + getTable4(); + try { + // Arrange + Map options = getCreationOptions(); + TableMetadata currentTableMetadata = + TableMetadata.newBuilder() + .addColumn(getColumnName1(), DataType.INT) + .addColumn(getColumnName2(), DataType.INT) + .addPartitionKey(getColumnName1()) + .build(); + admin.createTable(namespace1, getTable4(), currentTableMetadata, options); + admin.createTable(namespace1, newTableName, currentTableMetadata, options); + + // Act Assert + assertThatThrownBy(() -> admin.renameTable(namespace1, getTable4(), newTableName)) + .isInstanceOf(IllegalArgumentException.class); + } finally { + admin.dropTable(namespace1, getTable4(), true); + admin.dropTable(namespace1, newTableName, true); + } + } + @Test public void upgrade_WhenMetadataTableExistsButNotNamespacesTable_ShouldCreateNamespacesTableAndImportExistingNamespaces() diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminPermissionIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminPermissionIntegrationTestBase.java index 8b83527dd5..104ff168ae 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminPermissionIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminPermissionIntegrationTestBase.java @@ -348,6 +348,18 @@ public void renameColumn_WithSufficientPermission_ShouldSucceed() throws Executi .doesNotThrowAnyException(); } + @Test + public void renameTable_WithSufficientPermission_ShouldSucceed() throws ExecutionException { + // Arrange + createNamespaceByRoot(); + createTableByRoot(); + String newTableName = TABLE + "_new"; + + // Act Assert + assertThatCode(() -> adminForNormalUser.renameTable(NAMESPACE, TABLE, newTableName)) + .doesNotThrowAnyException(); + } + @Test public void importTable_WithSufficientPermission_ShouldSucceed() throws Exception { // Arrange diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java index a5877044ba..e9193d3d18 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java @@ -1160,6 +1160,67 @@ public void renameColumn_ForIndexKeyColumn_ShouldRenameColumnAndIndexCorrectly() } } + @Test + public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() throws ExecutionException { + String newTableName = "new" + TABLE4; + try { + // Arrange + Map options = getCreationOptions(); + TableMetadata currentTableMetadata = + TableMetadata.newBuilder() + .addColumn("c1", DataType.INT) + .addColumn("c2", DataType.INT) + .addPartitionKey("c1") + .build(); + admin.createTable(namespace1, TABLE4, currentTableMetadata, options); + + // Act + admin.renameTable(namespace1, TABLE4, newTableName); + + // Assert + assertThat(admin.tableExists(namespace1, TABLE4)).isFalse(); + assertThat(admin.tableExists(namespace1, newTableName)).isTrue(); + assertThat(admin.getTableMetadata(namespace1, newTableName)).isEqualTo(currentTableMetadata); + } finally { + admin.dropTable(namespace1, TABLE4, true); + admin.dropTable(namespace1, newTableName, true); + } + } + + @Test + public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException() { + // Arrange + + // Act Assert + assertThatThrownBy(() -> admin.renameTable(namespace1, TABLE4, "newTableName")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() + throws ExecutionException { + String newTableName = "new" + TABLE4; + try { + // Arrange + Map options = getCreationOptions(); + TableMetadata currentTableMetadata = + TableMetadata.newBuilder() + .addColumn("c1", DataType.INT) + .addColumn("c2", DataType.INT) + .addPartitionKey("c1") + .build(); + admin.createTable(namespace1, TABLE4, currentTableMetadata, options); + admin.createTable(namespace1, newTableName, currentTableMetadata, options); + + // Act Assert + assertThatThrownBy(() -> admin.renameTable(namespace1, TABLE4, newTableName)) + .isInstanceOf(IllegalArgumentException.class); + } finally { + admin.dropTable(namespace1, TABLE4, true); + admin.dropTable(namespace1, newTableName, true); + } + } + @Test public void createCoordinatorTables_ShouldCreateCoordinatorTablesCorrectly() throws ExecutionException { From 7a3f6d7145730c1cbcf21bb980634bddf673b95f Mon Sep 17 00:00:00 2001 From: Kodai Doki Date: Mon, 22 Sep 2025 11:09:44 +0900 Subject: [PATCH 2/6] Fix --- .../CassandraAdminPermissionIntegrationTest.java | 5 +++++ .../dynamo/DynamoAdminPermissionIntegrationTest.java | 5 +++++ core/src/main/java/com/scalar/db/api/Admin.java | 4 ++-- .../scalar/db/storage/jdbc/RdbEngineSqlServer.java | 4 ++-- .../com/scalar/db/storage/jdbc/JdbcAdminTest.java | 4 ++-- .../DistributedStorageAdminIntegrationTestBase.java | 12 ++++++------ ...stributedTransactionAdminIntegrationTestBase.java | 12 ++++++------ 7 files changed, 28 insertions(+), 18 deletions(-) diff --git a/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminPermissionIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminPermissionIntegrationTest.java index c98376f192..b6c1f3960e 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminPermissionIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminPermissionIntegrationTest.java @@ -153,4 +153,9 @@ public void renameColumn_WithSufficientPermission_ShouldSucceed() throws Executi assertThatCode(() -> adminForNormalUser.renameColumn(NAMESPACE, TABLE, COL_NAME1, NEW_COL_NAME)) .doesNotThrowAnyException(); } + + @Test + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_WithSufficientPermission_ShouldSucceed() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminPermissionIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminPermissionIntegrationTest.java index 456cf6b5e4..cec8d1af13 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminPermissionIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminPermissionIntegrationTest.java @@ -69,4 +69,9 @@ public void dropColumnFromTable_WithSufficientPermission_ShouldSucceed() {} @Override @Disabled("DynamoDB does not support renaming columns") public void renameColumn_WithSufficientPermission_ShouldSucceed() {} + + @Test + @Override + @Disabled("DynamoDB does not support renaming columns") + public void renameTable_WithSufficientPermission_ShouldSucceed() {} } diff --git a/core/src/main/java/com/scalar/db/api/Admin.java b/core/src/main/java/com/scalar/db/api/Admin.java index 5c6f39822d..e4a0e810b7 100644 --- a/core/src/main/java/com/scalar/db/api/Admin.java +++ b/core/src/main/java/com/scalar/db/api/Admin.java @@ -540,8 +540,8 @@ void renameColumn(String namespace, String table, String oldColumnName, String n * @param namespace the table namespace * @param oldTableName the current name of the table to rename * @param newTableName the new name of the table - * @throws IllegalArgumentException if the table to rename does not exist or the new table already - * exists + * @throws IllegalArgumentException if the table to rename does not exist or the table with the + * new name already exists * @throws ExecutionException if the operation fails */ void renameTable(String namespace, String oldTableName, String newTableName) diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java index 27491820f0..f741f44f39 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java @@ -113,7 +113,7 @@ public String renameColumnSql( + "." + enclose(oldColumnName) + "', '" - + enclose(newColumnName) + + newColumnName + "', 'COLUMN'"; } @@ -122,7 +122,7 @@ public String renameTableSql(String namespace, String oldTableName, String newTa return "EXEC sp_rename '" + encloseFullTableName(namespace, oldTableName) + "', '" - + enclose(newTableName) + + newTableName + "'"; } diff --git a/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java b/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java index 4e8c4918bb..4139087484 100644 --- a/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java +++ b/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java @@ -3143,7 +3143,7 @@ public void renameColumn_ForSqlServer_ShouldWorkProperly() "SELECT [column_name],[data_type],[key_type],[clustering_order],[indexed] FROM [" + METADATA_SCHEMA + "].[metadata] WHERE [full_table_name]=? ORDER BY [ordinal_position] ASC", - "EXEC sp_rename '[ns].[table].[c2]', '[c3]', 'COLUMN'", + "EXEC sp_rename '[ns].[table].[c2]', 'c3', 'COLUMN'", "DELETE FROM [" + METADATA_SCHEMA + "].[metadata] WHERE [full_table_name] = 'ns.table'", "INSERT INTO [" + METADATA_SCHEMA @@ -3297,7 +3297,7 @@ public void renameTable_ForSqlServer_ShouldWorkProperly() "SELECT [column_name],[data_type],[key_type],[clustering_order],[indexed] FROM [" + METADATA_SCHEMA + "].[metadata] WHERE [full_table_name]=? ORDER BY [ordinal_position] ASC", - "EXEC sp_rename '[ns].[table]', '[table_new]'", + "EXEC sp_rename '[ns].[table]', 'table_new'", "DELETE FROM [" + METADATA_SCHEMA + "].[metadata] WHERE [full_table_name] = 'ns.table'", "INSERT INTO [" + METADATA_SCHEMA diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java index 33ad772093..a053f4cef3 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java @@ -1077,13 +1077,13 @@ public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() throws Exe try { // Arrange Map options = getCreationOptions(); - TableMetadata currentTableMetadata = + TableMetadata tableMetadata = TableMetadata.newBuilder() .addColumn(getColumnName1(), DataType.INT) .addColumn(getColumnName2(), DataType.INT) .addPartitionKey(getColumnName1()) .build(); - admin.createTable(namespace1, getTable4(), currentTableMetadata, options); + admin.createTable(namespace1, getTable4(), tableMetadata, options); // Act admin.renameTable(namespace1, getTable4(), newTableName); @@ -1091,7 +1091,7 @@ public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() throws Exe // Assert assertThat(admin.tableExists(namespace1, getTable4())).isFalse(); assertThat(admin.tableExists(namespace1, newTableName)).isTrue(); - assertThat(admin.getTableMetadata(namespace1, newTableName)).isEqualTo(currentTableMetadata); + assertThat(admin.getTableMetadata(namespace1, newTableName)).isEqualTo(tableMetadata); } finally { admin.dropTable(namespace1, getTable4(), true); admin.dropTable(namespace1, newTableName, true); @@ -1340,14 +1340,14 @@ public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentEx try { // Arrange Map options = getCreationOptions(); - TableMetadata currentTableMetadata = + TableMetadata tableMetadata = TableMetadata.newBuilder() .addColumn(getColumnName1(), DataType.INT) .addColumn(getColumnName2(), DataType.INT) .addPartitionKey(getColumnName1()) .build(); - admin.createTable(namespace1, getTable4(), currentTableMetadata, options); - admin.createTable(namespace1, newTableName, currentTableMetadata, options); + admin.createTable(namespace1, getTable4(), tableMetadata, options); + admin.createTable(namespace1, newTableName, tableMetadata, options); // Act Assert assertThatThrownBy(() -> admin.renameTable(namespace1, getTable4(), newTableName)) diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java index e9193d3d18..fd3ee1bf7a 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java @@ -1166,13 +1166,13 @@ public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() throws Exe try { // Arrange Map options = getCreationOptions(); - TableMetadata currentTableMetadata = + TableMetadata tableMetadata = TableMetadata.newBuilder() .addColumn("c1", DataType.INT) .addColumn("c2", DataType.INT) .addPartitionKey("c1") .build(); - admin.createTable(namespace1, TABLE4, currentTableMetadata, options); + admin.createTable(namespace1, TABLE4, tableMetadata, options); // Act admin.renameTable(namespace1, TABLE4, newTableName); @@ -1180,7 +1180,7 @@ public void renameTable_ForExistingTable_ShouldRenameTableCorrectly() throws Exe // Assert assertThat(admin.tableExists(namespace1, TABLE4)).isFalse(); assertThat(admin.tableExists(namespace1, newTableName)).isTrue(); - assertThat(admin.getTableMetadata(namespace1, newTableName)).isEqualTo(currentTableMetadata); + assertThat(admin.getTableMetadata(namespace1, newTableName)).isEqualTo(tableMetadata); } finally { admin.dropTable(namespace1, TABLE4, true); admin.dropTable(namespace1, newTableName, true); @@ -1203,14 +1203,14 @@ public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentEx try { // Arrange Map options = getCreationOptions(); - TableMetadata currentTableMetadata = + TableMetadata tableMetadata = TableMetadata.newBuilder() .addColumn("c1", DataType.INT) .addColumn("c2", DataType.INT) .addPartitionKey("c1") .build(); - admin.createTable(namespace1, TABLE4, currentTableMetadata, options); - admin.createTable(namespace1, newTableName, currentTableMetadata, options); + admin.createTable(namespace1, TABLE4, tableMetadata, options); + admin.createTable(namespace1, newTableName, tableMetadata, options); // Act Assert assertThatThrownBy(() -> admin.renameTable(namespace1, TABLE4, newTableName)) From afcec3875e08fa8f82418a1b6308f7a5246396a9 Mon Sep 17 00:00:00 2001 From: Kodai Doki Date: Mon, 22 Sep 2025 11:48:43 +0900 Subject: [PATCH 3/6] Apply suggestion --- .../db/storage/dynamo/DynamoAdminPermissionIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminPermissionIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminPermissionIntegrationTest.java index cec8d1af13..b99fadca3a 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminPermissionIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminPermissionIntegrationTest.java @@ -72,6 +72,6 @@ public void renameColumn_WithSufficientPermission_ShouldSucceed() {} @Test @Override - @Disabled("DynamoDB does not support renaming columns") + @Disabled("DynamoDB does not support renaming tables") public void renameTable_WithSufficientPermission_ShouldSucceed() {} } From f3d31ed1e137bafde4cf9765bd2486b458e3ae79 Mon Sep 17 00:00:00 2001 From: Kodai Doki Date: Mon, 22 Sep 2025 18:08:21 +0900 Subject: [PATCH 4/6] Fix to rename indexes when the table has them --- ...raAdminCaseSensitivityIntegrationTest.java | 4 ++ .../CassandraAdminIntegrationTest.java | 4 ++ ...mmitAdminIntegrationTestWithCassandra.java | 4 ++ ...tionAdminIntegrationTestWithCassandra.java | 4 ++ ...sCommitAdminIntegrationTestWithCosmos.java | 4 ++ ...osAdminCaseSensitivityIntegrationTest.java | 4 ++ .../cosmos/CosmosAdminIntegrationTest.java | 4 ++ ...sactionAdminIntegrationTestWithCosmos.java | 4 ++ ...sCommitAdminIntegrationTestWithDynamo.java | 4 ++ ...moAdminCaseSensitivityIntegrationTest.java | 4 ++ .../dynamo/DynamoAdminIntegrationTest.java | 4 ++ ...sactionAdminIntegrationTestWithDynamo.java | 4 ++ .../com/scalar/db/storage/jdbc/JdbcAdmin.java | 23 ++++++++---- .../scalar/db/storage/jdbc/RdbEngineDb2.java | 6 +-- .../db/storage/jdbc/RdbEngineMysql.java | 6 +-- .../db/storage/jdbc/RdbEngineOracle.java | 6 +-- .../db/storage/jdbc/RdbEnginePostgresql.java | 6 +-- .../db/storage/jdbc/RdbEngineSqlServer.java | 6 +-- .../db/storage/jdbc/RdbEngineSqlite.java | 9 +---- .../db/storage/jdbc/RdbEngineStrategy.java | 6 +-- ...ibutedStorageAdminIntegrationTestBase.java | 37 +++++++++++++++++++ ...edTransactionAdminIntegrationTestBase.java | 37 +++++++++++++++++++ 22 files changed, 145 insertions(+), 45 deletions(-) diff --git a/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminCaseSensitivityIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminCaseSensitivityIntegrationTest.java index 85aab1817a..0d3e242592 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminCaseSensitivityIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminCaseSensitivityIntegrationTest.java @@ -88,4 +88,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("Cassandra does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminIntegrationTest.java index db4bfc1ebf..1b7b8b93a2 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cassandra/CassandraAdminIntegrationTest.java @@ -87,4 +87,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("Cassandra does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cassandra/ConsensusCommitAdminIntegrationTestWithCassandra.java b/core/src/integration-test/java/com/scalar/db/storage/cassandra/ConsensusCommitAdminIntegrationTestWithCassandra.java index f1f0ad298c..46f5571e32 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cassandra/ConsensusCommitAdminIntegrationTestWithCassandra.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cassandra/ConsensusCommitAdminIntegrationTestWithCassandra.java @@ -87,4 +87,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("Cassandra does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cassandra/SingleCrudOperationTransactionAdminIntegrationTestWithCassandra.java b/core/src/integration-test/java/com/scalar/db/storage/cassandra/SingleCrudOperationTransactionAdminIntegrationTestWithCassandra.java index 2c69a7c26d..6099945a44 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cassandra/SingleCrudOperationTransactionAdminIntegrationTestWithCassandra.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cassandra/SingleCrudOperationTransactionAdminIntegrationTestWithCassandra.java @@ -82,4 +82,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("Cassandra does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cassandra does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cosmos/ConsensusCommitAdminIntegrationTestWithCosmos.java b/core/src/integration-test/java/com/scalar/db/storage/cosmos/ConsensusCommitAdminIntegrationTestWithCosmos.java index 89ce2a32df..eff9d9ea7d 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cosmos/ConsensusCommitAdminIntegrationTestWithCosmos.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cosmos/ConsensusCommitAdminIntegrationTestWithCosmos.java @@ -79,4 +79,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("Cosmos DB does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminCaseSensitivityIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminCaseSensitivityIntegrationTest.java index b4db8450ad..ec8559fb0a 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminCaseSensitivityIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminCaseSensitivityIntegrationTest.java @@ -79,4 +79,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("Cosmos DB does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminIntegrationTest.java index cf7861c1b0..b16c14e2b6 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cosmos/CosmosAdminIntegrationTest.java @@ -78,4 +78,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("Cosmos DB does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/cosmos/SingleCrudOperationTransactionAdminIntegrationTestWithCosmos.java b/core/src/integration-test/java/com/scalar/db/storage/cosmos/SingleCrudOperationTransactionAdminIntegrationTestWithCosmos.java index 06e0cd5972..ede5138583 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/cosmos/SingleCrudOperationTransactionAdminIntegrationTestWithCosmos.java +++ b/core/src/integration-test/java/com/scalar/db/storage/cosmos/SingleCrudOperationTransactionAdminIntegrationTestWithCosmos.java @@ -73,4 +73,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("Cosmos DB does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("Cosmos DB does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/dynamo/ConsensusCommitAdminIntegrationTestWithDynamo.java b/core/src/integration-test/java/com/scalar/db/storage/dynamo/ConsensusCommitAdminIntegrationTestWithDynamo.java index 7a2d15a5c9..732ac6d315 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/dynamo/ConsensusCommitAdminIntegrationTestWithDynamo.java +++ b/core/src/integration-test/java/com/scalar/db/storage/dynamo/ConsensusCommitAdminIntegrationTestWithDynamo.java @@ -84,4 +84,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("DynamoDB does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminCaseSensitivityIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminCaseSensitivityIntegrationTest.java index e133aac658..75d528738b 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminCaseSensitivityIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminCaseSensitivityIntegrationTest.java @@ -84,4 +84,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("DynamoDB does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminIntegrationTest.java index fbdf73dd97..e03fd1dd8f 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminIntegrationTest.java +++ b/core/src/integration-test/java/com/scalar/db/storage/dynamo/DynamoAdminIntegrationTest.java @@ -83,4 +83,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("DynamoDB does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/integration-test/java/com/scalar/db/storage/dynamo/SingleCrudOperationTransactionAdminIntegrationTestWithDynamo.java b/core/src/integration-test/java/com/scalar/db/storage/dynamo/SingleCrudOperationTransactionAdminIntegrationTestWithDynamo.java index f8f2b9b210..c2c2a3294d 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/dynamo/SingleCrudOperationTransactionAdminIntegrationTestWithDynamo.java +++ b/core/src/integration-test/java/com/scalar/db/storage/dynamo/SingleCrudOperationTransactionAdminIntegrationTestWithDynamo.java @@ -78,4 +78,8 @@ public void renameTable_ForNonExistingTable_ShouldThrowIllegalArgumentException( @Override @Disabled("DynamoDB does not support renaming tables") public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentException() {} + + @Override + @Disabled("DynamoDB does not support renaming tables") + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() {} } diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java b/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java index 5f6ea70db9..82a6564522 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java @@ -914,7 +914,10 @@ public void renameColumn( try (Connection connection = dataSource.getConnection()) { execute(connection, renameColumnStatement); if (currentTableMetadata.getSecondaryIndexNames().contains(oldColumnName)) { - renameIndex(connection, namespace, table, oldColumnName, newColumnName); + String oldIndexName = getIndexName(namespace, table, oldColumnName); + String newIndexName = getIndexName(namespace, table, newColumnName); + renameIndexInternal( + connection, namespace, table, newColumnName, oldIndexName, newIndexName); } addTableMetadata(connection, namespace, table, updatedTableMetadata, false, true); } @@ -937,6 +940,12 @@ public void renameTable(String namespace, String oldTableName, String newTableNa try (Connection connection = dataSource.getConnection()) { execute(connection, renameTableStatement); execute(connection, getDeleteTableMetadataStatement(namespace, oldTableName)); + for (String indexedColumnName : tableMetadata.getSecondaryIndexNames()) { + String oldIndexName = getIndexName(namespace, oldTableName, indexedColumnName); + String newIndexName = getIndexName(namespace, newTableName, indexedColumnName); + renameIndexInternal( + connection, namespace, newTableName, indexedColumnName, oldIndexName, newIndexName); + } addTableMetadata(connection, namespace, newTableName, tableMetadata, false, false); } } catch (SQLException e) { @@ -1005,17 +1014,15 @@ private void dropIndex(Connection connection, String schema, String table, Strin execute(connection, sql); } - private void renameIndex( + private void renameIndexInternal( Connection connection, String schema, String table, - String oldIndexedColumn, - String newIndexedColumn) + String column, + String oldIndexName, + String newIndexName) throws SQLException { - String oldIndexName = getIndexName(schema, table, oldIndexedColumn); - String newIndexName = getIndexName(schema, table, newIndexedColumn); - String[] sqls = - rdbEngine.renameIndexSqls(schema, table, oldIndexName, newIndexName, newIndexedColumn); + String[] sqls = rdbEngine.renameIndexSqls(schema, table, column, oldIndexName, newIndexName); for (String sql : sqls) { execute(connection, sql); } diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java index ff67d0e048..4687582a6e 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineDb2.java @@ -302,11 +302,7 @@ public String dropIndexSql(String schema, String table, String indexName) { @Override public String[] renameIndexSqls( - String schema, - String table, - String oldIndexName, - String newIndexName, - String newIndexedColumn) { + String schema, String table, String column, String oldIndexName, String newIndexName) { return new String[] { "RENAME INDEX " + enclose(schema) diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineMysql.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineMysql.java index f0b209fb0d..2d5b3a6f08 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineMysql.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineMysql.java @@ -162,11 +162,7 @@ public String dropIndexSql(String schema, String table, String indexName) { @Override public String[] renameIndexSqls( - String schema, - String table, - String oldIndexName, - String newIndexName, - String newIndexedColumn) { + String schema, String table, String column, String oldIndexName, String newIndexName) { return new String[] { "ALTER TABLE " + encloseFullTableName(schema, table) diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineOracle.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineOracle.java index 2a5281d84e..44b8028eb5 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineOracle.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineOracle.java @@ -173,11 +173,7 @@ public String dropIndexSql(String schema, String table, String indexName) { @Override public String[] renameIndexSqls( - String schema, - String table, - String oldIndexName, - String newIndexName, - String newIndexedColumn) { + String schema, String table, String column, String oldIndexName, String newIndexName) { return new String[] { "ALTER INDEX " + enclose(schema) diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEnginePostgresql.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEnginePostgresql.java index c767c4a886..c8a097eaed 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEnginePostgresql.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEnginePostgresql.java @@ -142,11 +142,7 @@ public String dropIndexSql(String schema, String table, String indexName) { @Override public String[] renameIndexSqls( - String schema, - String table, - String oldIndexName, - String newIndexName, - String newIndexedColumn) { + String schema, String table, String column, String oldIndexName, String newIndexName) { return new String[] { "ALTER INDEX " + enclose(schema) diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java index f741f44f39..b91e0d24aa 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlServer.java @@ -145,11 +145,7 @@ public String dropIndexSql(String schema, String table, String indexName) { @Override public String[] renameIndexSqls( - String schema, - String table, - String oldIndexName, - String newIndexName, - String newIndexedColumn) { + String schema, String table, String column, String oldIndexName, String newIndexName) { return new String[] { "EXEC sp_rename '" + encloseFullTableName(schema, table) diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlite.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlite.java index ca316b8fac..e2e3ac8066 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlite.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineSqlite.java @@ -276,15 +276,10 @@ public String dropIndexSql(String schema, String table, String indexName) { @Override public String[] renameIndexSqls( - String schema, - String table, - String oldIndexName, - String newIndexName, - String newIndexedColumn) { + String schema, String table, String column, String oldIndexName, String newIndexName) { // SQLite does not support renaming an index return new String[] { - dropIndexSql(schema, table, oldIndexName), - createIndexSql(schema, table, newIndexName, newIndexedColumn) + dropIndexSql(schema, table, oldIndexName), createIndexSql(schema, table, newIndexName, column) }; } diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java index 526c2452dc..4e06a71914 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/RdbEngineStrategy.java @@ -141,11 +141,7 @@ default String createIndexSql( String dropIndexSql(String schema, String table, String indexName); String[] renameIndexSqls( - String schema, - String table, - String oldIndexName, - String newIndexName, - String newIndexedColumn); + String schema, String table, String column, String oldIndexName, String newIndexName); /** * Enclose the target (schema, table or column) to use reserved words and special characters. diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java index a053f4cef3..ae0bc4cc29 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java @@ -1358,6 +1358,43 @@ public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentEx } } + @Test + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() + throws ExecutionException { + String newTableName = "new" + getTable4(); + try { + // Arrange + Map options = getCreationOptions(); + TableMetadata tableMetadata = + TableMetadata.newBuilder() + .addColumn(getColumnName1(), DataType.INT) + .addColumn(getColumnName2(), DataType.INT) + .addColumn(getColumnName3(), DataType.INT) + .addPartitionKey(getColumnName1()) + .addSecondaryIndex(getColumnName2()) + .addSecondaryIndex(getColumnName3()) + .build(); + admin.createTable(namespace1, getTable4(), tableMetadata, options); + + // Act + admin.renameTable(namespace1, getTable4(), newTableName); + + // Assert + assertThat(admin.tableExists(namespace1, getTable4())).isFalse(); + assertThat(admin.tableExists(namespace1, newTableName)).isTrue(); + assertThat(admin.getTableMetadata(namespace1, newTableName)).isEqualTo(tableMetadata); + assertThat(admin.indexExists(namespace1, newTableName, getColumnName2())).isTrue(); + assertThat(admin.indexExists(namespace1, newTableName, getColumnName3())).isTrue(); + assertThatCode(() -> admin.dropIndex(namespace1, newTableName, getColumnName2())) + .doesNotThrowAnyException(); + assertThatCode(() -> admin.dropIndex(namespace1, newTableName, getColumnName3())) + .doesNotThrowAnyException(); + } finally { + admin.dropTable(namespace1, getTable4(), true); + admin.dropTable(namespace1, newTableName, true); + } + } + @Test public void upgrade_WhenMetadataTableExistsButNotNamespacesTable_ShouldCreateNamespacesTableAndImportExistingNamespaces() diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java index fd3ee1bf7a..b3f39ecea9 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedTransactionAdminIntegrationTestBase.java @@ -1221,6 +1221,43 @@ public void renameTable_IfNewTableNameAlreadyExists_ShouldThrowIllegalArgumentEx } } + @Test + public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesCorrectly() + throws ExecutionException { + String newTableName = "new" + TABLE4; + try { + // Arrange + Map options = getCreationOptions(); + TableMetadata tableMetadata = + TableMetadata.newBuilder() + .addColumn("c1", DataType.INT) + .addColumn("c2", DataType.INT) + .addColumn("c3", DataType.INT) + .addPartitionKey("c1") + .addSecondaryIndex("c2") + .addSecondaryIndex("c3") + .build(); + admin.createTable(namespace1, TABLE4, tableMetadata, options); + + // Act + admin.renameTable(namespace1, TABLE4, newTableName); + + // Assert + assertThat(admin.tableExists(namespace1, TABLE4)).isFalse(); + assertThat(admin.tableExists(namespace1, newTableName)).isTrue(); + assertThat(admin.getTableMetadata(namespace1, newTableName)).isEqualTo(tableMetadata); + assertThat(admin.indexExists(namespace1, newTableName, "c2")).isTrue(); + assertThat(admin.indexExists(namespace1, newTableName, "c3")).isTrue(); + assertThatCode(() -> admin.dropIndex(namespace1, newTableName, "c2")) + .doesNotThrowAnyException(); + assertThatCode(() -> admin.dropIndex(namespace1, newTableName, "c3")) + .doesNotThrowAnyException(); + } finally { + admin.dropTable(namespace1, TABLE4, true); + admin.dropTable(namespace1, newTableName, true); + } + } + @Test public void createCoordinatorTables_ShouldCreateCoordinatorTablesCorrectly() throws ExecutionException { From fa0dc443e968201d6af572d3b611264fd1cabaa8 Mon Sep 17 00:00:00 2001 From: Kodai Doki Date: Wed, 24 Sep 2025 12:49:51 +0900 Subject: [PATCH 5/6] Apply suggestions --- .../src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java | 2 +- .../transaction/consensuscommit/ConsensusCommitAdmin.java | 6 ------ .../db/api/DistributedStorageAdminIntegrationTestBase.java | 2 ++ ...istributedStorageAdminPermissionIntegrationTestBase.java | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java b/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java index 82a6564522..0e10dff779 100644 --- a/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java +++ b/core/src/main/java/com/scalar/db/storage/jdbc/JdbcAdmin.java @@ -939,7 +939,7 @@ public void renameTable(String namespace, String oldTableName, String newTableNa String renameTableStatement = rdbEngine.renameTableSql(namespace, oldTableName, newTableName); try (Connection connection = dataSource.getConnection()) { execute(connection, renameTableStatement); - execute(connection, getDeleteTableMetadataStatement(namespace, oldTableName)); + deleteTableMetadata(connection, namespace, oldTableName); for (String indexedColumnName : tableMetadata.getSecondaryIndexNames()) { String oldIndexName = getIndexName(namespace, oldTableName, indexedColumnName); String newIndexName = getIndexName(namespace, newTableName, indexedColumnName); diff --git a/core/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdmin.java b/core/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdmin.java index 99dc4f1dc3..b0abfb652c 100644 --- a/core/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdmin.java +++ b/core/src/main/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdmin.java @@ -282,12 +282,6 @@ public void renameTable(String namespace, String oldTableName, String newTableNa throws ExecutionException { checkNamespace(namespace); - TableMetadata tableMetadata = getTableMetadata(namespace, oldTableName); - if (tableMetadata == null) { - throw new IllegalArgumentException( - CoreError.TABLE_NOT_FOUND.buildMessage( - ScalarDbUtils.getFullTableName(namespace, oldTableName))); - } admin.renameTable(namespace, oldTableName, newTableName); } diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java index ae0bc4cc29..c4581f80b7 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminIntegrationTestBase.java @@ -1383,6 +1383,8 @@ public void renameTable_ForExistingTableWithIndexes_ShouldRenameTableAndIndexesC assertThat(admin.tableExists(namespace1, getTable4())).isFalse(); assertThat(admin.tableExists(namespace1, newTableName)).isTrue(); assertThat(admin.getTableMetadata(namespace1, newTableName)).isEqualTo(tableMetadata); + assertThat(admin.indexExists(namespace1, getTable4(), getColumnName2())).isFalse(); + assertThat(admin.indexExists(namespace1, getTable4(), getColumnName3())).isFalse(); assertThat(admin.indexExists(namespace1, newTableName, getColumnName2())).isTrue(); assertThat(admin.indexExists(namespace1, newTableName, getColumnName3())).isTrue(); assertThatCode(() -> admin.dropIndex(namespace1, newTableName, getColumnName2())) diff --git a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminPermissionIntegrationTestBase.java b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminPermissionIntegrationTestBase.java index 104ff168ae..97cc3087e2 100644 --- a/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminPermissionIntegrationTestBase.java +++ b/integration-test/src/main/java/com/scalar/db/api/DistributedStorageAdminPermissionIntegrationTestBase.java @@ -353,7 +353,7 @@ public void renameTable_WithSufficientPermission_ShouldSucceed() throws Executio // Arrange createNamespaceByRoot(); createTableByRoot(); - String newTableName = TABLE + "_new"; + String newTableName = "new_" + TABLE; // Act Assert assertThatCode(() -> adminForNormalUser.renameTable(NAMESPACE, TABLE, newTableName)) From 1f9425016c5b2ce181d6a85b831e823d58845a38 Mon Sep 17 00:00:00 2001 From: Kodai Doki Date: Wed, 24 Sep 2025 13:58:45 +0900 Subject: [PATCH 6/6] Fix --- .../java/com/scalar/db/common/CoreError.java | 6 ++++ .../scalar/db/storage/jdbc/JdbcAdminTest.java | 28 ++++++++++++++----- .../ConsensusCommitAdminTestBase.java | 5 ---- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/com/scalar/db/common/CoreError.java b/core/src/main/java/com/scalar/db/common/CoreError.java index 5bbb3b7d39..64d0128d47 100644 --- a/core/src/main/java/com/scalar/db/common/CoreError.java +++ b/core/src/main/java/com/scalar/db/common/CoreError.java @@ -1042,6 +1042,12 @@ public enum CoreError implements ScalarDbError { "Renaming a column failed. Table: %s; Old column name: %s; New column name: %s", "", ""), + RENAMING_TABLE_FAILED( + Category.INTERNAL_ERROR, + "0061", + "Renaming a table failed. Old table name: %s; New table name: %s", + "", + ""), // // Errors for the unknown transaction status error category diff --git a/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java b/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java index 4139087484..bcd7da4fad 100644 --- a/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java +++ b/core/src/test/java/com/scalar/db/storage/jdbc/JdbcAdminTest.java @@ -3242,6 +3242,7 @@ public void renameTable_ForMysql_ShouldWorkProperly() throws SQLException, Execu + "`.`metadata` WHERE `full_table_name`=? ORDER BY `ordinal_position` ASC", "ALTER TABLE `ns`.`table` RENAME TO `ns`.`table_new`", "DELETE FROM `" + METADATA_SCHEMA + "`.`metadata` WHERE `full_table_name` = 'ns.table'", + "SELECT DISTINCT `full_table_name` FROM `" + METADATA_SCHEMA + "`.`metadata`", "INSERT INTO `" + METADATA_SCHEMA + "`.`metadata` VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,false,1)", @@ -3261,6 +3262,7 @@ public void renameTable_ForOracle_ShouldWorkProperly() throws SQLException, Exec "DELETE FROM \"" + METADATA_SCHEMA + "\".\"metadata\" WHERE \"full_table_name\" = 'ns.table'", + "SELECT DISTINCT \"full_table_name\" FROM \"" + METADATA_SCHEMA + "\".\"metadata\"", "INSERT INTO \"" + METADATA_SCHEMA + "\".\"metadata\" VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,0,1)", @@ -3281,6 +3283,7 @@ public void renameTable_ForPostgresql_ShouldWorkProperly() "DELETE FROM \"" + METADATA_SCHEMA + "\".\"metadata\" WHERE \"full_table_name\" = 'ns.table'", + "SELECT DISTINCT \"full_table_name\" FROM \"" + METADATA_SCHEMA + "\".\"metadata\"", "INSERT INTO \"" + METADATA_SCHEMA + "\".\"metadata\" VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,false,1)", @@ -3299,6 +3302,7 @@ public void renameTable_ForSqlServer_ShouldWorkProperly() + "].[metadata] WHERE [full_table_name]=? ORDER BY [ordinal_position] ASC", "EXEC sp_rename '[ns].[table]', 'table_new'", "DELETE FROM [" + METADATA_SCHEMA + "].[metadata] WHERE [full_table_name] = 'ns.table'", + "SELECT DISTINCT [full_table_name] FROM [" + METADATA_SCHEMA + "].[metadata]", "INSERT INTO [" + METADATA_SCHEMA + "].[metadata] VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,0,1)", @@ -3316,6 +3320,7 @@ public void renameTable_ForSqlite_ShouldWorkProperly() throws SQLException, Exec + "$metadata\" WHERE \"full_table_name\"=? ORDER BY \"ordinal_position\" ASC", "ALTER TABLE \"ns$table\" RENAME TO \"ns$table_new\"", "DELETE FROM \"" + METADATA_SCHEMA + "$metadata\" WHERE \"full_table_name\" = 'ns.table'", + "SELECT DISTINCT \"full_table_name\" FROM \"" + METADATA_SCHEMA + "$metadata\"", "INSERT INTO \"" + METADATA_SCHEMA + "$metadata\" VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,FALSE,1)", @@ -3335,6 +3340,7 @@ public void renameTable_ForDb2_ShouldWorkProperly() throws SQLException, Executi "DELETE FROM \"" + METADATA_SCHEMA + "\".\"metadata\" WHERE \"full_table_name\" = 'ns.table'", + "SELECT DISTINCT \"full_table_name\" FROM \"" + METADATA_SCHEMA + "\".\"metadata\"", "INSERT INTO \"" + METADATA_SCHEMA + "\".\"metadata\" VALUES ('ns.table_new','c1','TEXT','PARTITION',NULL,false,1)", @@ -3353,19 +3359,23 @@ private void renameTable_ForX_ShouldWorkProperly( String columnName2 = "c2"; PreparedStatement selectStatement = mock(PreparedStatement.class); - ResultSet resultSet = + ResultSet resultSet1 = mockResultSet( new SelectAllFromMetadataTableResultSetMocker.Row( columnName1, DataType.TEXT.toString(), "PARTITION", null, false), new SelectAllFromMetadataTableResultSetMocker.Row( columnName2, DataType.INT.toString(), null, null, false)); - when(selectStatement.executeQuery()).thenReturn(resultSet); - + when(selectStatement.executeQuery()).thenReturn(resultSet1); when(connection.prepareStatement(any())).thenReturn(selectStatement); List expectedStatements = new ArrayList<>(); - for (int i = 0; i < expectedSqlStatements.length; i++) { - Statement expectedStatement = mock(Statement.class); - expectedStatements.add(expectedStatement); + for (String expectedSqlStatement : expectedSqlStatements) { + Statement mock = mock(Statement.class); + expectedStatements.add(mock); + if (expectedSqlStatement.startsWith("SELECT DISTINCT ")) { + ResultSet resultSet2 = mock(ResultSet.class); + when(resultSet2.next()).thenReturn(true); + when(mock.executeQuery(any())).thenReturn(resultSet2); + } } when(connection.createStatement()) .thenReturn( @@ -3382,7 +3392,11 @@ private void renameTable_ForX_ShouldWorkProperly( verify(selectStatement).setString(1, getFullTableName(namespace, table)); verify(connection).prepareStatement(expectedGetMetadataStatement); for (int i = 0; i < expectedSqlStatements.length; i++) { - verify(expectedStatements.get(i)).execute(expectedSqlStatements[i]); + if (expectedSqlStatements[i].startsWith("SELECT DISTINCT ")) { + verify(expectedStatements.get(i)).executeQuery(expectedSqlStatements[i]); + } else { + verify(expectedStatements.get(i)).execute(expectedSqlStatements[i]); + } } } diff --git a/core/src/test/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdminTestBase.java b/core/src/test/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdminTestBase.java index 5ed75b3892..7bcec40e74 100644 --- a/core/src/test/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdminTestBase.java +++ b/core/src/test/java/com/scalar/db/transaction/consensuscommit/ConsensusCommitAdminTestBase.java @@ -659,16 +659,11 @@ public void renameTable_ShouldCallJdbcAdminProperly() throws ExecutionException // Arrange String existingTableName = "tbl1"; String newTableName = "tbl2"; - TableMetadata tableMetadata = - TableMetadata.newBuilder().addColumn("col1", DataType.INT).addPartitionKey("col1").build(); - when(distributedStorageAdmin.getTableMetadata(NAMESPACE, existingTableName)) - .thenReturn(ConsensusCommitUtils.buildTransactionTableMetadata(tableMetadata)); // Act admin.renameTable(NAMESPACE, existingTableName, newTableName); // Assert - verify(distributedStorageAdmin).getTableMetadata(NAMESPACE, existingTableName); verify(distributedStorageAdmin).renameTable(NAMESPACE, existingTableName, newTableName); }