未验证 提交 467139b0 编写于 作者: Z zhyee 提交者: GitHub

add ShadowRouteDecorator for refactor shadow route (#5538)

* add ShadowRouteDecorator for refactor shadow route

* fix datasource name

* fix datasource logic name

* isShadowSql -> isShadowSQL
上级 2d46970a
......@@ -31,5 +31,7 @@
<modules>
<module>shadow-core-rewrite</module>
<module>shadow-core-common</module>
<module>shadow-core-route</module>
</modules>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shadow-core</artifactId>
<groupId>org.apache.shardingsphere</groupId>
<version>5.0.0-RC1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shadow-core-common</artifactId>
<name>${project.artifactId}</name>
<dependencies>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-core-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-route</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
......@@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.apache.shardingsphere.shadow.rewrite.condition;
package org.apache.shardingsphere.shadow.common.condition;
import lombok.EqualsAndHashCode;
import lombok.Getter;
......
......@@ -15,11 +15,12 @@
* limitations under the License.
*/
package org.apache.shardingsphere.shadow.rewrite.condition;
package org.apache.shardingsphere.shadow.common.condition;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.core.rule.ShadowRule;
import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
import org.apache.shardingsphere.sql.parser.binder.type.WhereAvailable;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.expr.simple.SimpleExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.AndPredicate;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.PredicateSegment;
......@@ -27,7 +28,6 @@ import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.WhereSegme
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.value.PredicateBetweenRightValue;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.value.PredicateCompareRightValue;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.value.PredicateInRightValue;
import org.apache.shardingsphere.sql.parser.binder.type.WhereAvailable;
import org.apache.shardingsphere.underlying.common.exception.ShardingSphereException;
import java.util.Collection;
......
......@@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.apache.shardingsphere.shadow.rewrite.condition;
package org.apache.shardingsphere.shadow.common.condition;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.expr.simple.LiteralExpressionSegment;
import org.junit.Test;
......
......@@ -34,6 +34,11 @@
<artifactId>sharding-core-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shadow-core-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-sql-parser-binder</artifactId>
......
......@@ -20,6 +20,7 @@ package org.apache.shardingsphere.shadow.rewrite.judgement;
/**
* Shadow judgement engine.
*/
//TODO need to remove
public interface ShadowJudgementEngine {
/**
......
......@@ -38,6 +38,7 @@ import java.util.Optional;
/**
* Shadow judgement engine for prepared.
*/
//TODO need to remove
@RequiredArgsConstructor
public final class PreparedJudgementEngine implements ShadowJudgementEngine {
......
......@@ -19,8 +19,8 @@ package org.apache.shardingsphere.shadow.rewrite.judgement.impl;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.core.rule.ShadowRule;
import org.apache.shardingsphere.shadow.rewrite.condition.ShadowCondition;
import org.apache.shardingsphere.shadow.rewrite.condition.ShadowConditionEngine;
import org.apache.shardingsphere.shadow.common.condition.ShadowCondition;
import org.apache.shardingsphere.shadow.common.condition.ShadowConditionEngine;
import org.apache.shardingsphere.shadow.rewrite.judgement.ShadowJudgementEngine;
import org.apache.shardingsphere.sql.parser.binder.segment.insert.values.InsertValueContext;
import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
......@@ -35,6 +35,7 @@ import java.util.Optional;
/**
* Simple shadow judgement engine.
*/
//TODO need to remove
@RequiredArgsConstructor
public final class SimpleJudgementEngine implements ShadowJudgementEngine {
......
......@@ -17,7 +17,7 @@
package org.apache.shardingsphere.shadow.rewrite.parameter.impl;
import org.apache.shardingsphere.shadow.rewrite.condition.ShadowConditionEngine;
import org.apache.shardingsphere.shadow.common.condition.ShadowConditionEngine;
import org.apache.shardingsphere.shadow.rewrite.parameter.ShadowParameterRewriter;
import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
import org.apache.shardingsphere.underlying.rewrite.parameter.builder.ParameterBuilder;
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shadow-core</artifactId>
<groupId>org.apache.shardingsphere</groupId>
<version>5.0.0-RC1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shadow-core-route</artifactId>
<name>${project.artifactId}</name>
<dependencies>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-core-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shadow-core-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-route</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
/*
* 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;
/**
* Route decorator for shadow.
*/
public interface ShadowDataSourceRouter {
/**
* Judge whether SQL is shadow.
*
* @return SQL is shadow or not
*/
boolean isShadowSQL();
/**
* Judge whether field is shadow.
* @param value the field
* @return field is shadow or not
*/
default boolean isShadowField(final Object value) {
return (value instanceof Boolean && (Boolean) value)
|| (value instanceof Integer && 1 == (Integer) value)
|| (value instanceof String && Boolean.parseBoolean((String) value));
}
}
/*
* 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;
import org.apache.shardingsphere.core.rule.ShadowRule;
import org.apache.shardingsphere.shadow.route.engine.impl.PreparedShadowDataSourceRouter;
import org.apache.shardingsphere.shadow.route.engine.impl.SimpleShadowDataSourceRouter;
import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
import org.apache.shardingsphere.sql.parser.sql.statement.SQLStatement;
import org.apache.shardingsphere.sql.parser.sql.statement.dml.DMLStatement;
import org.apache.shardingsphere.underlying.common.config.properties.ConfigurationProperties;
import org.apache.shardingsphere.underlying.common.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.underlying.route.context.RouteContext;
import org.apache.shardingsphere.underlying.route.context.RouteMapper;
import org.apache.shardingsphere.underlying.route.context.RouteResult;
import org.apache.shardingsphere.underlying.route.context.RouteUnit;
import org.apache.shardingsphere.underlying.route.decorator.RouteDecorator;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Route decorator for shadow.
*/
public final class ShadowRouteDecorator implements RouteDecorator<ShadowRule> {
@Override
public RouteContext decorate(final RouteContext routeContext, final ShardingSphereMetaData metaData, final ShadowRule shadowRule, final ConfigurationProperties properties) {
return routeContext.getRouteResult().getRouteUnits().isEmpty() ? getRouteContext(routeContext, shadowRule) : getRouteContextWithRouteResult(routeContext, shadowRule);
}
private RouteContext getRouteContext(final RouteContext routeContext, final ShadowRule shadowRule) {
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()));
});
return new RouteContext(sqlStatementContext, parameters, routeResult);
}
if (isShadowSQL(routeContext, shadowRule)) {
shadowRule.getShadowMappings().keySet().forEach(each -> routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(each, each), Collections.emptyList())));
} else {
shadowRule.getShadowMappings().values().forEach(each -> routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(each, each), Collections.emptyList())));
}
return new RouteContext(sqlStatementContext, parameters, routeResult);
}
private RouteContext getRouteContextWithRouteResult(final RouteContext routeContext, final ShadowRule shadowRule) {
SQLStatement sqlStatement = routeContext.getSqlStatementContext().getSqlStatement();
Collection<RouteUnit> toBeAdded = new LinkedList<>();
if (!(sqlStatement instanceof DMLStatement)) {
for (RouteUnit each : routeContext.getRouteResult().getRouteUnits()) {
String shadowDataSourceName = shadowRule.getShadowMappings().get(each.getDataSourceMapper().getActualName());
toBeAdded.add(new RouteUnit(new RouteMapper(each.getDataSourceMapper().getLogicName(), shadowDataSourceName), Collections.emptyList()));
}
routeContext.getRouteResult().getRouteUnits().addAll(toBeAdded);
return routeContext;
}
if (isShadowSQL(routeContext, shadowRule)) {
for (RouteUnit each : routeContext.getRouteResult().getRouteUnits()) {
routeContext.getRouteResult().getRouteUnits().remove(each);
String shadowDataSourceName = shadowRule.getShadowMappings().get(each.getDataSourceMapper().getActualName());
routeContext.getRouteResult().getRouteUnits().add(new RouteUnit(new RouteMapper(each.getDataSourceMapper().getLogicName(), shadowDataSourceName), Collections.emptyList()));
}
}
return routeContext;
}
private boolean isShadowSQL(final RouteContext routeContext, final ShadowRule shadowRule) {
List<Object> parameters = routeContext.getParameters();
SQLStatementContext sqlStatementContext = routeContext.getSqlStatementContext();
ShadowDataSourceRouter shadowDataSourceRouter = parameters == null ? new SimpleShadowDataSourceRouter(shadowRule, sqlStatementContext)
: new PreparedShadowDataSourceRouter(shadowRule, sqlStatementContext, parameters);
return shadowDataSourceRouter.isShadowSQL();
}
@Override
public int getOrder() {
return 20;
}
@Override
public Class<ShadowRule> getTypeClass() {
return ShadowRule.class;
}
}
/*
* 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.impl;
import com.google.common.base.Preconditions;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.core.rule.ShadowRule;
import org.apache.shardingsphere.shadow.route.engine.ShadowDataSourceRouter;
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;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.column.ColumnSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.AndPredicate;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.PredicateSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.WhereSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.value.PredicateCompareRightValue;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
/**
* Shadow judgement engine for prepared.
*/
@RequiredArgsConstructor
public final class PreparedShadowDataSourceRouter implements ShadowDataSourceRouter {
private final ShadowRule shadowRule;
private final SQLStatementContext sqlStatementContext;
private final List<Object> parameters;
@Override
public boolean isShadowSQL() {
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);
}
count++;
}
return false;
}
if (sqlStatementContext instanceof WhereAvailable) {
Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
if (!whereSegment.isPresent()) {
return false;
}
Collection<AndPredicate> andPredicates = whereSegment.get().getAndPredicates();
for (AndPredicate andPredicate : andPredicates) {
if (judgePredicateSegments(andPredicate.getPredicates())) {
return true;
}
}
}
return false;
}
private boolean judgePredicateSegments(final Collection<PredicateSegment> predicates) {
for (PredicateSegment each : predicates) {
if (each.getColumn().getIdentifier().getValue().equals(shadowRule.getColumn())) {
Preconditions.checkArgument(each.getRightValue() instanceof PredicateCompareRightValue, "must be PredicateCompareRightValue");
PredicateCompareRightValue rightValue = (PredicateCompareRightValue) each.getRightValue();
int parameterMarkerIndex = ((ParameterMarkerExpressionSegment) rightValue.getExpression()).getParameterMarkerIndex();
final Object value = parameters.get(parameterMarkerIndex);
return isShadowField(value);
}
}
return false;
}
}
/*
* 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.impl;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.core.rule.ShadowRule;
import org.apache.shardingsphere.shadow.common.condition.ShadowCondition;
import org.apache.shardingsphere.shadow.common.condition.ShadowConditionEngine;
import org.apache.shardingsphere.shadow.route.engine.ShadowDataSourceRouter;
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;
import org.apache.shardingsphere.sql.parser.binder.type.WhereAvailable;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
/**
* Simple shadow judgement engine.
*/
@RequiredArgsConstructor
public final class SimpleShadowDataSourceRouter implements ShadowDataSourceRouter {
private final ShadowRule shadowRule;
private final SQLStatementContext sqlStatementContext;
@Override
public boolean isShadowSQL() {
if (sqlStatementContext instanceof InsertStatementContext) {
for (InsertValueContext each : ((InsertStatementContext) sqlStatementContext).getInsertValueContexts()) {
if (judgeShadowSqlForInsert(each, (InsertStatementContext) sqlStatementContext)) {
return true;
}
}
return false;
}
if (sqlStatementContext instanceof WhereAvailable) {
Optional<ShadowCondition> shadowCondition = new ShadowConditionEngine(shadowRule).createShadowCondition(sqlStatementContext);
if (!shadowCondition.isPresent()) {
return false;
}
List<Object> values = shadowCondition.get().getValues(Collections.emptyList());
return values.size() != 0 && isShadowField(values.get(0));
}
return false;
}
private boolean judgeShadowSqlForInsert(final InsertValueContext insertValueContext, final InsertStatementContext insertStatementContext) {
Iterator<String> descendingColumnNames = insertStatementContext.getDescendingColumnNames();
while (descendingColumnNames.hasNext()) {
String columnName = descendingColumnNames.next();
if (shadowRule.getColumn().equals(columnName)) {
int columnIndex = insertStatementContext.getColumnNames().indexOf(columnName);
Object value = insertValueContext.getValue(columnIndex);
return isShadowField(value);
}
}
return false;
}
}
#
# 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.
#
org.apache.shardingsphere.shadow.route.engine.ShadowRouteDecorator
/*
* 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.impl;
import org.apache.shardingsphere.api.config.shadow.ShadowRuleConfiguration;
import org.apache.shardingsphere.core.rule.ShadowRule;
import org.apache.shardingsphere.sql.parser.binder.metadata.schema.SchemaMetaData;
import org.apache.shardingsphere.sql.parser.binder.statement.dml.InsertStatementContext;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.column.ColumnSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.column.InsertColumnsSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.generic.table.SimpleTableSegment;
import org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement;
import org.apache.shardingsphere.sql.parser.sql.value.identifier.IdentifierValue;
import org.junit.Assert;
import org.junit.Test;
import java.util.Arrays;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class PreparedShadowDataSourceRouterTest {
@Test
public void isShadowSQL() {
SchemaMetaData schemaMetaData = mock(SchemaMetaData.class);
when(schemaMetaData.getAllColumnNames("tbl")).thenReturn(Arrays.asList("id", "name", "shadow"));
ShadowRuleConfiguration shadowRuleConfiguration = new ShadowRuleConfiguration();
shadowRuleConfiguration.setColumn("shadow");
ShadowRule shadowRule = new ShadowRule(shadowRuleConfiguration);
InsertStatement insertStatement = new InsertStatement();
insertStatement.setTable(new SimpleTableSegment(0, 0, new IdentifierValue("tbl")));
InsertColumnsSegment insertColumnsSegment = new InsertColumnsSegment(0, 0,
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));
Assert.assertTrue("should be shadow", preparedShadowDataSourceRouter.isShadowSQL());
}
}
/*
* 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.impl;
import org.apache.shardingsphere.api.config.shadow.ShadowRuleConfiguration;
import org.apache.shardingsphere.core.rule.ShadowRule;
import org.apache.shardingsphere.sql.parser.binder.metadata.schema.SchemaMetaData;
import org.apache.shardingsphere.sql.parser.binder.statement.dml.InsertStatementContext;
import org.apache.shardingsphere.sql.parser.binder.statement.dml.SelectStatementContext;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.assignment.InsertValuesSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.column.ColumnSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.column.InsertColumnsSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.expr.simple.LiteralExpressionSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.item.ExpressionProjectionSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.item.ProjectionsSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.AndPredicate;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.PredicateSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.WhereSegment;
import org.apache.shardingsphere.sql.parser.sql.segment.dml.predicate.value.PredicateCompareRightValue;
import org.apache.shardingsphere.sql.parser.sql.segment.generic.table.SimpleTableSegment;
import org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement;
import org.apache.shardingsphere.sql.parser.sql.statement.dml.SelectStatement;
import org.apache.shardingsphere.sql.parser.sql.value.identifier.IdentifierValue;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class SimpleShadowDataSourceRouterTest {
private SchemaMetaData schemaMetaData;
private ShadowRule shadowRule;
@Before
public void setUp() {
schemaMetaData = mock(SchemaMetaData.class);
when(schemaMetaData.getAllColumnNames("tbl")).thenReturn(Arrays.asList("id", "name", "shadow"));
ShadowRuleConfiguration shadowRuleConfiguration = new ShadowRuleConfiguration();
shadowRuleConfiguration.setColumn("shadow");
shadowRule = new ShadowRule(shadowRuleConfiguration);
}
@Test
public void judgeForInsert() {
InsertStatement insertStatement = new InsertStatement();
insertStatement.setTable(new SimpleTableSegment(0, 0, new IdentifierValue("tbl")));
InsertColumnsSegment insertColumnsSegment = new InsertColumnsSegment(0, 0,
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);
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);
Assert.assertTrue("should be shadow", simpleShadowDataSourceRouter.isShadowSQL());
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);
Assert.assertFalse("should not be shadow", simpleShadowDataSourceRouter.isShadowSQL());
}
@Test
public void judgeForWhereSegment() {
SelectStatement selectStatement = new SelectStatement();
WhereSegment whereSegment = new WhereSegment(0, 0);
AndPredicate andPredicate = new AndPredicate();
andPredicate.getPredicates().addAll(Collections.singletonList(
new PredicateSegment(0, 0, new ColumnSegment(0, 0, new IdentifierValue("shadow")), new PredicateCompareRightValue("=", new LiteralExpressionSegment(0, 0, true)))));
whereSegment.getAndPredicates().addAll(Collections.singletonList(andPredicate));
selectStatement.setWhere(whereSegment);
ProjectionsSegment projectionsSegment = new ProjectionsSegment(0, 0);
projectionsSegment.setDistinctRow(true);
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);
Assert.assertTrue("should be shadow", simpleShadowDataSourceRouter.isShadowSQL());
andPredicate.getPredicates().clear();
andPredicate.getPredicates().addAll(Collections.singletonList(
new PredicateSegment(0, 0, new ColumnSegment(0, 0, new IdentifierValue("shadow")), new PredicateCompareRightValue("=", new LiteralExpressionSegment(0, 0, false)))));
projectionsSegment.getProjections().clear();
projectionsSegment.getProjections().addAll(Collections.singletonList(new ExpressionProjectionSegment(0, 0, "false")));
Assert.assertFalse("should not be shadow", simpleShadowDataSourceRouter.isShadowSQL());
}
}
......@@ -34,7 +34,7 @@ public final class ShadowRuleBuilder implements ShardingSphereRuleBuilder<Shadow
@Override
public int getOrder() {
return -5;
return 20;
}
@Override
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册