未验证 提交 48acae5a 编写于 作者: L Liang Zhang 提交者: GitHub

Refactor shadow route module (#7277)

* Refactor shadow route module

* Refactor ShadowRouteDecorator
上级 cc4020d4
......@@ -18,9 +18,10 @@
package org.apache.shardingsphere.shadow.route.engine;
import org.apache.shardingsphere.shadow.constant.ShadowOrder;
import org.apache.shardingsphere.shadow.route.engine.judge.ShadowDataSourceJudgeEngine;
import org.apache.shardingsphere.shadow.rule.ShadowRule;
import org.apache.shardingsphere.shadow.route.engine.impl.PreparedShadowDataSourceRouter;
import org.apache.shardingsphere.shadow.route.engine.impl.SimpleShadowDataSourceRouter;
import org.apache.shardingsphere.shadow.route.engine.judge.impl.PreparedShadowDataSourceJudgeEngine;
import org.apache.shardingsphere.shadow.route.engine.judge.impl.SimpleShadowDataSourceJudgeEngine;
import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
......@@ -48,18 +49,18 @@ public final class ShadowRouteDecorator implements RouteDecorator<ShadowRule> {
}
private RouteContext getRouteContext(final RouteContext routeContext, final ShadowRule shadowRule) {
SQLStatementContext sqlStatementContext = routeContext.getSqlStatementContext();
SQLStatementContext<?> sqlStatementContext = routeContext.getSqlStatementContext();
SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
RouteResult routeResult = new RouteResult();
List<Object> parameters = routeContext.getParameters();
if (!(sqlStatement instanceof DMLStatement)) {
shadowRule.getShadowMappings().forEach((k, v) -> {
routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(k, k), Collections.emptyList()));
routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(v, v), Collections.emptyList()));
shadowRule.getShadowMappings().forEach((key, value) -> {
routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(key, key), Collections.emptyList()));
routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(value, value), Collections.emptyList()));
});
return new RouteContext(sqlStatementContext, parameters, routeResult);
}
if (isShadowSQL(routeContext, shadowRule)) {
if (isShadow(routeContext, shadowRule)) {
shadowRule.getShadowMappings().values().forEach(each -> routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(each, each), Collections.emptyList())));
} else {
shadowRule.getShadowMappings().keySet().forEach(each -> routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(each, each), Collections.emptyList())));
......@@ -79,7 +80,7 @@ public final class ShadowRouteDecorator implements RouteDecorator<ShadowRule> {
return routeContext;
}
Collection<RouteUnit> toBeRemoved = new LinkedList<>();
if (isShadowSQL(routeContext, shadowRule)) {
if (isShadow(routeContext, shadowRule)) {
for (RouteUnit each : routeContext.getRouteResult().getRouteUnits()) {
toBeRemoved.add(each);
String shadowDataSourceName = shadowRule.getShadowMappings().get(each.getDataSourceMapper().getActualName());
......@@ -91,12 +92,12 @@ public final class ShadowRouteDecorator implements RouteDecorator<ShadowRule> {
return routeContext;
}
private boolean isShadowSQL(final RouteContext routeContext, final ShadowRule shadowRule) {
private boolean isShadow(final RouteContext routeContext, final ShadowRule shadowRule) {
List<Object> parameters = routeContext.getParameters();
SQLStatementContext sqlStatementContext = routeContext.getSqlStatementContext();
ShadowDataSourceRouter shadowDataSourceRouter = parameters.isEmpty() ? new SimpleShadowDataSourceRouter(shadowRule, sqlStatementContext)
: new PreparedShadowDataSourceRouter(shadowRule, sqlStatementContext, parameters);
return shadowDataSourceRouter.isShadowSQL();
SQLStatementContext<?> sqlStatementContext = routeContext.getSqlStatementContext();
ShadowDataSourceJudgeEngine shadowDataSourceRouter = parameters.isEmpty() ? new SimpleShadowDataSourceJudgeEngine(shadowRule, sqlStatementContext)
: new PreparedShadowDataSourceJudgeEngine(shadowRule, sqlStatementContext, parameters);
return shadowDataSourceRouter.isShadow();
}
@Override
......
/*
* 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.shadow.route.engine.judge;
/**
* Shadow data source judge engine.
*/
public interface ShadowDataSourceJudgeEngine {
/**
* Judge whether shadow.
*
* @return is shadow or not
*/
boolean isShadow();
}
......@@ -15,12 +15,13 @@
* limitations under the License.
*/
package org.apache.shardingsphere.shadow.route.engine.impl;
package org.apache.shardingsphere.shadow.route.engine.judge.impl;
import com.google.common.base.Preconditions;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.shadow.route.engine.judge.util.ShadowValueJudgeUtil;
import org.apache.shardingsphere.shadow.rule.ShadowRule;
import org.apache.shardingsphere.shadow.route.engine.ShadowDataSourceRouter;
import org.apache.shardingsphere.shadow.route.engine.judge.ShadowDataSourceJudgeEngine;
import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
import org.apache.shardingsphere.sql.parser.binder.statement.dml.InsertStatementContext;
import org.apache.shardingsphere.sql.parser.binder.type.WhereAvailable;
......@@ -36,26 +37,25 @@ import java.util.List;
import java.util.Optional;
/**
* Shadow judgement engine for prepared.
* Prepared shadow data source judge engine.
*/
@RequiredArgsConstructor
public final class PreparedShadowDataSourceRouter implements ShadowDataSourceRouter {
public final class PreparedShadowDataSourceJudgeEngine implements ShadowDataSourceJudgeEngine {
private final ShadowRule shadowRule;
private final SQLStatementContext sqlStatementContext;
private final SQLStatementContext<?> sqlStatementContext;
private final List<Object> parameters;
@Override
public boolean isShadowSQL() {
public boolean isShadow() {
if (sqlStatementContext instanceof InsertStatementContext) {
Collection<ColumnSegment> columnSegments = (((InsertStatementContext) sqlStatementContext).getSqlStatement()).getColumns();
int count = 0;
for (ColumnSegment each : columnSegments) {
if (each.getIdentifier().getValue().equals(shadowRule.getColumn())) {
Object value = parameters.get(count);
return isShadowField(value);
return ShadowValueJudgeUtil.isShadowValue(parameters.get(count));
}
count++;
}
......@@ -82,8 +82,7 @@ public final class PreparedShadowDataSourceRouter implements ShadowDataSourceRou
Preconditions.checkArgument(each.getRightValue() instanceof PredicateCompareRightValue, "must be PredicateCompareRightValue");
PredicateCompareRightValue rightValue = (PredicateCompareRightValue) each.getRightValue();
int parameterMarkerIndex = ((ParameterMarkerExpressionSegment) rightValue.getExpression()).getParameterMarkerIndex();
Object value = parameters.get(parameterMarkerIndex);
return isShadowField(value);
return ShadowValueJudgeUtil.isShadowValue(parameters.get(parameterMarkerIndex));
}
}
return false;
......
......@@ -15,13 +15,14 @@
* limitations under the License.
*/
package org.apache.shardingsphere.shadow.route.engine.impl;
package org.apache.shardingsphere.shadow.route.engine.judge.impl;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.shadow.rule.ShadowRule;
import org.apache.shardingsphere.shadow.condition.ShadowCondition;
import org.apache.shardingsphere.shadow.condition.ShadowConditionEngine;
import org.apache.shardingsphere.shadow.route.engine.ShadowDataSourceRouter;
import org.apache.shardingsphere.shadow.route.engine.judge.ShadowDataSourceJudgeEngine;
import org.apache.shardingsphere.shadow.route.engine.judge.util.ShadowValueJudgeUtil;
import org.apache.shardingsphere.shadow.rule.ShadowRule;
import org.apache.shardingsphere.sql.parser.binder.segment.insert.values.InsertValueContext;
import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
import org.apache.shardingsphere.sql.parser.binder.statement.dml.InsertStatementContext;
......@@ -33,17 +34,17 @@ import java.util.List;
import java.util.Optional;
/**
* Simple shadow judgement engine.
* Simple shadow data source judge engine.
*/
@RequiredArgsConstructor
public final class SimpleShadowDataSourceRouter implements ShadowDataSourceRouter {
public final class SimpleShadowDataSourceJudgeEngine implements ShadowDataSourceJudgeEngine {
private final ShadowRule shadowRule;
private final SQLStatementContext sqlStatementContext;
private final SQLStatementContext<?> sqlStatementContext;
@Override
public boolean isShadowSQL() {
public boolean isShadow() {
if (sqlStatementContext instanceof InsertStatementContext) {
for (InsertValueContext each : ((InsertStatementContext) sqlStatementContext).getInsertValueContexts()) {
if (judgeShadowSqlForInsert(each, (InsertStatementContext) sqlStatementContext)) {
......@@ -58,7 +59,7 @@ public final class SimpleShadowDataSourceRouter implements ShadowDataSourceRoute
return false;
}
List<Object> values = shadowCondition.get().getValues(Collections.emptyList());
return !values.isEmpty() && isShadowField(values.get(0));
return !values.isEmpty() && ShadowValueJudgeUtil.isShadowValue(values.get(0));
}
return false;
}
......@@ -69,8 +70,7 @@ public final class SimpleShadowDataSourceRouter implements ShadowDataSourceRoute
String columnName = descendingColumnNames.next();
if (shadowRule.getColumn().equals(columnName)) {
int columnIndex = insertStatementContext.getColumnNames().indexOf(columnName);
Object value = insertValueContext.getValue(columnIndex);
return isShadowField(value);
return ShadowValueJudgeUtil.isShadowValue(insertValueContext.getValue(columnIndex));
}
}
return false;
......
......@@ -15,28 +15,25 @@
* limitations under the License.
*/
package org.apache.shardingsphere.shadow.route.engine;
package org.apache.shardingsphere.shadow.route.engine.judge.util;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* Route decorator for shadow.
* Shadow value judge util.
*/
public interface ShadowDataSourceRouter {
/**
* Judge whether SQL is shadow.
*
* @return SQL is shadow or not
*/
boolean isShadowSQL();
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ShadowValueJudgeUtil {
/**
* Judge whether field is shadow.
* @param value the field
* @return field is shadow or not
* Judge whether shadow value.
*
* @param value value to be judged
* @return is shadow value ot not
*/
default boolean isShadowField(final Object value) {
public static boolean isShadowValue(final Object value) {
return (value instanceof Boolean && (Boolean) value)
|| (value instanceof Integer && 1 == (Integer) value)
|| (value instanceof String && Boolean.parseBoolean((String) value));
|| (value instanceof Integer && 1 == (Integer) value) || (value instanceof String && Boolean.parseBoolean((String) value));
}
}
......@@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.apache.shardingsphere.shadow.route.engine.impl;
package org.apache.shardingsphere.shadow.route.engine.judge.impl;
import org.apache.shardingsphere.shadow.api.config.ShadowRuleConfiguration;
import org.apache.shardingsphere.shadow.rule.ShadowRule;
......@@ -49,7 +49,7 @@ public final class PreparedShadowDataSourceRouterTest {
Arrays.asList(new ColumnSegment(0, 0, new IdentifierValue("id")), new ColumnSegment(0, 0, new IdentifierValue("name")), new ColumnSegment(0, 0, new IdentifierValue("shadow"))));
insertStatement.setInsertColumns(insertColumnsSegment);
InsertStatementContext insertStatementContext = new InsertStatementContext(schemaMetaData, Arrays.asList(1, "Tom", 2, "Jerry", 3, true), insertStatement);
PreparedShadowDataSourceRouter preparedShadowDataSourceRouter = new PreparedShadowDataSourceRouter(shadowRule, insertStatementContext, Arrays.asList(1, "Tom", true));
assertTrue("should be shadow", preparedShadowDataSourceRouter.isShadowSQL());
PreparedShadowDataSourceJudgeEngine preparedShadowDataSourceRouter = new PreparedShadowDataSourceJudgeEngine(shadowRule, insertStatementContext, Arrays.asList(1, "Tom", true));
assertTrue("should be shadow", preparedShadowDataSourceRouter.isShadow());
}
}
......@@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.apache.shardingsphere.shadow.route.engine.impl;
package org.apache.shardingsphere.shadow.route.engine.judge.impl;
import org.apache.shardingsphere.shadow.api.config.ShadowRuleConfiguration;
import org.apache.shardingsphere.shadow.rule.ShadowRule;
......@@ -71,14 +71,14 @@ public final class SimpleShadowDataSourceRouterTest {
insertStatement.getValues().addAll(Collections.singletonList(new InsertValuesSegment(
0, 0, Arrays.asList(new LiteralExpressionSegment(0, 0, 1), new LiteralExpressionSegment(0, 0, "name"), new LiteralExpressionSegment(0, 0, true)))));
InsertStatementContext insertStatementContext = new InsertStatementContext(schemaMetaData, Collections.emptyList(), insertStatement);
SimpleShadowDataSourceRouter simpleShadowDataSourceRouter = new SimpleShadowDataSourceRouter(shadowRule, insertStatementContext);
assertTrue("should be shadow", simpleShadowDataSourceRouter.isShadowSQL());
SimpleShadowDataSourceJudgeEngine simpleShadowDataSourceRouter = new SimpleShadowDataSourceJudgeEngine(shadowRule, insertStatementContext);
assertTrue("should be shadow", simpleShadowDataSourceRouter.isShadow());
insertStatement.getValues().clear();
insertStatement.getValues().addAll(Collections.singletonList(
new InsertValuesSegment(0, 0, Arrays.asList(new LiteralExpressionSegment(0, 0, 1), new LiteralExpressionSegment(0, 0, "name"), new LiteralExpressionSegment(0, 0, false)))));
insertStatementContext = new InsertStatementContext(schemaMetaData, Collections.emptyList(), insertStatement);
simpleShadowDataSourceRouter = new SimpleShadowDataSourceRouter(shadowRule, insertStatementContext);
assertFalse("should not be shadow", simpleShadowDataSourceRouter.isShadowSQL());
simpleShadowDataSourceRouter = new SimpleShadowDataSourceJudgeEngine(shadowRule, insertStatementContext);
assertFalse("should not be shadow", simpleShadowDataSourceRouter.isShadow());
}
@Test
......@@ -95,13 +95,13 @@ public final class SimpleShadowDataSourceRouterTest {
projectionsSegment.getProjections().addAll(Collections.singletonList(new ExpressionProjectionSegment(0, 0, "true")));
selectStatement.setProjections(projectionsSegment);
SelectStatementContext selectStatementContext = new SelectStatementContext(schemaMetaData, Collections.emptyList(), selectStatement);
SimpleShadowDataSourceRouter simpleShadowDataSourceRouter = new SimpleShadowDataSourceRouter(shadowRule, selectStatementContext);
assertTrue("should be shadow", simpleShadowDataSourceRouter.isShadowSQL());
SimpleShadowDataSourceJudgeEngine simpleShadowDataSourceRouter = new SimpleShadowDataSourceJudgeEngine(shadowRule, selectStatementContext);
assertTrue("should be shadow", simpleShadowDataSourceRouter.isShadow());
andPredicate.getPredicates().clear();
andPredicate.getPredicates().addAll(Collections.singletonList(
new PredicateSegment(0, 0, new ColumnSegment(0, 0, new IdentifierValue("shadow")), new PredicateCompareRightValue(0, 0, "=", new LiteralExpressionSegment(0, 0, false)))));
projectionsSegment.getProjections().clear();
projectionsSegment.getProjections().addAll(Collections.singletonList(new ExpressionProjectionSegment(0, 0, "false")));
assertFalse("should not be shadow", simpleShadowDataSourceRouter.isShadowSQL());
assertFalse("should not be shadow", simpleShadowDataSourceRouter.isShadow());
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册