1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sharding.route.engine.validator.ddl.impl;
19
20 import com.cedarsoftware.util.CaseInsensitiveSet;
21 import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
22 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
23 import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
24 import org.apache.shardingsphere.infra.datanode.DataNode;
25 import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
26 import org.apache.shardingsphere.infra.hint.HintValueContext;
27 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
28 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
29 import org.apache.shardingsphere.infra.route.context.RouteContext;
30 import org.apache.shardingsphere.infra.route.context.RouteMapper;
31 import org.apache.shardingsphere.sharding.exception.connection.ShardingDDLRouteException;
32 import org.apache.shardingsphere.sharding.exception.metadata.InUsedTablesException;
33 import org.apache.shardingsphere.sharding.exception.syntax.UnsupportedShardingOperationException;
34 import org.apache.shardingsphere.sharding.route.engine.validator.ddl.ShardingDDLStatementValidator;
35 import org.apache.shardingsphere.sharding.rule.ShardingRule;
36 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
37 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropTableStatement;
38 import org.apache.shardingsphere.sql.parser.sql.dialect.handler.ddl.DropTableStatementHandler;
39
40 import java.util.Collection;
41 import java.util.List;
42 import java.util.Set;
43 import java.util.stream.Collectors;
44
45
46
47
48 public final class ShardingDropTableStatementValidator extends ShardingDDLStatementValidator {
49
50 @Override
51 public void preValidate(final ShardingRule shardingRule, final SQLStatementContext sqlStatementContext,
52 final List<Object> params, final ShardingSphereDatabase database, final ConfigurationProperties props) {
53 DropTableStatement dropTableStatement = (DropTableStatement) sqlStatementContext.getSqlStatement();
54 if (!DropTableStatementHandler.ifExists(dropTableStatement)) {
55 String defaultSchemaName = new DatabaseTypeRegistry(sqlStatementContext.getDatabaseType()).getDefaultSchemaName(database.getName());
56 ShardingSphereSchema schema = sqlStatementContext.getTablesContext().getSchemaName()
57 .map(database::getSchema).orElseGet(() -> database.getSchema(defaultSchemaName));
58 validateTableExist(schema, sqlStatementContext.getTablesContext().getSimpleTableSegments());
59 }
60 if (DropTableStatementHandler.containsCascade(dropTableStatement)) {
61 throw new UnsupportedShardingOperationException("DROP TABLE ... CASCADE",
62 sqlStatementContext.getTablesContext().getSimpleTableSegments().iterator().next().getTableName().getIdentifier().getValue());
63 }
64 }
65
66 @Override
67 public void postValidate(final ShardingRule shardingRule, final SQLStatementContext sqlStatementContext, final HintValueContext hintValueContext, final List<Object> params,
68 final ShardingSphereDatabase database, final ConfigurationProperties props, final RouteContext routeContext) {
69 DropTableStatement dropTableStatement = (DropTableStatement) sqlStatementContext.getSqlStatement();
70 checkTableInUsed(shardingRule, sqlStatementContext, routeContext);
71 for (SimpleTableSegment each : dropTableStatement.getTables()) {
72 if (isRouteUnitDataNodeDifferentSize(shardingRule, routeContext, each.getTableName().getIdentifier().getValue())) {
73 throw new ShardingDDLRouteException("DROP", "TABLE", sqlStatementContext.getTablesContext().getTableNames());
74 }
75 }
76 }
77
78 private void checkTableInUsed(final ShardingRule shardingRule, final SQLStatementContext sqlStatementContext, final RouteContext routeContext) {
79 Collection<String> dropTables = sqlStatementContext.getTablesContext().getTableNames();
80 Collection<String> otherRuleActualTables = shardingRule.getShardingTables().values().stream().filter(each -> !dropTables.contains(each.getLogicTable()))
81 .flatMap(each -> each.getActualDataNodes().stream().map(DataNode::getTableName)).collect(Collectors.toCollection(CaseInsensitiveSet::new));
82 if (otherRuleActualTables.isEmpty()) {
83 return;
84 }
85
86 Set<String> actualTables = routeContext.getRouteUnits().stream().flatMap(each -> each.getTableMappers().stream().map(RouteMapper::getActualName)).collect(Collectors.toSet());
87 Collection<String> inUsedTables = actualTables.stream().filter(otherRuleActualTables::contains).collect(Collectors.toList());
88 ShardingSpherePreconditions.checkMustEmpty(inUsedTables, () -> new InUsedTablesException(inUsedTables));
89 }
90 }