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

duanzhengqiang 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 86196a9  #11397 fix bug of wrong route result (#11690)
86196a9 is described below

commit 86196a92a314a0dc4e4a1acbebbd72221f4f3c0b
Author: LiaoWenxing <[email protected]>
AuthorDate: Tue Aug 10 13:57:22 2021 +0800

    #11397 fix bug of wrong route result (#11690)
---
 .../parser/sql/common/util/ExpressionBuilder.java  | 41 +++++++++++++++++-----
 .../sql/common/util/ExpressionBuilderTest.java     | 23 ++++++++++++
 .../resources/scenario/sharding/case/select.xml    |  6 ++++
 3 files changed, 62 insertions(+), 8 deletions(-)

diff --git 
a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionBuilder.java
 
b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionBuilder.java
index 9dba409..d446224 100644
--- 
a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionBuilder.java
+++ 
b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionBuilder.java
@@ -23,7 +23,8 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOp
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.OrPredicateSegment;
-
+import java.util.Collection;
+import java.util.LinkedList;
 import java.util.Optional;
 
 /**
@@ -50,13 +51,7 @@ public final class ExpressionBuilder {
                 
result.getAndPredicates().addAll(leftBuilder.extractAndPredicates().getAndPredicates());
                 
result.getAndPredicates().addAll(rightBuilder.extractAndPredicates().getAndPredicates());
             } else if (logicalOperator.isPresent() && LogicalOperator.AND == 
logicalOperator.get()) {
-                ExpressionBuilder leftBuilder = new 
ExpressionBuilder(((BinaryOperationExpression) expression).getLeft());
-                ExpressionBuilder rightBuilder = new 
ExpressionBuilder(((BinaryOperationExpression) expression).getRight());
-                for (AndPredicate eachLeft : 
leftBuilder.extractAndPredicates().getAndPredicates()) {
-                    for (AndPredicate eachRight : 
rightBuilder.extractAndPredicates().getAndPredicates()) {
-                        
result.getAndPredicates().add(createAndPredicate(eachLeft, eachRight));
-                    }
-                }
+                result.getAndPredicates().addAll(createAndPredicates());
             } else {
                 AndPredicate andPredicate = new AndPredicate();
                 andPredicate.getPredicates().add(expression);
@@ -76,4 +71,34 @@ public final class ExpressionBuilder {
         result.getPredicates().addAll(right.getPredicates());
         return result;
     }
+
+    private Collection<AndPredicate> createAndPredicates() {
+        Collection<AndPredicate> result = new LinkedList<>();
+        ExpressionBuilder leftBuilder = new 
ExpressionBuilder(((BinaryOperationExpression) expression).getLeft());
+        ExpressionBuilder rightBuilder = new 
ExpressionBuilder(((BinaryOperationExpression) expression).getRight());
+        ExpressionSegment leftExpression = ((BinaryOperationExpression) 
expression).getLeft();
+        if (leftExpression instanceof BinaryOperationExpression) {
+            String leftOp = ((BinaryOperationExpression) 
leftExpression).getOperator();
+            Optional<LogicalOperator> logicLeftOp = 
LogicalOperator.valueFrom(leftOp);
+            if (logicLeftOp.isPresent() && LogicalOperator.OR == 
logicLeftOp.get()) {
+                ExpressionBuilder beforeOrBuilder = new 
ExpressionBuilder(((BinaryOperationExpression) leftExpression).getLeft());
+                ExpressionBuilder afterOrBuilder = new 
ExpressionBuilder(((BinaryOperationExpression) leftExpression).getRight());
+                
result.addAll(beforeOrBuilder.extractAndPredicates().getAndPredicates());
+                result.addAll(createResultCollection(afterOrBuilder, 
rightBuilder));
+                return result;
+            }
+        }
+        result.addAll(createResultCollection(leftBuilder, rightBuilder));
+        return result;
+    }
+
+    private Collection<AndPredicate> createResultCollection(final 
ExpressionBuilder leftBuilder, final ExpressionBuilder rightBuilder) {
+        Collection<AndPredicate> result = new LinkedList<>();
+        for (AndPredicate eachLeft : 
leftBuilder.extractAndPredicates().getAndPredicates()) {
+            for (AndPredicate eachRight : 
rightBuilder.extractAndPredicates().getAndPredicates()) {
+                result.add(createAndPredicate(eachLeft, eachRight));
+            }
+        }
+        return result;
+    }
 }
diff --git 
a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionBuilderTest.java
 
b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionBuilderTest.java
index 1c2e6a0..2f7316b 100644
--- 
a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionBuilderTest.java
+++ 
b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionBuilderTest.java
@@ -82,4 +82,27 @@ public final class ExpressionBuilderTest {
         assertThat(andPredicate2.getPredicates().iterator().next(), 
is(expressionSegment2));
 
     }
+
+    @Test
+    public void assertExtractAndPredicatesOrAndCondition() {
+        ColumnSegment columnSegment1 = new ColumnSegment(28, 33, new 
IdentifierValue("status"));
+        ParameterMarkerExpressionSegment parameterMarkerExpressionSegment1 = 
new ParameterMarkerExpressionSegment(35, 35, 0);
+        ExpressionSegment expressionSegment1 = new 
BinaryOperationExpression(28, 39, columnSegment1, 
parameterMarkerExpressionSegment1, "=", "status=?");
+        ColumnSegment columnSegment2 = new ColumnSegment(40, 45, new 
IdentifierValue("status"));
+        ParameterMarkerExpressionSegment parameterMarkerExpressionSegment2 = 
new ParameterMarkerExpressionSegment(47, 47, 1);
+        ExpressionSegment expressionSegment2 = new 
BinaryOperationExpression(40, 47, columnSegment2, 
parameterMarkerExpressionSegment2, "=", "status=?");
+        BinaryOperationExpression expressionOr = new 
BinaryOperationExpression(28, 47, expressionSegment1, expressionSegment2, "OR", 
"status=? OR status=?");
+        ColumnSegment columnSegment3 = new ColumnSegment(53, 57, new 
IdentifierValue("count"));
+        ParameterMarkerExpressionSegment parameterMarkerExpressionSegment3 = 
new ParameterMarkerExpressionSegment(59, 59, 2);
+        ExpressionSegment expressionSegment3 = new 
BinaryOperationExpression(53, 59, columnSegment3, 
parameterMarkerExpressionSegment3, "=", "count=?");
+        BinaryOperationExpression expression = new 
BinaryOperationExpression(28, 59, expressionOr, expressionSegment3, "AND", 
"status=? OR status=? AND count=?");
+        ExpressionBuilder expressionBuilder = new 
ExpressionBuilder(expression);
+        OrPredicateSegment result = expressionBuilder.extractAndPredicates();
+        Iterator<AndPredicate> andPredicateIterator = 
result.getAndPredicates().iterator();
+        AndPredicate andPredicate1 = andPredicateIterator.next();
+        AndPredicate andPredicate2 = andPredicateIterator.next();
+        assertThat(result.getAndPredicates().size(), is(2));
+        assertThat(andPredicate1.getPredicates().size(), is(1));
+        assertThat(andPredicate2.getPredicates().size(), is(2));
+    }
 }
diff --git 
a/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/sharding/case/select.xml
 
b/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/sharding/case/select.xml
index ebde0f0..c59a811 100644
--- 
a/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/sharding/case/select.xml
+++ 
b/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/sharding/case/select.xml
@@ -486,4 +486,10 @@
         <input sql="SELECT * FROM t_user JOIN t_user_extend ON t_user.id = 
t_user_extend.user_id WHERE t_user_extend.user_id = ?" parameters="1"/>
         <output sql="SELECT * FROM t_user_1 JOIN t_user_extend_1 ON 
t_user_1.id = t_user_extend_1.user_id WHERE t_user_extend_1.user_id = ?" 
parameters="1"/>
     </rewrite-assertion>
+
+    <rewrite-assertion id="select_with_or_and_condition">
+        <input sql="SELECT * FROM t_account WHERE amount=? OR amount=? AND 
account_id=?" parameters="1, 2, 3"/>
+        <output sql="SELECT * FROM t_account_0 WHERE amount=? OR amount=? AND 
account_id=?" parameters="1, 2, 3"/>
+        <output sql="SELECT * FROM t_account_1 WHERE amount=? OR amount=? AND 
account_id=?" parameters="1, 2, 3"/>
+    </rewrite-assertion>
 </rewrite-assertions>

Reply via email to