Skip to content

Commit

Permalink
Merge 0f912fb into 2c2ca80
Browse files Browse the repository at this point in the history
  • Loading branch information
sunbufu committed Sep 16, 2019
2 parents 2c2ca80 + 0f912fb commit ed483ed
Show file tree
Hide file tree
Showing 11 changed files with 668 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,12 @@ public InlineShardingStrategyConfiguration(final String shardingColumn, final St
this.shardingColumn = shardingColumn;
this.algorithmExpression = algorithmExpression;
}

@Override
public String toString() {
return "Inline{"
+ "shardingColumn='" + shardingColumn + '\''
+ ", algorithmExpression='" + algorithmExpression + '\''
+ '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,9 @@ public void assertConstructorWithFullArguments() {
assertThat(actual.getShardingColumn(), is("id"));
assertThat(actual.getAlgorithmExpression(), is("ds_$->{id%16}"));
}

@Test
public void assertToString() {
assertThat(new InlineShardingStrategyConfiguration("id", "ds_$->{id%2}").toString(), is("Inline{shardingColumn='id', algorithmExpression='ds_$->{id%2}'}"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@

package org.apache.shardingsphere.core.strategy.route.value;

import com.google.common.base.Joiner;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

import java.util.ArrayList;
import java.util.Collection;

/**
Expand All @@ -30,12 +31,17 @@
*/
@RequiredArgsConstructor
@Getter
@ToString
public final class ListRouteValue<T extends Comparable<?>> implements RouteValue {

private final String columnName;

private final String tableName;

private final Collection<T> values;

@Override
public String toString() {
return tableName + "." + columnName
+ (1 == values.size() ? " = " + new ArrayList<>(values).get(0) : " in (" + Joiner.on(",").join(values) + ")");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.core.strategy.route.value;

import org.junit.Test;

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

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

public class ListRouteValueTest {

@Test
public void assertToStringWithEqual() {
assertThat(new ListRouteValue("order_id", "t_order", Collections.singleton(10)).toString(), is("t_order.order_id = 10"));
}

@Test
public void assertToStringWithIn() {
assertThat(new ListRouteValue("order_id", "t_order", Arrays.asList(10, 20)).toString(), is("t_order.order_id in (10,20)"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.apache.shardingsphere.core.parse.SQLParseEngine;
import org.apache.shardingsphere.core.parse.sql.statement.SQLStatement;
import org.apache.shardingsphere.core.route.SQLRouteResult;
import org.apache.shardingsphere.core.route.type.RoutingEngine;
import org.apache.shardingsphere.core.route.type.RoutingResult;
import org.apache.shardingsphere.core.rule.BindingTableRule;
import org.apache.shardingsphere.core.rule.ShardingRule;
Expand Down Expand Up @@ -78,7 +79,9 @@ public SQLRouteResult route(final String logicSQL, final List<Object> parameters
checkSubqueryShardingValues(shardingStatement, ((ShardingConditionOptimizedStatement) shardingStatement).getShardingConditions());
mergeShardingConditions(((ShardingConditionOptimizedStatement) shardingStatement).getShardingConditions());
}
RoutingResult routingResult = RoutingEngineFactory.newInstance(shardingRule, metaData.getDataSources(), shardingStatement).route();
RoutingEngine routingEngine = RoutingEngineFactory.newInstance(shardingRule, metaData.getDataSources(), shardingStatement);
RoutingResult routingResult = routingEngine.route();
new ParsingSQLRoutingResultChecker(shardingRule, metaData, shardingStatement).check(routingEngine, routingResult);
if (needMergeShardingValues) {
Preconditions.checkState(1 == routingResult.getRoutingUnits().size(), "Must have one sharding with subquery.");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/*
* 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.core.route.router.sharding;

import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.ShardingStrategyConfiguration;
import org.apache.shardingsphere.core.exception.ShardingException;
import org.apache.shardingsphere.core.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.core.optimize.sharding.segment.condition.ShardingCondition;
import org.apache.shardingsphere.core.optimize.sharding.statement.ShardingOptimizedStatement;
import org.apache.shardingsphere.core.optimize.sharding.statement.ddl.ShardingDropIndexOptimizedStatement;
import org.apache.shardingsphere.core.optimize.sharding.statement.dml.ShardingConditionOptimizedStatement;
import org.apache.shardingsphere.core.parse.sql.statement.dml.DMLStatement;
import org.apache.shardingsphere.core.route.type.RoutingEngine;
import org.apache.shardingsphere.core.route.type.RoutingResult;
import org.apache.shardingsphere.core.route.type.RoutingUnit;
import org.apache.shardingsphere.core.route.type.TableUnit;
import org.apache.shardingsphere.core.route.type.standard.StandardRoutingEngine;
import org.apache.shardingsphere.core.rule.ShardingRule;
import org.apache.shardingsphere.core.rule.TableRule;
import org.apache.shardingsphere.core.strategy.route.value.RouteValue;

import java.util.Collection;
import java.util.LinkedList;

/**
* Checker for sharding router with parse.
*
* @author sunbufu
*/
public class ParsingSQLRoutingResultChecker implements RoutingResultChecker {

private final ShardingRule shardingRule;

private final ShardingSphereMetaData metaData;

private final ShardingOptimizedStatement shardingStatement;

private boolean checkDataSource;

private boolean checkTable;

public ParsingSQLRoutingResultChecker(final ShardingRule shardingRule, final ShardingSphereMetaData metaData, final ShardingOptimizedStatement shardingStatement) {
this.shardingRule = shardingRule;
this.metaData = metaData;
this.shardingStatement = shardingStatement;
if (shardingRule.getRuleConfiguration().getMasterSlaveRuleConfigs().isEmpty()) {
checkDataSource = true;
}
if (shardingStatement.getSQLStatement() instanceof DMLStatement) {
checkTable = true;
}
}

/**
* Check for ParsingSQLRouter's routing result.
*
* @param routingEngine routing engine
* @param routingResult routing result
*/
@Override
public void check(final RoutingEngine routingEngine, final RoutingResult routingResult) {
if (shardingStatement instanceof ShardingDropIndexOptimizedStatement) {
return;
}
Multimap<RoutingUnit, TableUnit> absentRoutingUnitMap = getAbsentRoutingUnit(routingResult.getRoutingUnits());
if (absentRoutingUnitMap.isEmpty()) {
return;
}
if (routingEngine instanceof StandardRoutingEngine) {
throwAbsentStandardRoutingResultException(shardingStatement, absentRoutingUnitMap);
} else {
throwOthersRoutingResultException(absentRoutingUnitMap);
}
}

/**
* Throw other's absent routing result exception.
*
* @param absentRoutingUnitMap absent routingUnit map
*/
private void throwOthersRoutingResultException(final Multimap<RoutingUnit, TableUnit> absentRoutingUnitMap) {
RoutingUnit routingUnit = absentRoutingUnitMap.keySet().iterator().next();
Collection<String> absentDataNodes = Lists.newArrayListWithExpectedSize(absentRoutingUnitMap.get(routingUnit).size());
for (TableUnit each : absentRoutingUnitMap.get(routingUnit)) {
absentDataNodes.add(routingUnit.getDataSourceName() + "." + each.getActualTableName());
}
if (!absentDataNodes.isEmpty()) {
throwExceptionForAbsentDataNode(absentDataNodes, "");
}
}

/**
* Throw StandardRoutingEngine's absent routing result exception.
*
* @param shardingStatement sharding statement
* @param absentRoutingUnitMap absent routing unit map
*/
private void throwAbsentStandardRoutingResultException(final ShardingOptimizedStatement shardingStatement, final Multimap<RoutingUnit, TableUnit> absentRoutingUnitMap) {
RoutingUnit routingUnit = absentRoutingUnitMap.keySet().iterator().next();
Collection<String> absentDataNodes = Lists.newArrayListWithExpectedSize(absentRoutingUnitMap.get(routingUnit).size());
ShardingStrategyConfiguration databaseStrategy = null;
ShardingStrategyConfiguration tableStrategy = null;
if (null != shardingRule.getRuleConfiguration().getDefaultDatabaseShardingStrategyConfig()) {
databaseStrategy = shardingRule.getRuleConfiguration().getDefaultDatabaseShardingStrategyConfig();
}
if (null != shardingRule.getRuleConfiguration().getDefaultTableShardingStrategyConfig()) {
tableStrategy = shardingRule.getRuleConfiguration().getDefaultTableShardingStrategyConfig();
}
for (TableUnit each : absentRoutingUnitMap.get(routingUnit)) {
absentDataNodes.add(routingUnit.getDataSourceName() + "." + each.getActualTableName());
Optional<TableRuleConfiguration> tableRuleConfiguration = getTableRuleConfiguration(shardingRule.getRuleConfiguration().getTableRuleConfigs(), each.getLogicTableName());
if (!tableRuleConfiguration.isPresent()) {
continue;
}
databaseStrategy = tableRuleConfiguration.get().getDatabaseShardingStrategyConfig();
tableStrategy = tableRuleConfiguration.get().getTableShardingStrategyConfig();
}
if (!absentDataNodes.isEmpty()) {
StringBuilder detail = new StringBuilder();
if (null != databaseStrategy) {
detail.append("DatabaseStrategy=[").append(databaseStrategy).append("], ");
}
detail.append("TableStrategy=[").append(tableStrategy).append("], ");
if (shardingStatement instanceof ShardingConditionOptimizedStatement) {
detail.append("with ")
.append(getAllRouteValues(((ShardingConditionOptimizedStatement) shardingStatement).getShardingConditions().getConditions()))
.append(", ");
}
throwExceptionForAbsentDataNode(absentDataNodes, detail);
}
}

private Multimap<RoutingUnit, TableUnit> getAbsentRoutingUnit(final Collection<RoutingUnit> routingUnits) {
Multimap<RoutingUnit, TableUnit> result = HashMultimap.create();
for (RoutingUnit each : routingUnits) {
String dataSourceName = each.getDataSourceName();
result.putAll(each, getAbsentTableUnit(each, dataSourceName));
}
return result;
}

private Collection<TableUnit> getAbsentTableUnit(final RoutingUnit routingUnit, final String dataSourceName) {
Collection<TableUnit> result = new LinkedList<>();
for (TableUnit each : routingUnit.getTableUnits()) {
if (containsInMetaData(dataSourceName, each.getActualTableName()) || containsInShardingRule(dataSourceName, each)) {
continue;
}
result.add(each);
}
return result;
}

private boolean containsInShardingRule(final String dataSourceName, final TableUnit tableUnit) {
Optional<TableRule> tableRule = shardingRule.findTableRule(tableUnit.getLogicTableName());
return tableRule.isPresent() && tableRule.get().getActualTableNames(dataSourceName).contains(tableUnit.getActualTableName());
}

private boolean containsInMetaData(final String dataSourceName, final String actualTableName) {
if (checkDataSource && (null == metaData.getDataSources() || null == metaData.getDataSources().getDataSourceMetaData(dataSourceName))) {
return false;
}
if (checkTable && (null == metaData.getTables() || !metaData.getTables().containsTable(actualTableName))) {
return false;
}
return true;
}

private void throwExceptionForAbsentDataNode(final Collection<String> absentDataNodes, final CharSequence detail) {
String msg = "We get some absent DataNodes=" + absentDataNodes + " in routing result, "
+ (Strings.isNullOrEmpty(detail.toString()) ? "" : detail)
+ "please check the configuration of rule and data node.";
throw new ShardingException(msg.replace("%", "%%"));
}

private Optional<TableRuleConfiguration> getTableRuleConfiguration(final Collection<TableRuleConfiguration> tableRuleConfigurations, final String tableName) {
for (TableRuleConfiguration each : tableRuleConfigurations) {
if (tableName.equals(each.getLogicTable())) {
return Optional.of(each);
}
}
return Optional.absent();
}

private Collection<RouteValue> getAllRouteValues(final Collection<ShardingCondition> shardingConditions) {
Collection<RouteValue> result = new LinkedList<>();
for (ShardingCondition each : shardingConditions) {
result.addAll(each.getRouteValues());
}
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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.core.route.router.sharding;

import org.apache.shardingsphere.core.route.type.RoutingEngine;
import org.apache.shardingsphere.core.route.type.RoutingResult;

/**
* RoutingResult checker.
*
* @author sunbufu
*/
public interface RoutingResultChecker {

/**
* Check routing result.
*
* @param routingEngine routing engine
* @param routingResult routing result
*/
void check(RoutingEngine routingEngine, RoutingResult routingResult);
}

0 comments on commit ed483ed

Please sign in to comment.