Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
import org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.table.AlterTableStatement;

import java.util.Collection;
import java.util.Optional;
import java.util.stream.Collectors;

/**
* Alter table supported checker for sharding.
Expand All @@ -45,10 +43,16 @@ public boolean isCheck(final SQLStatementContext sqlStatementContext) {
@Override
public void check(final ShardingRule rule, final ShardingSphereDatabase database, final ShardingSphereSchema currentSchema, final CommonSQLStatementContext sqlStatementContext) {
AlterTableStatement sqlStatement = (AlterTableStatement) sqlStatementContext.getSqlStatement();
Collection<String> tableNames = sqlStatementContext.getTablesContext().getSimpleTables().stream()
.map(each -> each.getTableName().getIdentifier().getValue()).collect(Collectors.toList());
Optional<SimpleTableSegment> renameTable = sqlStatement.getRenameTable();
ShardingSpherePreconditions.checkState(!renameTable.isPresent() || !rule.containsShardingTable(tableNames),
() -> new UnsupportedShardingOperationException("ALTER TABLE ... RENAME TO ...", renameTable.map(optional -> optional.getTableName().getIdentifier().getValue()).orElse("")));
if (!renameTable.isPresent()) {
return;
}
String newTableName = renameTable.get().getTableName().getIdentifier().getValue();
// Validate new table name does not conflict with existing sharding tables
ShardingSpherePreconditions.checkState(!rule.isShardingTable(newTableName),
() -> new UnsupportedShardingOperationException("ALTER TABLE ... RENAME TO ...", newTableName));
// Validate new table name does not exist in current schema
ShardingSpherePreconditions.checkState(!currentSchema.containsTable(newTableName),
() -> new UnsupportedShardingOperationException("ALTER TABLE ... RENAME TO ...", newTableName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,8 @@
import org.apache.shardingsphere.sharding.exception.syntax.UnsupportedShardingOperationException;
import org.apache.shardingsphere.sharding.rule.ShardingRule;
import org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.table.RenameTableDefinitionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
import org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.table.RenameTableStatement;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
* Rename table supported checker for sharding.
*/
Expand All @@ -44,11 +39,15 @@ public boolean isCheck(final SQLStatementContext sqlStatementContext) {

@Override
public void check(final ShardingRule rule, final ShardingSphereDatabase database, final ShardingSphereSchema currentSchema, final SQLStatementContext sqlStatementContext) {
Collection<String> tableNames = sqlStatementContext.getTablesContext().getSimpleTables().stream()
.map(each -> each.getTableName().getIdentifier().getValue()).collect(Collectors.toList());
List<SimpleTableSegment> renameTables = ((RenameTableStatement) sqlStatementContext.getSqlStatement())
.getRenameTables().stream().map(RenameTableDefinitionSegment::getRenameTable).collect(Collectors.toList());
ShardingSpherePreconditions.checkState(renameTables.isEmpty() || !rule.containsShardingTable(tableNames),
() -> new UnsupportedShardingOperationException("RENAME TABLE", renameTables.get(0).getTableName().getIdentifier().getValue()));
RenameTableStatement sqlStatement = (RenameTableStatement) sqlStatementContext.getSqlStatement();
for (RenameTableDefinitionSegment each : sqlStatement.getRenameTables()) {
String newTableName = each.getRenameTable().getTableName().getIdentifier().getValue();
// Validate new table name does not conflict with existing sharding tables
ShardingSpherePreconditions.checkState(!rule.isShardingTable(newTableName),
() -> new UnsupportedShardingOperationException("RENAME TABLE", newTableName));
// Validate new table name does not exist in current schema
ShardingSpherePreconditions.checkState(!currentSchema.containsTable(newTableName),
() -> new UnsupportedShardingOperationException("RENAME TABLE", newTableName));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import org.apache.shardingsphere.infra.binder.context.statement.type.CommonSQLStatementContext;
import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.sharding.exception.syntax.UnsupportedShardingOperationException;
import org.apache.shardingsphere.sharding.rule.ShardingRule;
Expand All @@ -35,8 +36,7 @@
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;

import java.util.Arrays;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
Expand All @@ -54,12 +54,46 @@ class ShardingAlterTableSupportedCheckerTest {
private ShardingSphereDatabase database;

@Test
void assertCheckWithRenameTableWithShardingTable() {
void assertCheckWithRenameTableWhenNewTableNameConflictsWithShardingTable() {
AlterTableStatement sqlStatement = new AlterTableStatement(databaseType);
sqlStatement.setTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order"))));
sqlStatement.setRenameTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_user"))));
CommonSQLStatementContext sqlStatementContext = new CommonSQLStatementContext(sqlStatement);
ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
when(rule.isShardingTable("t_user")).thenReturn(true);
when(schema.containsTable("t_user")).thenReturn(false);
assertThrows(UnsupportedShardingOperationException.class, () -> new ShardingAlterTableSupportedChecker().check(rule, database, schema, sqlStatementContext));
}

@Test
void assertCheckWithRenameTableWhenNewTableNameConflictsWithExistingTable() {
AlterTableStatement sqlStatement = new AlterTableStatement(databaseType);
sqlStatement.setTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order"))));
sqlStatement.setRenameTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_existing"))));
CommonSQLStatementContext sqlStatementContext = new CommonSQLStatementContext(sqlStatement);
ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
when(rule.isShardingTable("t_existing")).thenReturn(false);
when(schema.containsTable("t_existing")).thenReturn(true);
assertThrows(UnsupportedShardingOperationException.class, () -> new ShardingAlterTableSupportedChecker().check(rule, database, schema, sqlStatementContext));
}

@Test
void assertCheckWithRenameTableSuccess() {
AlterTableStatement sqlStatement = new AlterTableStatement(databaseType);
sqlStatement.setTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order"))));
sqlStatement.setRenameTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order_new"))));
CommonSQLStatementContext sqlStatementContext = new CommonSQLStatementContext(sqlStatement);
when(rule.containsShardingTable(Arrays.asList("t_order", "t_order_new"))).thenReturn(true);
assertThrows(UnsupportedShardingOperationException.class, () -> new ShardingAlterTableSupportedChecker().check(rule, database, mock(), sqlStatementContext));
ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
when(rule.isShardingTable("t_order_new")).thenReturn(false);
when(schema.containsTable("t_order_new")).thenReturn(false);
assertDoesNotThrow(() -> new ShardingAlterTableSupportedChecker().check(rule, database, schema, sqlStatementContext));
}

@Test
void assertCheckWithoutRenameTable() {
AlterTableStatement sqlStatement = new AlterTableStatement(databaseType);
sqlStatement.setTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order"))));
CommonSQLStatementContext sqlStatementContext = new CommonSQLStatementContext(sqlStatement);
assertDoesNotThrow(() -> new ShardingAlterTableSupportedChecker().check(rule, database, mock(ShardingSphereSchema.class), sqlStatementContext));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
import org.apache.shardingsphere.infra.binder.context.statement.type.CommonSQLStatementContext;
import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
import org.apache.shardingsphere.sharding.exception.syntax.UnsupportedShardingOperationException;
import org.apache.shardingsphere.sharding.rule.ShardingRule;
import org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.table.RenameTableDefinitionSegment;
Expand All @@ -32,33 +33,75 @@
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;

import java.util.Arrays;
import java.util.Collections;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class ShardingRenameTableSupportedCheckerTest {

@Mock
private ShardingRule rule;

@Test
void assertCheckShardingTable() {
void assertCheckWhenNewTableNameConflictsWithShardingTable() {
SQLStatementContext sqlStatementContext = createRenameTableStatementContext("t_order", "t_user");
ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
when(rule.isShardingTable("t_user")).thenReturn(true);
when(schema.containsTable("t_user")).thenReturn(false);
assertThrows(UnsupportedShardingOperationException.class, () -> new ShardingRenameTableSupportedChecker().check(rule, mock(), schema, sqlStatementContext));
}

@Test
void assertCheckWhenNewTableNameConflictsWithExistingTable() {
SQLStatementContext sqlStatementContext = createRenameTableStatementContext("t_order", "t_existing");
ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
when(rule.isShardingTable("t_existing")).thenReturn(false);
when(schema.containsTable("t_existing")).thenReturn(true);
assertThrows(UnsupportedShardingOperationException.class, () -> new ShardingRenameTableSupportedChecker().check(rule, mock(), schema, sqlStatementContext));
}

@Test
void assertCheckSuccess() {
SQLStatementContext sqlStatementContext = createRenameTableStatementContext("t_order", "t_user_order");
when(rule.containsShardingTable(argThat(tableNames -> tableNames.contains("t_order") || tableNames.contains("t_user_order")))).thenReturn(true);
assertThrows(UnsupportedShardingOperationException.class, () -> new ShardingRenameTableSupportedChecker().check(rule, mock(), mock(), sqlStatementContext));
ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
when(rule.isShardingTable("t_user_order")).thenReturn(false);
when(schema.containsTable("t_user_order")).thenReturn(false);
assertDoesNotThrow(() -> new ShardingRenameTableSupportedChecker().check(rule, mock(), schema, sqlStatementContext));
}

@Test
void assertCheckNormalCase() {
SQLStatementContext sqlStatementContext = createRenameTableStatementContext("t_not_sharding_table", "t_not_sharding_table_new");
assertDoesNotThrow(() -> new ShardingRenameTableSupportedChecker().check(rule, mock(), mock(), sqlStatementContext));
void assertCheckWithMultipleTables() {
RenameTableStatement sqlStatement = mock(RenameTableStatement.class);
RenameTableDefinitionSegment segment1 = createRenameTableDefinitionSegment("t_order", "t_order_new");
RenameTableDefinitionSegment segment2 = createRenameTableDefinitionSegment("t_user", "t_user_new");
when(sqlStatement.getRenameTables()).thenReturn(Arrays.asList(segment1, segment2));
when(sqlStatement.getAttributes()).thenReturn(new SQLStatementAttributes(new TableSQLStatementAttribute(Arrays.asList(
segment1.getTable(), segment1.getRenameTable(), segment2.getTable(), segment2.getRenameTable()))));
SQLStatementContext sqlStatementContext = new CommonSQLStatementContext(sqlStatement);
ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
when(rule.isShardingTable("t_order_new")).thenReturn(false);
when(rule.isShardingTable("t_user_new")).thenReturn(false);
when(schema.containsTable("t_order_new")).thenReturn(false);
when(schema.containsTable("t_user_new")).thenReturn(false);
assertDoesNotThrow(() -> new ShardingRenameTableSupportedChecker().check(rule, mock(), schema, sqlStatementContext));
}

private RenameTableDefinitionSegment createRenameTableDefinitionSegment(final String originTableName, final String newTableName) {
RenameTableDefinitionSegment renameTableDefinitionSegment = new RenameTableDefinitionSegment(0, 0);
SimpleTableSegment table = new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue(originTableName)));
SimpleTableSegment renameTable = new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue(newTableName)));
renameTableDefinitionSegment.setTable(table);
renameTableDefinitionSegment.setRenameTable(renameTable);
return renameTableDefinitionSegment;
}

private SQLStatementContext createRenameTableStatementContext(final String originTableName, final String newTableName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,18 @@ public void refresh(final MetaDataManagerPersistService metaDataManagerPersistSe
final String schemaName, final DatabaseType databaseType, final AlterTableStatement sqlStatement, final ConfigurationProperties props) throws SQLException {
String tableName = TableRefreshUtils.getTableName(sqlStatement.getTable().getTableName().getIdentifier(), databaseType);
Collection<ShardingSphereTable> alteredTables = new LinkedList<>();
Collection<String> droppedTables = new LinkedList<>();
if (sqlStatement.getRenameTable().isPresent()) {
String renameTable = sqlStatement.getRenameTable().get().getTableName().getIdentifier().getValue();
alteredTables.add(getTable(database, logicDataSourceName, schemaName, renameTable, props));
droppedTables.add(tableName);
// Add new table to metadata first
metaDataManagerPersistService.alterTables(database, schemaName, alteredTables);
// Then drop old table and update single table rules
Map<String, String> renameTableMap = Collections.singletonMap(tableName, renameTable);
metaDataManagerPersistService.renameTables(database, schemaName, renameTableMap);
} else {
alteredTables.add(getTable(database, logicDataSourceName, schemaName, tableName, props));
metaDataManagerPersistService.alterTables(database, schemaName, alteredTables);
}
metaDataManagerPersistService.alterTables(database, schemaName, alteredTables);
metaDataManagerPersistService.dropTables(database, schemaName, droppedTables);
}

private ShardingSphereTable getTable(final ShardingSphereDatabase database, final String logicDataSourceName, final String schemaName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@

import java.sql.SQLException;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;

/**
* Rename table push down meta data refresher.
Expand All @@ -39,16 +41,18 @@ public final class RenameTablePushDownMetaDataRefresher implements PushDownMetaD
public void refresh(final MetaDataManagerPersistService metaDataManagerPersistService, final ShardingSphereDatabase database, final String logicDataSourceName,
final String schemaName, final DatabaseType databaseType, final RenameTableStatement sqlStatement, final ConfigurationProperties props) throws SQLException {
Collection<ShardingSphereTable> alteredTables = new LinkedList<>();
Collection<String> droppedTables = new LinkedList<>();
Map<String, String> renameTableMap = new LinkedHashMap<>();
for (RenameTableDefinitionSegment each : sqlStatement.getRenameTables()) {
String toBeRenamedTableName = each.getTable().getTableName().getIdentifier().getValue();
ShardingSphereTable toBeRenamedTable = database.getSchema(schemaName).getTable(toBeRenamedTableName);
alteredTables.add(new ShardingSphereTable(
each.getRenameTable().getTableName().getIdentifier().getValue(), toBeRenamedTable.getAllColumns(), toBeRenamedTable.getAllIndexes(), toBeRenamedTable.getAllConstraints()));
droppedTables.add(toBeRenamedTableName);
String oldTableName = each.getTable().getTableName().getIdentifier().getValue();
String newTableName = each.getRenameTable().getTableName().getIdentifier().getValue();
ShardingSphereTable toBeRenamedTable = database.getSchema(schemaName).getTable(oldTableName);
alteredTables.add(new ShardingSphereTable(newTableName, toBeRenamedTable.getAllColumns(), toBeRenamedTable.getAllIndexes(), toBeRenamedTable.getAllConstraints()));
renameTableMap.put(oldTableName, newTableName);
}
// Add new tables to metadata first
metaDataManagerPersistService.alterTables(database, schemaName, alteredTables);
metaDataManagerPersistService.dropTables(database, schemaName, droppedTables);
// Then drop old tables and update single table rules
metaDataManagerPersistService.renameTables(database, schemaName, renameTableMap);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ public interface MetaDataManagerPersistService {
*/
void dropTables(ShardingSphereDatabase database, String schemaName, Collection<String> tableNames);

/**
* Rename tables.
*
* @param database database
* @param schemaName schema name
* @param renameTableMap rename table map, key is old table name, value is new table name
*/
void renameTables(ShardingSphereDatabase database, String schemaName, Map<String, String> renameTableMap);

/**
* Alter tables.
*
Expand Down
Loading
Loading