Skip to content

Commit

Permalink
add check for drop table (apache#9189)
Browse files Browse the repository at this point in the history
* add check for drop table

* fix

* fix

* fix
  • Loading branch information
jingshanglu authored Jan 28, 2021
1 parent 2b3b1bd commit 357cd79
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.shardingsphere.sharding.route.engine.validator.ddl.impl.ShardingCreateProcedureStatementValidator;
import org.apache.shardingsphere.sharding.route.engine.validator.ddl.impl.ShardingCreateTableStatementValidator;
import org.apache.shardingsphere.sharding.route.engine.validator.ddl.impl.ShardingCreateViewStatementValidator;
import org.apache.shardingsphere.sharding.route.engine.validator.ddl.impl.ShardingDropTableStatementValidator;
import org.apache.shardingsphere.sharding.route.engine.validator.dml.impl.ShardingDeleteStatementValidator;
import org.apache.shardingsphere.sharding.route.engine.validator.dml.impl.ShardingInsertStatementValidator;
import org.apache.shardingsphere.sharding.route.engine.validator.dml.impl.ShardingSelectStatementValidator;
Expand All @@ -35,6 +36,7 @@
import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateTableStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateViewStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropTableStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
Expand Down Expand Up @@ -81,6 +83,9 @@ private static Optional<ShardingStatementValidator> getDDLStatementValidator(fin
if (sqlStatement instanceof AlterViewStatement) {
return Optional.of(new ShardingAlterViewStatementValidator());
}
if (sqlStatement instanceof DropTableStatement) {
return Optional.of(new ShardingDropTableStatementValidator());
}
return Optional.empty();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.shardingsphere.sharding.route.engine.validator.ddl.impl;

import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
import org.apache.shardingsphere.infra.datanode.DataNode;
import org.apache.shardingsphere.infra.exception.ShardingSphereException;
import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
import org.apache.shardingsphere.infra.route.context.RouteContext;
import org.apache.shardingsphere.infra.route.context.RouteMapper;
import org.apache.shardingsphere.sharding.route.engine.validator.ddl.ShardingDDLStatementValidator;
import org.apache.shardingsphere.sharding.rule.ShardingRule;
import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropTableStatement;

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

/**
* Sharding drop table statement validator.
*/
public final class ShardingDropTableStatementValidator extends ShardingDDLStatementValidator<DropTableStatement> {

private ShardingRule shardingRule;

@Override
public void preValidate(final ShardingRule shardingRule, final SQLStatementContext<DropTableStatement> sqlStatementContext,
final List<Object> parameters, final ShardingSphereSchema schema) {
this.shardingRule = shardingRule;
validateTableExist(schema, sqlStatementContext.getTablesContext().getTables());
}

@Override
public void postValidate(final DropTableStatement sqlStatement, final RouteContext routeContext) {
checkTableInUsed(sqlStatement, routeContext);
}

private void checkTableInUsed(final DropTableStatement sqlStatement, final RouteContext routeContext) {
Collection<String> inUsedTable = new LinkedList<>();
Set<String> dropTables = sqlStatement.getTables().stream().map(each -> each.getTableName().getIdentifier().getValue()).collect(Collectors.toSet());
Set<String> actualTables = routeContext.getRouteUnits().stream().flatMap(each -> each.getTableMappers().stream().map(RouteMapper::getActualName)).collect(Collectors.toSet());
Collection<String> tableMeta = this.shardingRule.getTableRules().stream().filter(each -> !dropTables.contains(each.getLogicTable()))
.flatMap(each -> each.getActualDataNodes().stream().map(DataNode::getTableName)).collect(Collectors.toSet());
for (String each : actualTables) {
if (tableMeta.contains(each)) {
inUsedTable.add(each);
}
}
if (!inUsedTable.isEmpty()) {
throw new ShardingSphereException("Actual Tables: [%s] are in use.", inUsedTable);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.shardingsphere.sharding.route.engine.validator.ddl;

import org.apache.shardingsphere.infra.binder.statement.CommonSQLStatementContext;
import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
import org.apache.shardingsphere.infra.datanode.DataNode;
import org.apache.shardingsphere.infra.exception.ShardingSphereException;
import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
import org.apache.shardingsphere.infra.route.context.RouteContext;
import org.apache.shardingsphere.infra.route.context.RouteMapper;
import org.apache.shardingsphere.infra.route.context.RouteUnit;
import org.apache.shardingsphere.sharding.route.engine.validator.ddl.impl.ShardingDropTableStatementValidator;
import org.apache.shardingsphere.sharding.rule.ShardingRule;
import org.apache.shardingsphere.sharding.rule.TableRule;
import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropTableStatement;
import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.ddl.MySQLDropTableStatement;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public final class ShardingDropTableStatementValidatorTest {

private ShardingRule shardingRule;

@Before
public void init() {
shardingRule = mock(ShardingRule.class);
Collection<TableRule> tableRules = new LinkedList<>();
tableRules.add(generateShardingRule("t_order_item"));
tableRules.add(generateShardingRule("t_order"));
when(shardingRule.getTableRules()).thenReturn(tableRules);
}

@Test(expected = ShardingSphereException.class)
public void assertValidateDropTableForMySQL() {
MySQLDropTableStatement sqlStatement = new MySQLDropTableStatement();
sqlStatement.getTables().add(new SimpleTableSegment(0, 0, new IdentifierValue("t_order_item")));
SQLStatementContext<DropTableStatement> sqlStatementContext = new CommonSQLStatementContext<>(sqlStatement);
ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
when(schema.getAllTableNames()).thenReturn(Arrays.asList("t_order", "t_order_item"));
ShardingDropTableStatementValidator validator = new ShardingDropTableStatementValidator();
validator.preValidate(shardingRule, sqlStatementContext, Collections.emptyList(), schema);
Collection<RouteUnit> routeUnits = new LinkedList<>();
RouteMapper dataSourceMapper = new RouteMapper("db", "db1");
Collection<RouteMapper> tableMapper = new LinkedList<>();
tableMapper.add(new RouteMapper("t_order_item", "t_order_item_1"));
tableMapper.add(new RouteMapper("t_order_item", "t_order_item_2"));
RouteUnit routeUnit = new RouteUnit(dataSourceMapper, tableMapper);
routeUnits.add(routeUnit);
RouteContext routeContext = mock(RouteContext.class);
when(routeContext.getRouteUnits()).thenReturn(routeUnits);
validator.postValidate(sqlStatement, routeContext);
}

private TableRule generateShardingRule(final String tableName) {
TableRule result = mock(TableRule.class);
when(result.getLogicTable()).thenReturn(tableName);
List<DataNode> dataNodes = new LinkedList<>();
DataNode d1 = mock(DataNode.class);
when(d1.getTableName()).thenReturn("t_order_item_1");
dataNodes.add(d1);
DataNode d2 = mock(DataNode.class);
when(d2.getTableName()).thenReturn("t_order_item_2");
dataNodes.add(d2);
when(result.getActualDataNodes()).thenReturn(dataNodes);
return result;
}

@After
public void clean() {
shardingRule = mock(ShardingRule.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private void check(final String schemaName, final Collection<String> resourceNam
}
}
Collection<String> conflictResources = new LinkedList<>();
for (String each : useResources) {
for (String each : resourceNames) {
if (useResources.contains(each)) {
conflictResources.add(each);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.shardingsphere.infra.database.type.DatabaseType;
import org.apache.shardingsphere.infra.datanode.DataNode;
import org.apache.shardingsphere.sharding.algorithm.sharding.inline.InlineExpressionParser;
import org.apache.shardingsphere.sharding.route.engine.exception.NoSuchTableException;
import org.apache.shardingsphere.test.integration.cases.assertion.IntegrationTestCaseAssertion;
import org.apache.shardingsphere.test.integration.cases.dataset.metadata.DataSetColumn;
import org.apache.shardingsphere.test.integration.cases.dataset.metadata.DataSetIndex;
Expand Down Expand Up @@ -93,6 +94,7 @@ private void dropInitializedTable(final Connection connection) {
try (PreparedStatement preparedStatement = connection.prepareStatement(String.format("DROP TABLE %s", getAssertion().getInitialSQL().getAffectedTable()))) {
preparedStatement.executeUpdate();
} catch (final SQLException ignored) {
} catch (final NoSuchTableException ignored) {
}
}

Expand Down

0 comments on commit 357cd79

Please sign in to comment.