You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2020/09/18 03:17:02 UTC

[shardingsphere] branch master updated: Fix shadow value in literal expression (#7486)

This is an automated email from the ASF dual-hosted git repository.

zhyee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 17d1375  Fix shadow value in literal expression (#7486)
17d1375 is described below

commit 17d137566799fe2f51a2173c97a7cdbf9e66ea6b
Author: Yanick.xia <me...@qq.com>
AuthorDate: Fri Sep 18 11:16:42 2020 +0800

    Fix shadow value in literal expression (#7486)
    
    * Fix shadow value in literal expression
    
    * Add more unit test
    
    Co-authored-by: yanick.xia <ya...@daocloud.io>
---
 .../application-shadow-databases.properties        |  3 +-
 .../impl/PreparedShadowDataSourceJudgeEngine.java  | 13 ++++---
 .../impl/PreparedShadowDataSourceRouterTest.java   | 43 ++++++++++++++++++++++
 .../statement/ShadowPreparedStatementTest.java     | 14 +++++++
 4 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/examples/shardingsphere-jdbc-example/other-feature-example/shadow-example/shadow-spring-boot-example/src/main/resources/application-shadow-databases.properties b/examples/shardingsphere-jdbc-example/other-feature-example/shadow-example/shadow-spring-boot-example/src/main/resources/application-shadow-databases.properties
index 8226d15..4360c90 100644
--- a/examples/shardingsphere-jdbc-example/other-feature-example/shadow-example/shadow-spring-boot-example/src/main/resources/application-shadow-databases.properties
+++ b/examples/shardingsphere-jdbc-example/other-feature-example/shadow-example/shadow-spring-boot-example/src/main/resources/application-shadow-databases.properties
@@ -27,4 +27,5 @@ spring.shardingsphere.datasource.ds.jdbc-url=jdbc:mysql://localhost:3306/demo_ds
 spring.shardingsphere.datasource.shadow_ds.jdbc-url=jdbc:mysql://localhost:3306/shadow_demo_ds?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
 
 spring.shardingsphere.rules.shadow.column=shadow
-spring.shardingsphere.rules.shadow.shadow-mappings.ds=shadow_ds
+spring.shardingsphere.rules.shadow.sourceDataSourceNames=ds
+spring.shardingsphere.rules.shadow.shadowDataSourceNames=shadow_ds
diff --git a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/main/java/org/apache/shardingsphere/shadow/route/engine/judge/impl/PreparedShadowDataSourceJudgeEngine.java b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/main/java/org/apache/shardingsphere/shadow/route/engine/judge/impl/PreparedShadowDataSourceJudgeEngine.java
index 44e01ae..11f7431 100644
--- a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/main/java/org/apache/shardingsphere/shadow/route/engine/judge/impl/PreparedShadowDataSourceJudgeEngine.java
+++ b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/main/java/org/apache/shardingsphere/shadow/route/engine/judge/impl/PreparedShadowDataSourceJudgeEngine.java
@@ -19,15 +19,16 @@ 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.ShadowDataSourceJudgeEngine;
 import org.apache.shardingsphere.shadow.route.engine.judge.util.ShadowValueJudgeUtil;
 import org.apache.shardingsphere.shadow.rule.ShadowRule;
-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;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
@@ -98,11 +99,13 @@ public final class PreparedShadowDataSourceJudgeEngine implements ShadowDataSour
             }
             if (column.getIdentifier().getValue().equals(shadowRule.getColumn())) {
                 Preconditions.checkArgument(each instanceof BinaryOperationExpression, "must be BinaryOperationExpression");
-                if (!(right instanceof ParameterMarkerExpressionSegment)) {
-                    continue;
+                if (right instanceof LiteralExpressionSegment) {
+                    return ShadowValueJudgeUtil.isShadowValue(((LiteralExpressionSegment) right).getLiterals());
+                }
+                if (right instanceof ParameterMarkerExpressionSegment) {
+                    int parameterMarkerIndex = ((ParameterMarkerExpressionSegment) right).getParameterMarkerIndex();
+                    return ShadowValueJudgeUtil.isShadowValue(parameters.get(parameterMarkerIndex));
                 }
-                int parameterMarkerIndex = ((ParameterMarkerExpressionSegment) right).getParameterMarkerIndex();
-                return ShadowValueJudgeUtil.isShadowValue(parameters.get(parameterMarkerIndex));
             }
         }
         return false;
diff --git a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/test/java/org/apache/shardingsphere/shadow/route/engine/judge/impl/PreparedShadowDataSourceRouterTest.java b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/test/java/org/apache/shardingsphere/shadow/route/engine/judge/impl/PreparedShadowDataSourceRouterTest.java
index 0271c3c..48663e8 100644
--- a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/test/java/org/apache/shardingsphere/shadow/route/engine/judge/impl/PreparedShadowDataSourceRouterTest.java
+++ b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/test/java/org/apache/shardingsphere/shadow/route/engine/judge/impl/PreparedShadowDataSourceRouterTest.java
@@ -21,10 +21,16 @@ import org.apache.shardingsphere.shadow.api.config.ShadowRuleConfiguration;
 import org.apache.shardingsphere.shadow.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.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.InsertColumnsSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLInsertStatement;
 import org.junit.Test;
@@ -53,4 +59,41 @@ public final class PreparedShadowDataSourceRouterTest {
         PreparedShadowDataSourceJudgeEngine preparedShadowDataSourceRouter = new PreparedShadowDataSourceJudgeEngine(shadowRule, insertStatementContext, Arrays.asList(1, "Tom", true));
         assertTrue("should be shadow", preparedShadowDataSourceRouter.isShadow());
     }
+    
+    @Test
+    public void isShadowSQLInLiteralExpression() {
+        SchemaMetaData schemaMetaData = mock(SchemaMetaData.class);
+        when(schemaMetaData.getAllColumnNames("tbl")).thenReturn(Arrays.asList("id", "name", "shadow"));
+        ShadowRuleConfiguration shadowRuleConfiguration = new ShadowRuleConfiguration("shadow", Collections.singletonList("ds"), Collections.singletonList("shadow_ds"));
+        ShadowRule shadowRule = new ShadowRule(shadowRuleConfiguration);
+        
+        PreparedShadowDataSourceJudgeEngine preparedShadowDataSourceRouter = new PreparedShadowDataSourceJudgeEngine(shadowRule, selectStatementContext(), Arrays.asList(1, "Tom", true));
+        assertTrue("should be shadow", preparedShadowDataSourceRouter.isShadow());
+    }
+    
+    private SelectStatementContext selectStatementContext() {
+        BinaryOperationExpression left = new BinaryOperationExpression();
+        left.setLeft(new ColumnSegment(0, 0, new IdentifierValue("id")));
+        left.setRight(new ParameterMarkerExpressionSegment(0, 0, 0));
+        left.setText("id=?");
+        left.setOperator("=");
+        
+        BinaryOperationExpression right = new BinaryOperationExpression();
+        right.setLeft(new ColumnSegment(0, 0, new IdentifierValue("shadow")));
+        right.setRight(new LiteralExpressionSegment(45, 48, "true"));
+        right.setText("shadow=true");
+        right.setOperator("=");
+        
+        BinaryOperationExpression binaryOperationExpression = new BinaryOperationExpression();
+        binaryOperationExpression.setLeft(left);
+        binaryOperationExpression.setRight(right);
+        binaryOperationExpression.setOperator("and");
+        binaryOperationExpression.setText("id=? and shadow=true");
+        
+        WhereSegment whereSegment = new WhereSegment(0, 0, binaryOperationExpression);
+        SelectStatement selectStatement = new SelectStatement();
+        selectStatement.setWhere(whereSegment);
+        
+        return new SelectStatementContext(selectStatement, null, null, null, null);
+    }
 }
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShadowPreparedStatementTest.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShadowPreparedStatementTest.java
index 3bb67ff..7ecbd8c 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShadowPreparedStatementTest.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShadowPreparedStatementTest.java
@@ -51,6 +51,8 @@ public final class ShadowPreparedStatementTest extends AbstractShardingSphereDat
     
     private static final String SHADOW_UPDATE_SQL = "UPDATE t_encrypt SET cipher_pwd = ? WHERE id = ? AND shadow = ?";
     
+    private static final String SHADOW_UPDATE_SQL_WITH_CONDITION = "UPDATE t_encrypt SET cipher_pwd = ? WHERE id = ? AND shadow = true";
+    
     @Test
     public void assertInsertWithExecute() throws SQLException {
         try (PreparedStatement statement = getShadowDataSource().getConnection().prepareStatement(INSERT_SQL)) {
@@ -121,6 +123,18 @@ public final class ShadowPreparedStatementTest extends AbstractShardingSphereDat
         assertResultSet(true, 99, 1, "cipher_pwd");
     }
     
+    @Test
+    public void assertShadowUpdateConditionWithExecuteUpdate() throws SQLException {
+        int result;
+        try (PreparedStatement statement = getShadowDataSource().getConnection().prepareStatement(SHADOW_UPDATE_SQL_WITH_CONDITION)) {
+            statement.setString(1, "cipher_pwd");
+            statement.setInt(2, 99);
+            result = statement.executeUpdate();
+        }
+        assertThat(result, is(1));
+        assertResultSet(true, 99, 1, "cipher_pwd");
+    }
+    
     private void assertResultSet(final boolean isShadow, final int resultSetCount, final Object cipherPwd) throws SQLException {
         Map<String, DataSource> dataMaps = getDATABASE_TYPE_MAP().get(DatabaseTypes.getActualDatabaseType("H2"));
         DataSource dataSource = isShadow ? dataMaps.get("jdbc_1") : dataMaps.get("jdbc_0");