tristaZero commented on a change in pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#discussion_r486936546



##########
File path: 
shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java
##########
@@ -81,50 +88,65 @@
     private Collection<EncryptCondition> createEncryptConditions(final 
SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<EncryptCondition> result = new LinkedList<>();
         Collection<Integer> stopIndexes = new HashSet<>();
-        for (PredicateSegment predicate : andPredicate.getPredicates()) {
+        for (ExpressionSegment predicate : andPredicate.getPredicates()) {
             if (stopIndexes.add(predicate.getStopIndex())) {
                 createEncryptCondition(sqlStatementContext, 
predicate).ifPresent(result::add);
             }
         }
         return result;
     }
     
-    private Optional<EncryptCondition> createEncryptCondition(final 
SQLStatementContext sqlStatementContext, final PredicateSegment 
predicateSegment) {
-        Optional<String> tableName = 
sqlStatementContext.getTablesContext().findTableName(predicateSegment.getColumn(),
 schemaMetaData);
-        return tableName.isPresent() && 
encryptRule.findEncryptor(tableName.get(), 
predicateSegment.getColumn().getIdentifier().getValue()).isPresent()
-                ? createEncryptCondition(predicateSegment, tableName.get()) : 
Optional.empty();
+    private Optional<EncryptCondition> createEncryptCondition(final 
SQLStatementContext sqlStatementContext, final ExpressionSegment expression) {
+        ColumnSegment column = 
ExpressionUtil.getColumnFromExpression(expression);

Review comment:
       return Optional<ColumnSegment>

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/MySQLVisitor.java
##########
@@ -255,123 +254,173 @@ public final ASTNode visitExpr(final ExprContext ctx) {
         if (null != ctx.booleanPrimary()) {
             return visit(ctx.booleanPrimary());
         }
+        if (null != ctx.LP_()) {
+            return visit(ctx.expr(0));
+        }
+        if (null != ctx.XOR()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator("XOR");
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
+        }
         if (null != ctx.logicalOperator()) {
-            return new PredicateBuildUtils(visit(ctx.expr(0)), 
visit(ctx.expr(1)), ctx.logicalOperator().getText()).mergePredicate();
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator(ctx.logicalOperator().getText());
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
         }
-        // TODO deal with XOR
-        return visit(ctx.expr().get(0));
+        NotExpression result = new NotExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setExpression((ExpressionSegment) visit(ctx.expr(0)));
+        return result;
     }
     
     @Override
     public final ASTNode visitBooleanPrimary(final BooleanPrimaryContext ctx) {
+        if (null != ctx.IS()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+            result.setRight(new 
LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 1, 
ctx.stop.getStopIndex(), new Interval(ctx.IS().getSymbol().getStopIndex() + 1,
+                    ctx.stop.getStopIndex())));
+            result.setOperator("IS");
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
+        }
         if (null != ctx.comparisonOperator() || null != ctx.SAFE_EQ_()) {
             return createCompareSegment(ctx);
         }
-        if (null != ctx.predicate()) {
-            return visit(ctx.predicate());
-        }
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        //TODO deal with IS NOT? (TRUE | FALSE | UNKNOWN | NULL)
-        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
-        return new CommonExpressionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), text);
+        return visit(ctx.predicate());
     }
     
     private ASTNode createCompareSegment(final BooleanPrimaryContext ctx) {
-        ASTNode leftValue = visit(ctx.booleanPrimary());
-        if (!(leftValue instanceof ColumnSegment)) {
-            return leftValue;
-        }
-        PredicateRightValue rightValue = (PredicateRightValue) 
createPredicateRightValue(ctx);
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (ColumnSegment) leftValue, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx) 
{
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        ASTNode rightValue = visit(ctx.predicate());
-        return createPredicateRightValue(ctx, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx, 
final ASTNode rightValue) {
-        if (rightValue instanceof ColumnSegment) {
-            return rightValue;
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+        if (null != ctx.predicate()) {
+            result.setRight((ExpressionSegment) visit(ctx.predicate()));
+        } else {
+            result.setRight((ExpressionSegment) visit(ctx.subquery()));
         }
-        return rightValue instanceof SubquerySegment ? new 
PredicateCompareRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                ctx.comparisonOperator().getText(), new 
SubqueryExpressionSegment((SubquerySegment) rightValue))
-                : new 
PredicateCompareRightValue(ctx.predicate().start.getStartIndex(), 
ctx.predicate().stop.getStopIndex(), ctx.comparisonOperator().getText(),
-                (ExpressionSegment) rightValue);
+        String operator = null != ctx.SAFE_EQ_() ? ctx.SAFE_EQ_().getText() : 
ctx.comparisonOperator().getText();
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        return result;
     }
     
     @Override
     public final ASTNode visitPredicate(final PredicateContext ctx) {
-        if (null != ctx.IN() && null == ctx.NOT()) {
+        if (null != ctx.IN()) {
             return createInSegment(ctx);
         }
-        if (null != ctx.BETWEEN() && null == ctx.NOT()) {
+        if (null != ctx.BETWEEN()) {
             return createBetweenSegment(ctx);
         }
-        if (1 == ctx.children.size()) {
-            return visit(ctx.bitExpr(0));
+        if (null != ctx.LIKE()) {
+            return createBinaryOperationExpressionFromLike(ctx);
         }
-        return visitRemainPredicate(ctx);
-    }
-    
-    private PredicateSegment createInSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        PredicateInRightValue predicateInRightValue = null != ctx.subquery() ? 
new PredicateInRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                getExpressionSegments(ctx))
-                : new 
PredicateInRightValue(ctx.LP_().getSymbol().getStartIndex(), 
ctx.RP_().getSymbol().getStopIndex(), getExpressionSegments(ctx));
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, predicateInRightValue);
+        if (null != ctx.REGEXP()) {
+            return createBinaryOperationExpressionFromRegexp(ctx);
+        }
+        return visit(ctx.bitExpr(0));
     }
     
-    private Collection<ExpressionSegment> getExpressionSegments(final 
PredicateContext ctx) {
-        Collection<ExpressionSegment> result = new LinkedList<>();
+    private InExpression createInSegment(final PredicateContext ctx) {
+        InExpression result = new InExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
         if (null != ctx.subquery()) {
-            SubqueryContext subquery = ctx.subquery();
-            result.add(new SubqueryExpressionSegment(new 
SubquerySegment(subquery.getStart().getStartIndex(), 
subquery.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
-            return result;
-        }
-        for (ExprContext each : ctx.expr()) {
-            result.add((ExpressionSegment) visit(each));
-        }
+            result.setRight(new SubqueryExpressionSegment(new 
SubquerySegment(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
+        } else {
+            ListExpression listExpression = new ListExpression();
+            
listExpression.setStartIndex(ctx.LP_().getSymbol().getStartIndex());
+            listExpression.setStopIndex(ctx.RP_().getSymbol().getStopIndex());
+            for (ExprContext each : ctx.expr()) {
+                listExpression.getItems().add((ExpressionSegment) visit(each));
+            }
+            result.setRight(listExpression);
+        }
+        Boolean operator = null != ctx.NOT() ? true : false;
+        result.setNot(operator);
         return result;
     }
     
-    private PredicateSegment createBetweenSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        ExpressionSegment between = (ExpressionSegment) visit(ctx.bitExpr(1));
-        ExpressionSegment and = (ExpressionSegment) visit(ctx.predicate());
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, new 
PredicateBetweenRightValue(between.getStartIndex(), and.getStopIndex(), 
between, and));
+    private BinaryOperationExpression 
createBinaryOperationExpressionFromLike(final PredicateContext ctx) {
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        String operator;
+        if (null != ctx.SOUNDS()) {
+            result.setRight((ExpressionSegment) visit(ctx.bitExpr(1)));
+            operator = "SOUNDS LIKE";
+        } else {
+            ListExpression listExpression = new ListExpression();
+            for (SimpleExprContext each : ctx.simpleExpr()) {
+                listExpression.getItems().add((ExpressionSegment) visit(each));
+            }
+            result.setRight(listExpression);
+            operator = null != ctx.NOT() ? "NOT LIKE" : "LIKE";
+        }
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        return result;
     }
     
-    private ASTNode visitRemainPredicate(final PredicateContext ctx) {
-        for (BitExprContext each : ctx.bitExpr()) {
-            visit(each);
-        }
-        for (ExprContext each : ctx.expr()) {
-            visit(each);
-        }
-        for (SimpleExprContext each : ctx.simpleExpr()) {
-            visit(each);
-        }
-        if (null != ctx.predicate()) {
-            visit(ctx.predicate());
-        }
+    private BinaryOperationExpression 
createBinaryOperationExpressionFromRegexp(final PredicateContext ctx) {
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        result.setRight((ExpressionSegment) visit(ctx.bitExpr(1)));

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/MySQLVisitor.java
##########
@@ -255,123 +254,173 @@ public final ASTNode visitExpr(final ExprContext ctx) {
         if (null != ctx.booleanPrimary()) {
             return visit(ctx.booleanPrimary());
         }
+        if (null != ctx.LP_()) {
+            return visit(ctx.expr(0));
+        }
+        if (null != ctx.XOR()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator("XOR");
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
+        }
         if (null != ctx.logicalOperator()) {
-            return new PredicateBuildUtils(visit(ctx.expr(0)), 
visit(ctx.expr(1)), ctx.logicalOperator().getText()).mergePredicate();
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator(ctx.logicalOperator().getText());
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
         }
-        // TODO deal with XOR
-        return visit(ctx.expr().get(0));
+        NotExpression result = new NotExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setExpression((ExpressionSegment) visit(ctx.expr(0)));
+        return result;
     }
     
     @Override
     public final ASTNode visitBooleanPrimary(final BooleanPrimaryContext ctx) {
+        if (null != ctx.IS()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+            result.setRight(new 
LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 1, 
ctx.stop.getStopIndex(), new Interval(ctx.IS().getSymbol().getStopIndex() + 1,
+                    ctx.stop.getStopIndex())));
+            result.setOperator("IS");
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
+        }
         if (null != ctx.comparisonOperator() || null != ctx.SAFE_EQ_()) {
             return createCompareSegment(ctx);
         }
-        if (null != ctx.predicate()) {
-            return visit(ctx.predicate());
-        }
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        //TODO deal with IS NOT? (TRUE | FALSE | UNKNOWN | NULL)
-        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
-        return new CommonExpressionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), text);
+        return visit(ctx.predicate());
     }
     
     private ASTNode createCompareSegment(final BooleanPrimaryContext ctx) {
-        ASTNode leftValue = visit(ctx.booleanPrimary());
-        if (!(leftValue instanceof ColumnSegment)) {
-            return leftValue;
-        }
-        PredicateRightValue rightValue = (PredicateRightValue) 
createPredicateRightValue(ctx);
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (ColumnSegment) leftValue, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx) 
{
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        ASTNode rightValue = visit(ctx.predicate());
-        return createPredicateRightValue(ctx, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx, 
final ASTNode rightValue) {
-        if (rightValue instanceof ColumnSegment) {
-            return rightValue;
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+        if (null != ctx.predicate()) {
+            result.setRight((ExpressionSegment) visit(ctx.predicate()));
+        } else {
+            result.setRight((ExpressionSegment) visit(ctx.subquery()));
         }
-        return rightValue instanceof SubquerySegment ? new 
PredicateCompareRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                ctx.comparisonOperator().getText(), new 
SubqueryExpressionSegment((SubquerySegment) rightValue))
-                : new 
PredicateCompareRightValue(ctx.predicate().start.getStartIndex(), 
ctx.predicate().stop.getStopIndex(), ctx.comparisonOperator().getText(),
-                (ExpressionSegment) rightValue);
+        String operator = null != ctx.SAFE_EQ_() ? ctx.SAFE_EQ_().getText() : 
ctx.comparisonOperator().getText();
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        return result;
     }
     
     @Override
     public final ASTNode visitPredicate(final PredicateContext ctx) {
-        if (null != ctx.IN() && null == ctx.NOT()) {
+        if (null != ctx.IN()) {
             return createInSegment(ctx);
         }
-        if (null != ctx.BETWEEN() && null == ctx.NOT()) {
+        if (null != ctx.BETWEEN()) {
             return createBetweenSegment(ctx);
         }
-        if (1 == ctx.children.size()) {
-            return visit(ctx.bitExpr(0));
+        if (null != ctx.LIKE()) {
+            return createBinaryOperationExpressionFromLike(ctx);
         }
-        return visitRemainPredicate(ctx);
-    }
-    
-    private PredicateSegment createInSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        PredicateInRightValue predicateInRightValue = null != ctx.subquery() ? 
new PredicateInRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                getExpressionSegments(ctx))
-                : new 
PredicateInRightValue(ctx.LP_().getSymbol().getStartIndex(), 
ctx.RP_().getSymbol().getStopIndex(), getExpressionSegments(ctx));
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, predicateInRightValue);
+        if (null != ctx.REGEXP()) {
+            return createBinaryOperationExpressionFromRegexp(ctx);
+        }
+        return visit(ctx.bitExpr(0));
     }
     
-    private Collection<ExpressionSegment> getExpressionSegments(final 
PredicateContext ctx) {
-        Collection<ExpressionSegment> result = new LinkedList<>();
+    private InExpression createInSegment(final PredicateContext ctx) {
+        InExpression result = new InExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
         if (null != ctx.subquery()) {
-            SubqueryContext subquery = ctx.subquery();
-            result.add(new SubqueryExpressionSegment(new 
SubquerySegment(subquery.getStart().getStartIndex(), 
subquery.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
-            return result;
-        }
-        for (ExprContext each : ctx.expr()) {
-            result.add((ExpressionSegment) visit(each));
-        }
+            result.setRight(new SubqueryExpressionSegment(new 
SubquerySegment(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
+        } else {
+            ListExpression listExpression = new ListExpression();
+            
listExpression.setStartIndex(ctx.LP_().getSymbol().getStartIndex());
+            listExpression.setStopIndex(ctx.RP_().getSymbol().getStopIndex());
+            for (ExprContext each : ctx.expr()) {
+                listExpression.getItems().add((ExpressionSegment) visit(each));
+            }
+            result.setRight(listExpression);
+        }
+        Boolean operator = null != ctx.NOT() ? true : false;
+        result.setNot(operator);
         return result;
     }
     
-    private PredicateSegment createBetweenSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        ExpressionSegment between = (ExpressionSegment) visit(ctx.bitExpr(1));
-        ExpressionSegment and = (ExpressionSegment) visit(ctx.predicate());
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, new 
PredicateBetweenRightValue(between.getStartIndex(), and.getStopIndex(), 
between, and));
+    private BinaryOperationExpression 
createBinaryOperationExpressionFromLike(final PredicateContext ctx) {
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        String operator;
+        if (null != ctx.SOUNDS()) {
+            result.setRight((ExpressionSegment) visit(ctx.bitExpr(1)));

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/OracleVisitor.java
##########
@@ -236,120 +234,141 @@ public final ASTNode visitExpr(final ExprContext ctx) {
         if (null != ctx.booleanPrimary()) {
             return visit(ctx.booleanPrimary());
         }
+        if (null != ctx.LP_()) {
+            return visit(ctx.expr(0));
+        }
         if (null != ctx.logicalOperator()) {
-            return new PredicateBuildUtils(visit(ctx.expr(0)), 
visit(ctx.expr(1)), ctx.logicalOperator().getText()).mergePredicate();
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator(ctx.logicalOperator().getText());
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
         }
-        // TODO deal with XOR
-        return visit(ctx.expr().get(0));
+        NotExpression result = new NotExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setExpression((ExpressionSegment) visit(ctx.expr(0)));
+        return result;
     }
     
     @Override
     public final ASTNode visitBooleanPrimary(final BooleanPrimaryContext ctx) {
+        if (null != ctx.IS()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+            result.setRight(new 
LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 1, 
ctx.stop.getStopIndex(), new Interval(ctx.IS().getSymbol().getStopIndex() + 1,
+                    ctx.stop.getStopIndex())));
+            result.setOperator("IS");
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
+        }
         if (null != ctx.comparisonOperator() || null != ctx.SAFE_EQ_()) {
             return createCompareSegment(ctx);
         }
-        if (null != ctx.predicate()) {
-            return visit(ctx.predicate());
-        }
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        //TODO deal with IS NOT? (TRUE | FALSE | UNKNOWN | NULL)
-        return new CommonExpressionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ctx.getText());
+        return visit(ctx.predicate());
     }
     
     private ASTNode createCompareSegment(final BooleanPrimaryContext ctx) {
-        ASTNode leftValue = visit(ctx.booleanPrimary());
-        if (!(leftValue instanceof ColumnSegment)) {
-            return leftValue;
-        }
-        PredicateRightValue rightValue = (PredicateRightValue) 
createPredicateRightValue(ctx);
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (ColumnSegment) leftValue, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx) 
{
-        if (null != ctx.subquery()) {
-            new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        ASTNode rightValue = visit(ctx.predicate());
-        return createPredicateRightValue(ctx, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx, 
final ASTNode rightValue) {
-        if (rightValue instanceof ColumnSegment) {
-            return rightValue;
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+        if (null != ctx.predicate()) {
+            result.setRight((ExpressionSegment) visit(ctx.predicate()));
+        } else {
+            result.setRight((ExpressionSegment) visit(ctx.subquery()));
         }
-        return rightValue instanceof SubquerySegment ? new 
PredicateCompareRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(), ctx.comparisonOperator().getText(),
-                new SubqueryExpressionSegment((SubquerySegment) rightValue))
-                : new 
PredicateCompareRightValue(ctx.predicate().start.getStartIndex(), 
ctx.predicate().stop.getStopIndex(), ctx.comparisonOperator().getText(), 
(ExpressionSegment) rightValue);
+        String operator = null != ctx.SAFE_EQ_() ? ctx.SAFE_EQ_().getText() : 
ctx.comparisonOperator().getText();
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        return result;
     }
     
     @Override
     public final ASTNode visitPredicate(final PredicateContext ctx) {
-        if (null != ctx.IN() && null == ctx.NOT()) {
+        if (null != ctx.IN()) {
             return createInSegment(ctx);
         }
-        if (null != ctx.BETWEEN() && null == ctx.NOT()) {
+        if (null != ctx.BETWEEN()) {
             return createBetweenSegment(ctx);
         }
-        if (1 == ctx.children.size()) {
-            return visit(ctx.bitExpr(0));
+        if (null != ctx.LIKE()) {
+            return createBinaryOperationExpressionFromLike(ctx);
         }
-        return visitRemainPredicate(ctx);
+        return visit(ctx.bitExpr(0));
     }
     
-    private PredicateSegment createInSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        PredicateInRightValue predicateInRightValue = null != ctx.subquery() ? 
new PredicateInRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                getExpressionSegments(ctx))
-                : new 
PredicateInRightValue(ctx.LP_().getSymbol().getStartIndex(), 
ctx.RP_().getSymbol().getStopIndex(), getExpressionSegments(ctx));
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, predicateInRightValue);
-    }
-    
-    private Collection<ExpressionSegment> getExpressionSegments(final 
PredicateContext ctx) {
-        Collection<ExpressionSegment> result = new LinkedList<>();
+    private InExpression createInSegment(final PredicateContext ctx) {
+        InExpression result = new InExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
         if (null != ctx.subquery()) {
-            SubqueryContext subquery = ctx.subquery();
-            result.add(new SubqueryExpressionSegment(new 
SubquerySegment(subquery.getStart().getStartIndex(), 
subquery.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
-            return result;
-        }
-        for (ExprContext each : ctx.expr()) {
-            result.add((ExpressionSegment) visit(each));
-        }
+            result.setRight(new SubqueryExpressionSegment(new 
SubquerySegment(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
+        } else {
+            ListExpression listExpression = new ListExpression();
+            
listExpression.setStartIndex(ctx.LP_().getSymbol().getStartIndex());
+            listExpression.setStopIndex(ctx.RP_().getSymbol().getStopIndex());
+            for (ExprContext each : ctx.expr()) {
+                listExpression.getItems().add((ExpressionSegment) visit(each));
+            }
+            result.setRight(listExpression);
+        }
+        Boolean operator = null != ctx.NOT() ? true : false;
+        result.setNot(operator);
         return result;
     }
     
-    private PredicateSegment createBetweenSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        ExpressionSegment between = (ExpressionSegment) visit(ctx.bitExpr(1));
-        ExpressionSegment and = (ExpressionSegment) visit(ctx.predicate());
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, new 
PredicateBetweenRightValue(between.getStartIndex(), and.getStopIndex(), 
between, and));
-    }
-    
-    private ASTNode visitRemainPredicate(final PredicateContext ctx) {
-        for (BitExprContext each : ctx.bitExpr()) {
-            visit(each);
-        }
-        for (ExprContext each : ctx.expr()) {
-            visit(each);
-        }
+    private BinaryOperationExpression 
createBinaryOperationExpressionFromLike(final PredicateContext ctx) {
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        ListExpression listExpression = new ListExpression();
         for (SimpleExprContext each : ctx.simpleExpr()) {
-            visit(each);
-        }
-        if (null != ctx.predicate()) {
-            visit(ctx.predicate());
+            listExpression.getItems().add((ExpressionSegment) visit(each));
         }
-        return new CommonExpressionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ctx.getText());
+        result.setRight(listExpression);
+        String operator;

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/PostgreSQLVisitor.java
##########
@@ -173,26 +176,33 @@ public ASTNode visitAExpr(final AExprContext ctx) {
         if (null != ctx.cExpr()) {
             return visit(ctx.cExpr());
         }
-        if (null != ctx.BETWEEN() && null == ctx.NOT()) {
+        if (null != ctx.BETWEEN()) {
             return createBetweenSegment(ctx);
         }
-        if (null != ctx.IN() && null == ctx.NOT()) {
+        if (null != ctx.IN()) {
             return createInSegment(ctx);
         }
         if (null != ctx.comparisonOperator()) {
-            ASTNode left = visit(ctx.aExpr(0));
-            if (left instanceof ColumnSegment) {
-                ColumnSegment columnSegment = (ColumnSegment) left;
-                SQLSegment right = (SQLSegment) visit(ctx.aExpr(1));
-                PredicateRightValue value = right instanceof ColumnSegment
-                        ? (PredicateRightValue) right : new 
PredicateCompareRightValue(right.getStartIndex(), right.getStopIndex(), 
ctx.comparisonOperator().getText(), (ExpressionSegment) right);
-                return new PredicateSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), columnSegment, value);
-            }
-            visit(ctx.aExpr(1));
-            return new 
LiteralExpressionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ctx.getText());
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.aExpr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.aExpr(1)));

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/PostgreSQLVisitor.java
##########
@@ -250,24 +260,76 @@ public ASTNode visitColumnref(final ColumnrefContext ctx) 
{
         return new ColumnSegment(ctx.colId().start.getStartIndex(), 
ctx.colId().stop.getStopIndex(), new IdentifierValue(ctx.colId().getText()));
     }
     
-    private PredicateSegment createInSegment(final AExprContext ctx) {
-        ColumnSegment column = (ColumnSegment) 
visit(ctx.aExpr(0).cExpr().columnref());
-        ASTNode predicateInRightValue = visit(ctx.inExpr());
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, (PredicateRightValue) 
predicateInRightValue);
+    private InExpression createInSegment(final AExprContext ctx) {
+        InExpression result = new InExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.aExpr(0)));
+        result.setRight(visitInExpression(ctx.inExpr()));
+        if (null != ctx.NOT()) {
+            result.setNot(true);
+        } else {
+            result.setNot(false);
+        }
+        return result;
     }
     
-    private PredicateSegment createBetweenSegment(final AExprContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.aExpr().get(0));
-        SQLSegment value = (SQLSegment) visit(ctx.bExpr());
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, new 
PredicateBetweenRightValue(value.getStartIndex(), value.getStopIndex(),
-                (ExpressionSegment) value, (ExpressionSegment) 
visit(ctx.aExpr(1))));
+    private ExpressionSegment visitInExpression(final InExprContext ctx) {
+        if (null != ctx.selectWithParens()) {
+            SelectStatement select = (SelectStatement) 
visit(ctx.selectWithParens());
+            SubquerySegment subquerySegment = new 
SubquerySegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), select);
+            SubqueryExpressionSegment result = new 
SubqueryExpressionSegment(subquerySegment);
+            return result;
+        }
+        return (ExpressionSegment) visit(ctx.exprList());
+    }
+    
+    @Override
+    public ASTNode visitExprList(final ExprListContext ctx) {
+        ListExpression result = new ListExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        if (null != ctx.exprList()) {
+            result.getItems().addAll(((ListExpression) 
visitExprList(ctx.exprList())).getItems());
+        }
+        result.getItems().add((ExpressionSegment) visit(ctx.aExpr()));
+        return result;
+    }
+    
+    private BetweenExpression createBetweenSegment(final AExprContext ctx) {
+        BetweenExpression result = new BetweenExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.aExpr(0)));
+        result.setBetweenExpr((ExpressionSegment) visit(ctx.bExpr()));
+        result.setAndExpr((ExpressionSegment) visit(ctx.aExpr(1)));
+        if (null != ctx.NOT()) {
+            result.setNot(true);
+        }
+        return result;
     }
     
     @Override
     public ASTNode visitBExpr(final BExprContext ctx) {
         if (null != ctx.cExpr()) {
             return visit(ctx.cExpr());
         }
+        if (null != ctx.TYPE_CAST_() || null != ctx.qualOp()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.bExpr(0)));
+            if (null != ctx.TYPE_CAST_()) {
+                result.setOperator(ctx.TYPE_CAST_().getText());
+                result.setRight(new 
CommonExpressionSegment(ctx.typeName().start.getStartIndex(), 
ctx.typeName().stop.getStopIndex(), ctx.typeName().getText()));
+            } else {

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -98,22 +107,45 @@
         return result;
     }
     
-    private Map<Column, Collection<RouteValue>> createRouteValueMap(final 
SQLStatementContext sqlStatementContext, final AndPredicate andPredicate, final 
List<Object> parameters) {
+    private Map<Column, Collection<RouteValue>> createRouteValueMap(final 
SQLStatementContext sqlStatementContext, final AndPredicate expressions, final 
List<Object> parameters) {
         Map<Column, Collection<RouteValue>> result = new HashMap<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<String> tableName = 
sqlStatementContext.getTablesContext().findTableName(each.getColumn(), 
schemaMetaData);
-            if (!tableName.isPresent() || 
!shardingRule.isShardingColumn(each.getColumn().getIdentifier().getValue(), 
tableName.get())) {
-                continue;
+    
+        for (ExpressionSegment each : expressions.getPredicates()) {
+            Optional<RouteValue> routeValue = Optional.empty();
+            Column column = null;
+            if (each instanceof BinaryOperationExpression && 
((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                ColumnSegment columnSegment = (ColumnSegment) 
((BinaryOperationExpression) each).getLeft();
+                Optional<String> tableName = 
sqlStatementContext.getTablesContext().findTableName(columnSegment, 
schemaMetaData);
+                if (tableName.isPresent() && 
shardingRule.isShardingColumn(columnSegment.getIdentifier().getValue(), 
tableName.get())) {
+                    column = new 
Column(columnSegment.getIdentifier().getValue(), tableName.get());
+                    routeValue = ConditionValueGeneratorFactory.generate(each, 
column, parameters);
+                }
             }
-            Column column = new 
Column(each.getColumn().getIdentifier().getValue(), tableName.get());
-            Optional<RouteValue> routeValue = 
ConditionValueGeneratorFactory.generate(each.getRightValue(), column, 
parameters);
-            if (!routeValue.isPresent()) {
-                continue;
+            if (each instanceof InExpression && ((InExpression) 
each).getLeft() instanceof ColumnSegment) {
+                ColumnSegment columnSegment = (ColumnSegment) ((InExpression) 
each).getLeft();
+                Optional<String> tableName = 
sqlStatementContext.getTablesContext().findTableName(columnSegment, 
schemaMetaData);
+                if (tableName.isPresent() && 
shardingRule.isShardingColumn(columnSegment.getIdentifier().getValue(), 
tableName.get())) {
+                    column = new 
Column(columnSegment.getIdentifier().getValue(), tableName.get());
+                    routeValue = ConditionValueGeneratorFactory.generate(each, 
column, parameters);
+                }
             }
-            if (!result.containsKey(column)) {
-                result.put(column, new LinkedList<>());
+            if (each instanceof BetweenExpression && ((BetweenExpression) 
each).getLeft() instanceof ColumnSegment) {
+                ColumnSegment columnSegment = (ColumnSegment) 
((BetweenExpression) each).getLeft();

Review comment:
       Functions are needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/MySQLVisitor.java
##########
@@ -255,123 +254,173 @@ public final ASTNode visitExpr(final ExprContext ctx) {
         if (null != ctx.booleanPrimary()) {
             return visit(ctx.booleanPrimary());
         }
+        if (null != ctx.LP_()) {
+            return visit(ctx.expr(0));
+        }
+        if (null != ctx.XOR()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java
##########
@@ -516,6 +506,13 @@ private ASTNode createProjection(final ProjectionContext 
ctx, final AliasSegment
             result.setAlias(alias);
             return result;
         }
+        if (projection instanceof BinaryOperationExpression) {
+            int startIndex = ((BinaryOperationExpression) 
projection).getStartIndex();
+            int stopIndex = null != alias ? alias.getStopIndex() : 
((BinaryOperationExpression) projection).getStopIndex();
+            ExpressionProjectionSegment result = new 
ExpressionProjectionSegment(startIndex, stopIndex, ((BinaryOperationExpression) 
projection).getText());

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/SQLServerVisitor.java
##########
@@ -244,121 +241,141 @@ public final ASTNode visitExpr(final ExprContext ctx) {
         if (null != ctx.booleanPrimary()) {
             return visit(ctx.booleanPrimary());
         }
+        if (null != ctx.LP_()) {
+            return visit(ctx.expr(0));
+        }
         if (null != ctx.logicalOperator()) {
-            return new PredicateBuildUtils(visit(ctx.expr(0)), 
visit(ctx.expr(1)), ctx.logicalOperator().getText()).mergePredicate();
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator(ctx.logicalOperator().getText());
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
         }
-        // TODO deal with XOR
-        return visit(ctx.expr().get(0));
+        NotExpression result = new NotExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setExpression((ExpressionSegment) visit(ctx.expr(0)));
+        return result;
     }
     
     @Override
     public final ASTNode visitBooleanPrimary(final BooleanPrimaryContext ctx) {
+        if (null != ctx.IS()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+            result.setRight(new 
LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 1, 
ctx.stop.getStopIndex(), new Interval(ctx.IS().getSymbol().getStopIndex() + 1,
+                    ctx.stop.getStopIndex())));
+            result.setOperator("IS");
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
+        }
         if (null != ctx.comparisonOperator() || null != ctx.SAFE_EQ_()) {
             return createCompareSegment(ctx);
         }
-        if (null != ctx.predicate()) {
-            return visit(ctx.predicate());
-        }
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        //TODO deal with IS NOT? (TRUE | FALSE | UNKNOWN | NULL)
-        return new CommonExpressionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ctx.getText());
+        return visit(ctx.predicate());
     }
     
     private ASTNode createCompareSegment(final BooleanPrimaryContext ctx) {
-        ASTNode leftValue = visit(ctx.booleanPrimary());
-        if (!(leftValue instanceof ColumnSegment)) {
-            return leftValue;
-        }
-        PredicateRightValue rightValue = (PredicateRightValue) 
createPredicateRightValue(ctx);
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (ColumnSegment) leftValue, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx) 
{
-        if (null != ctx.subquery()) {
-            new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        ASTNode rightValue = visit(ctx.predicate());
-        return createPredicateRightValue(ctx, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx, 
final ASTNode rightValue) {
-        if (rightValue instanceof ColumnSegment) {
-            return rightValue;
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+        if (null != ctx.predicate()) {
+            result.setRight((ExpressionSegment) visit(ctx.predicate()));
+        } else {
+            result.setRight((ExpressionSegment) visit(ctx.subquery()));
         }
-        return rightValue instanceof SubquerySegment ? new 
PredicateCompareRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(), ctx.comparisonOperator().getText(),
-                new SubqueryExpressionSegment((SubquerySegment) rightValue))
-                : new 
PredicateCompareRightValue(ctx.predicate().start.getStartIndex(), 
ctx.predicate().stop.getStopIndex(), ctx.comparisonOperator().getText(), 
(ExpressionSegment) rightValue);
+        String operator = null != ctx.SAFE_EQ_() ? ctx.SAFE_EQ_().getText() : 
ctx.comparisonOperator().getText();
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        return result;
     }
     
     @Override
     public final ASTNode visitPredicate(final PredicateContext ctx) {
-        if (null != ctx.IN() && null == ctx.NOT()) {
+        if (null != ctx.IN()) {
             return createInSegment(ctx);
         }
-        if (null != ctx.BETWEEN() && null == ctx.NOT()) {
+        if (null != ctx.BETWEEN()) {
             return createBetweenSegment(ctx);
         }
-        if (1 == ctx.children.size()) {
-            return visit(ctx.bitExpr(0));
+        if (null != ctx.LIKE()) {
+            return createBinaryOperationExpressionFromLike(ctx);
         }
-        return visitRemainPredicate(ctx);
-    }
-    
-    private PredicateSegment createInSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        PredicateInRightValue predicateInRightValue = null != ctx.subquery() ? 
new PredicateInRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                getExpressionSegments(ctx))
-                : new 
PredicateInRightValue(ctx.LP_().getSymbol().getStartIndex(), 
ctx.RP_().getSymbol().getStopIndex(), getExpressionSegments(ctx));
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, predicateInRightValue);
+        return visit(ctx.bitExpr(0));
     }
     
-    private Collection<ExpressionSegment> getExpressionSegments(final 
PredicateContext ctx) {
-        Collection<ExpressionSegment> result = new LinkedList<>();
-        if (null != ctx.subquery()) {
-            SubqueryContext subquery = ctx.subquery();
-            result.add(new SubqueryExpressionSegment(new 
SubquerySegment(subquery.getStart().getStartIndex(), 
subquery.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
-            return result;
-        }
-        for (ExprContext each : ctx.expr()) {
-            result.add((ExpressionSegment) visit(each));
+    private BinaryOperationExpression 
createBinaryOperationExpressionFromLike(final PredicateContext ctx) {
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        ListExpression listExpression = new ListExpression();
+        for (SimpleExprContext each : ctx.simpleExpr()) {
+            listExpression.getItems().add((ExpressionSegment) visit(each));
         }
+        result.setRight(listExpression);
+        String operator;
+        operator = null != ctx.NOT() ? "NOT LIKE" : "LIKE";
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
         return result;
     }
     
-    private PredicateSegment createBetweenSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        ExpressionSegment between = (ExpressionSegment) visit(ctx.bitExpr(1));
-        ExpressionSegment and = (ExpressionSegment) visit(ctx.predicate());
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, new 
PredicateBetweenRightValue(between.getStartIndex(), and.getStopIndex(), 
between, and));
+    private InExpression createInSegment(final PredicateContext ctx) {
+        InExpression result = new InExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        if (null != ctx.subquery()) {
+            result.setRight(new SubqueryExpressionSegment(new 
SubquerySegment(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
+        } else {
+            ListExpression listExpression = new ListExpression();
+            
listExpression.setStartIndex(ctx.LP_().getSymbol().getStartIndex());
+            listExpression.setStopIndex(ctx.RP_().getSymbol().getStopIndex());

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/MySQLVisitor.java
##########
@@ -255,123 +254,173 @@ public final ASTNode visitExpr(final ExprContext ctx) {
         if (null != ctx.booleanPrimary()) {
             return visit(ctx.booleanPrimary());
         }
+        if (null != ctx.LP_()) {
+            return visit(ctx.expr(0));
+        }
+        if (null != ctx.XOR()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator("XOR");
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
+        }
         if (null != ctx.logicalOperator()) {
-            return new PredicateBuildUtils(visit(ctx.expr(0)), 
visit(ctx.expr(1)), ctx.logicalOperator().getText()).mergePredicate();
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator(ctx.logicalOperator().getText());
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
         }
-        // TODO deal with XOR
-        return visit(ctx.expr().get(0));
+        NotExpression result = new NotExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setExpression((ExpressionSegment) visit(ctx.expr(0)));
+        return result;
     }
     
     @Override
     public final ASTNode visitBooleanPrimary(final BooleanPrimaryContext ctx) {
+        if (null != ctx.IS()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+            result.setRight(new 
LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 1, 
ctx.stop.getStopIndex(), new Interval(ctx.IS().getSymbol().getStopIndex() + 1,
+                    ctx.stop.getStopIndex())));
+            result.setOperator("IS");
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
+        }
         if (null != ctx.comparisonOperator() || null != ctx.SAFE_EQ_()) {
             return createCompareSegment(ctx);
         }
-        if (null != ctx.predicate()) {
-            return visit(ctx.predicate());
-        }
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        //TODO deal with IS NOT? (TRUE | FALSE | UNKNOWN | NULL)
-        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
-        return new CommonExpressionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), text);
+        return visit(ctx.predicate());
     }
     
     private ASTNode createCompareSegment(final BooleanPrimaryContext ctx) {
-        ASTNode leftValue = visit(ctx.booleanPrimary());
-        if (!(leftValue instanceof ColumnSegment)) {
-            return leftValue;
-        }
-        PredicateRightValue rightValue = (PredicateRightValue) 
createPredicateRightValue(ctx);
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (ColumnSegment) leftValue, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx) 
{
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        ASTNode rightValue = visit(ctx.predicate());
-        return createPredicateRightValue(ctx, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx, 
final ASTNode rightValue) {
-        if (rightValue instanceof ColumnSegment) {
-            return rightValue;
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+        if (null != ctx.predicate()) {
+            result.setRight((ExpressionSegment) visit(ctx.predicate()));
+        } else {
+            result.setRight((ExpressionSegment) visit(ctx.subquery()));
         }
-        return rightValue instanceof SubquerySegment ? new 
PredicateCompareRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                ctx.comparisonOperator().getText(), new 
SubqueryExpressionSegment((SubquerySegment) rightValue))
-                : new 
PredicateCompareRightValue(ctx.predicate().start.getStartIndex(), 
ctx.predicate().stop.getStopIndex(), ctx.comparisonOperator().getText(),
-                (ExpressionSegment) rightValue);
+        String operator = null != ctx.SAFE_EQ_() ? ctx.SAFE_EQ_().getText() : 
ctx.comparisonOperator().getText();
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        return result;
     }
     
     @Override
     public final ASTNode visitPredicate(final PredicateContext ctx) {
-        if (null != ctx.IN() && null == ctx.NOT()) {
+        if (null != ctx.IN()) {
             return createInSegment(ctx);
         }
-        if (null != ctx.BETWEEN() && null == ctx.NOT()) {
+        if (null != ctx.BETWEEN()) {
             return createBetweenSegment(ctx);
         }
-        if (1 == ctx.children.size()) {
-            return visit(ctx.bitExpr(0));
+        if (null != ctx.LIKE()) {
+            return createBinaryOperationExpressionFromLike(ctx);
         }
-        return visitRemainPredicate(ctx);
-    }
-    
-    private PredicateSegment createInSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        PredicateInRightValue predicateInRightValue = null != ctx.subquery() ? 
new PredicateInRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                getExpressionSegments(ctx))
-                : new 
PredicateInRightValue(ctx.LP_().getSymbol().getStartIndex(), 
ctx.RP_().getSymbol().getStopIndex(), getExpressionSegments(ctx));
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, predicateInRightValue);
+        if (null != ctx.REGEXP()) {
+            return createBinaryOperationExpressionFromRegexp(ctx);
+        }
+        return visit(ctx.bitExpr(0));
     }
     
-    private Collection<ExpressionSegment> getExpressionSegments(final 
PredicateContext ctx) {
-        Collection<ExpressionSegment> result = new LinkedList<>();
+    private InExpression createInSegment(final PredicateContext ctx) {
+        InExpression result = new InExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
         if (null != ctx.subquery()) {
-            SubqueryContext subquery = ctx.subquery();
-            result.add(new SubqueryExpressionSegment(new 
SubquerySegment(subquery.getStart().getStartIndex(), 
subquery.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
-            return result;
-        }
-        for (ExprContext each : ctx.expr()) {
-            result.add((ExpressionSegment) visit(each));
-        }
+            result.setRight(new SubqueryExpressionSegment(new 
SubquerySegment(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
+        } else {
+            ListExpression listExpression = new ListExpression();
+            
listExpression.setStartIndex(ctx.LP_().getSymbol().getStartIndex());
+            listExpression.setStopIndex(ctx.RP_().getSymbol().getStopIndex());
+            for (ExprContext each : ctx.expr()) {
+                listExpression.getItems().add((ExpressionSegment) visit(each));
+            }
+            result.setRight(listExpression);
+        }
+        Boolean operator = null != ctx.NOT() ? true : false;
+        result.setNot(operator);
         return result;
     }
     
-    private PredicateSegment createBetweenSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        ExpressionSegment between = (ExpressionSegment) visit(ctx.bitExpr(1));
-        ExpressionSegment and = (ExpressionSegment) visit(ctx.predicate());
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, new 
PredicateBetweenRightValue(between.getStartIndex(), and.getStopIndex(), 
between, and));
+    private BinaryOperationExpression 
createBinaryOperationExpressionFromLike(final PredicateContext ctx) {
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        String operator;
+        if (null != ctx.SOUNDS()) {
+            result.setRight((ExpressionSegment) visit(ctx.bitExpr(1)));
+            operator = "SOUNDS LIKE";
+        } else {
+            ListExpression listExpression = new ListExpression();
+            for (SimpleExprContext each : ctx.simpleExpr()) {
+                listExpression.getItems().add((ExpressionSegment) visit(each));
+            }
+            result.setRight(listExpression);
+            operator = null != ctx.NOT() ? "NOT LIKE" : "LIKE";
+        }
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        return result;
     }
     
-    private ASTNode visitRemainPredicate(final PredicateContext ctx) {
-        for (BitExprContext each : ctx.bitExpr()) {
-            visit(each);
-        }
-        for (ExprContext each : ctx.expr()) {
-            visit(each);
-        }
-        for (SimpleExprContext each : ctx.simpleExpr()) {
-            visit(each);
-        }
-        if (null != ctx.predicate()) {
-            visit(ctx.predicate());
-        }
+    private BinaryOperationExpression 
createBinaryOperationExpressionFromRegexp(final PredicateContext ctx) {
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        result.setRight((ExpressionSegment) visit(ctx.bitExpr(1)));
+        String operator = null != ctx.NOT() ? "NOT REGEXP" : "REGEXP";
+        result.setOperator(operator);
         String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
-        return new CommonExpressionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), text);
+        result.setText(text);
+        return result;
+    }
+    
+    private BetweenExpression createBetweenSegment(final PredicateContext ctx) 
{
+        BetweenExpression result = new BetweenExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/OracleVisitor.java
##########
@@ -236,120 +234,141 @@ public final ASTNode visitExpr(final ExprContext ctx) {
         if (null != ctx.booleanPrimary()) {
             return visit(ctx.booleanPrimary());
         }
+        if (null != ctx.LP_()) {
+            return visit(ctx.expr(0));
+        }
         if (null != ctx.logicalOperator()) {
-            return new PredicateBuildUtils(visit(ctx.expr(0)), 
visit(ctx.expr(1)), ctx.logicalOperator().getText()).mergePredicate();
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator(ctx.logicalOperator().getText());
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
         }
-        // TODO deal with XOR
-        return visit(ctx.expr().get(0));
+        NotExpression result = new NotExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setExpression((ExpressionSegment) visit(ctx.expr(0)));
+        return result;
     }
     
     @Override
     public final ASTNode visitBooleanPrimary(final BooleanPrimaryContext ctx) {
+        if (null != ctx.IS()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+            result.setRight(new 
LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 1, 
ctx.stop.getStopIndex(), new Interval(ctx.IS().getSymbol().getStopIndex() + 1,

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sql92/src/main/java/org/apache/shardingsphere/sql/parser/sql92/visitor/SQL92Visitor.java
##########
@@ -229,123 +227,141 @@ public final ASTNode visitExpr(final ExprContext ctx) {
         if (null != ctx.booleanPrimary()) {
             return visit(ctx.booleanPrimary());
         }
+        if (null != ctx.LP_()) {
+            return visit(ctx.expr(0));
+        }
         if (null != ctx.logicalOperator()) {
-            return new PredicateBuildUtils(visit(ctx.expr(0)), 
visit(ctx.expr(1)), ctx.logicalOperator().getText()).mergePredicate();
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator(ctx.logicalOperator().getText());
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
         }
-        // TODO deal with XOR
-        return visit(ctx.expr().get(0));
+        NotExpression result = new NotExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setExpression((ExpressionSegment) visit(ctx.expr(0)));
+        return result;
     }
     
     @Override
     public final ASTNode visitBooleanPrimary(final BooleanPrimaryContext ctx) {
+        if (null != ctx.IS()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+            result.setRight(new 
LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 1, 
ctx.stop.getStopIndex(), new Interval(ctx.IS().getSymbol().getStopIndex() + 1,
+                    ctx.stop.getStopIndex())));
+            result.setOperator("IS");
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
+        }
         if (null != ctx.comparisonOperator() || null != ctx.SAFE_EQ_()) {
             return createCompareSegment(ctx);
         }
-        if (null != ctx.predicate()) {
-            return visit(ctx.predicate());
-        }
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        //TODO deal with IS NOT? (TRUE | FALSE | UNKNOWN | NULL)
-        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
-        return new CommonExpressionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), text);
+        return visit(ctx.predicate());
     }
     
     private ASTNode createCompareSegment(final BooleanPrimaryContext ctx) {
-        ASTNode leftValue = visit(ctx.booleanPrimary());
-        if (!(leftValue instanceof ColumnSegment)) {
-            return leftValue;
-        }
-        PredicateRightValue rightValue = (PredicateRightValue) 
createPredicateRightValue(ctx);
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (ColumnSegment) leftValue, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx) 
{
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        ASTNode rightValue = visit(ctx.predicate());
-        return createPredicateRightValue(ctx, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx, 
final ASTNode rightValue) {
-        if (rightValue instanceof ColumnSegment) {
-            return rightValue;
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        if (null != ctx.predicate()) {
+            result.setRight((ExpressionSegment) visit(ctx.predicate()));
+        } else {
+            result.setRight((ExpressionSegment) visit(ctx.subquery()));
         }
-        return rightValue instanceof SubquerySegment ? new 
PredicateCompareRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                ctx.comparisonOperator().getText(), new 
SubqueryExpressionSegment((SubquerySegment) rightValue))
-                : new 
PredicateCompareRightValue(ctx.predicate().start.getStartIndex(), 
ctx.predicate().stop.getStopIndex(), ctx.comparisonOperator().getText(),
-                (ExpressionSegment) rightValue);
+        String operator = null != ctx.SAFE_EQ_() ? ctx.SAFE_EQ_().getText() : 
ctx.comparisonOperator().getText();
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        return result;
     }
     
     @Override
     public final ASTNode visitPredicate(final PredicateContext ctx) {
-        if (null != ctx.IN() && null == ctx.NOT()) {
+        if (null != ctx.IN()) {
             return createInSegment(ctx);
         }
-        if (null != ctx.BETWEEN() && null == ctx.NOT()) {
+        if (null != ctx.BETWEEN()) {
             return createBetweenSegment(ctx);
         }
-        if (1 == ctx.children.size()) {
-            return visit(ctx.bitExpr(0));
+        if (null != ctx.LIKE()) {
+            return createBinaryOperationExpressionFromLike(ctx);
         }
-        return visitRemainPredicate(ctx);
-    }
-    
-    private PredicateSegment createInSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        PredicateInRightValue predicateInRightValue = null != ctx.subquery() ? 
new PredicateInRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                getExpressionSegments(ctx))
-                : new 
PredicateInRightValue(ctx.LP_().getSymbol().getStartIndex(), 
ctx.RP_().getSymbol().getStopIndex(), getExpressionSegments(ctx));
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, predicateInRightValue);
+        return visit(ctx.bitExpr(0));
     }
     
-    private Collection<ExpressionSegment> getExpressionSegments(final 
PredicateContext ctx) {
-        Collection<ExpressionSegment> result = new LinkedList<>();
-        if (null != ctx.subquery()) {
-            SubqueryContext subquery = ctx.subquery();
-            result.add(new SubqueryExpressionSegment(new 
SubquerySegment(subquery.getStart().getStartIndex(), 
subquery.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
-            return result;
-        }
-        for (ExprContext each : ctx.expr()) {
-            result.add((ExpressionSegment) visit(each));
+    private BinaryOperationExpression 
createBinaryOperationExpressionFromLike(final PredicateContext ctx) {
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        ListExpression listExpression = new ListExpression();
+        for (SimpleExprContext each : ctx.simpleExpr()) {
+            listExpression.getItems().add((ExpressionSegment) visit(each));
         }
+        result.setRight(listExpression);
+        String operator;
+        operator = null != ctx.NOT() ? "NOT LIKE" : "LIKE";
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
         return result;
     }
     
-    private PredicateSegment createBetweenSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        ExpressionSegment between = (ExpressionSegment) visit(ctx.bitExpr(1));
-        ExpressionSegment and = (ExpressionSegment) visit(ctx.predicate());
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, new 
PredicateBetweenRightValue(between.getStartIndex(), and.getStopIndex(), 
between, and));
+    private InExpression createInSegment(final PredicateContext ctx) {
+        InExpression result = new InExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        if (null != ctx.subquery()) {
+            result.setRight(new SubqueryExpressionSegment(new 
SubquerySegment(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
+        } else {
+            ListExpression listExpression = new ListExpression();
+            
listExpression.setStartIndex(ctx.LP_().getSymbol().getStartIndex());
+            listExpression.setStopIndex(ctx.RP_().getSymbol().getStopIndex());
+            for (ExprContext each : ctx.expr()) {

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/main/java/org/apache/shardingsphere/shadow/route/engine/judge/impl/PreparedShadowDataSourceJudgeEngine.java
##########
@@ -61,27 +63,46 @@ public boolean isShadow() {
             }
             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;
-                }
+        if (!(sqlStatementContext instanceof WhereAvailable)) {
+            return false;
+        }
+        Optional<WhereSegment> whereSegment = ((WhereAvailable) 
sqlStatementContext).getWhere();
+        if (!whereSegment.isPresent()) {
+            return false;
+        }
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = whereSegment.get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().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();
+    private boolean judgePredicateSegments(final Collection<ExpressionSegment> 
predicates) {
+        for (ExpressionSegment each : predicates) {
+            if (!(each instanceof BinaryOperationExpression)) {
+                continue;
+            }
+            BinaryOperationExpression expression = (BinaryOperationExpression) 
each;
+            ColumnSegment column = null;
+            ExpressionSegment right = null;
+            if (expression.getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) 
each).getLeft();
+                right = ((BinaryOperationExpression) each).getRight();
+            }
+            if (null == column) {
+                continue;
+            }

Review comment:
       Refactoring

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/java/org/apache/shardingsphere/sql/parser/postgresql/visitor/impl/PostgreSQLDMLVisitor.java
##########
@@ -459,101 +451,87 @@ public ASTNode visitTargetEl(final TargetElContext ctx) {
         return result;
     }
     
-    private ColumnProjectionSegment generateColumnProjection(final 
ColumnrefContext ctx) {
-        if (null != ctx.indirection()) {
-            PostgreSQLStatementParser.AttrNameContext attrName = 
ctx.indirection().indirectionEl().attrName();
-            ColumnSegment columnSegment = new 
ColumnSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), new 
IdentifierValue(attrName.getText()));
-            OwnerSegment owner = new 
OwnerSegment(ctx.colId().start.getStartIndex(), 
ctx.colId().stop.getStopIndex(), new IdentifierValue(ctx.colId().getText()));
-            columnSegment.setOwner(owner);
-            return new ColumnProjectionSegment(columnSegment);
-        }
-        ColumnSegment columnSegment = new 
ColumnSegment(ctx.colId().start.getStartIndex(), 
ctx.colId().stop.getStopIndex(), new IdentifierValue(ctx.colId().getText()));
-        return new ColumnProjectionSegment(columnSegment);
-    }
-    
     @Override
     public ASTNode visitFromClause(final FromClauseContext ctx) {
         return visit(ctx.fromList());
     }
     
     @Override
-    public ASTNode visitFromList(final 
PostgreSQLStatementParser.FromListContext ctx) {
-        CollectionValue<TableReferenceSegment> result = new 
CollectionValue<>();
+    public ASTNode visitFromList(final FromListContext ctx) {
         if (null != ctx.fromList()) {
-            result.getValue().addAll(((CollectionValue<TableReferenceSegment>) 
visit(ctx.fromList())).getValue());
+            JoinTableSegment result = new JoinTableSegment();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((TableSegment) visit(ctx.fromList()));
+            result.setRight((TableSegment) visit(ctx.tableReference()));
+            return result;
         }
-        result.getValue().add((TableReferenceSegment) 
visit(ctx.tableReference()));
+        TableSegment result = (TableSegment) visit(ctx.tableReference());
         return result;
     }
     
     @Override
     public ASTNode visitTableReference(final TableReferenceContext ctx) {
-        if (null != ctx.tableReference()) {
-            TableReferenceSegment result = (TableReferenceSegment) 
visit(ctx.tableReference());
-            if (null != ctx.joinedTable()) {
-                result.getJoinedTables().add((JoinedTableSegment) 
visit(ctx.joinedTable()));
-            }
-            return result;
-        }
         if (null != ctx.relationExpr()) {
-            TableReferenceSegment result = new TableReferenceSegment();
-            SimpleTableSegment table = 
generateTableFromRelationExpr(ctx.relationExpr());
+            SimpleTableSegment result = 
generateTableFromRelationExpr(ctx.relationExpr());
             if (null != ctx.aliasClause()) {
-                table.setAlias((AliasSegment) visit(ctx.aliasClause()));
+                result.setAlias((AliasSegment) visit(ctx.aliasClause()));
             }
-            TableFactorSegment tableFactorSegment = new TableFactorSegment();
-            tableFactorSegment.setTable(table);
-            result.setTableFactor(tableFactorSegment);
             return result;
         }
         if (null != ctx.selectWithParens()) {
-            TableReferenceSegment result = new TableReferenceSegment();
             SelectStatement select = (SelectStatement) 
visit(ctx.selectWithParens());
             SubquerySegment subquery = new 
SubquerySegment(ctx.selectWithParens().start.getStartIndex(), 
ctx.selectWithParens().stop.getStopIndex(), select);
             AliasSegment alias = null != ctx.aliasClause() ? (AliasSegment) 
visit(ctx.aliasClause()) : null;
-            SubqueryTableSegment subqueryTable = new 
SubqueryTableSegment(subquery);
-            subqueryTable.setAlias(alias);
-            TableFactorSegment tableFactor = new TableFactorSegment();
-            tableFactor.setTable(subqueryTable);
-            result.setTableFactor(tableFactor);
+            SubqueryTableSegment result = new SubqueryTableSegment(subquery);
+            result.setAlias(alias);
+            return result;
+        }
+        if (null != ctx.tableReference()) {
+            JoinTableSegment result = new JoinTableSegment();
+            int startIndex = null != ctx.LP_() ? 
ctx.LP_().getSymbol().getStartIndex() : 
ctx.tableReference().start.getStartIndex();
+            int stopIndex = 0;
+            AliasSegment alias = null;
+            if (null != ctx.aliasClause()) {
+                alias = (AliasSegment) visit(ctx.aliasClause());
+                startIndex = null != ctx.RP_() ? 
ctx.RP_().getSymbol().getStopIndex() : ctx.joinedTable().stop.getStopIndex();
+            } else {

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java
##########
@@ -65,8 +67,13 @@
         if (!whereSegment.isPresent()) {
             return Collections.emptyList();
         }
+    

Review comment:
       Remove

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngine.java
##########
@@ -51,27 +50,39 @@
     /**
      * Create pagination context.
      * 
-     * @param andPredicates and predicates
+     * @param where where condition
      * @param projectionsContext projections context
      * @param parameters SQL parameters
      * @return pagination context
      */
-    public PaginationContext createPaginationContext(final 
Collection<AndPredicate> andPredicates, final ProjectionsContext 
projectionsContext, final List<Object> parameters) {
+    public PaginationContext createPaginationContext(final ExpressionSegment 
where, final ProjectionsContext projectionsContext, final List<Object> 
parameters) {
         Optional<String> rowNumberAlias = isRowNumberAlias(projectionsContext);
         if (!rowNumberAlias.isPresent()) {
             return new PaginationContext(null, null, parameters);
         }
-        Collection<PredicateSegment> rowNumberPredicates = 
getRowNumberPredicates(andPredicates, rowNumberAlias.get());
+        Collection<BinaryOperationExpression> rowNumberPredicates = 
getRowNumberPredicates(where, rowNumberAlias.get());
         return rowNumberPredicates.isEmpty() ? new PaginationContext(null, 
null, parameters) : createPaginationWithRowNumber(rowNumberPredicates, 
parameters);
     }
     
-    private Collection<PredicateSegment> getRowNumberPredicates(final 
Collection<AndPredicate> andPredicates, final String rowNumberAlias) {
-        Collection<PredicateSegment> result = new LinkedList<>();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                if (isRowNumberColumn(predicate, rowNumberAlias) && 
isCompareCondition(predicate)) {
-                    result.add(predicate);
-                }
+    private Collection<BinaryOperationExpression> getRowNumberPredicates(final 
ExpressionSegment where, final String rowNumberAlias) {
+        List<BinaryOperationExpression> result = new LinkedList<>();
+        if (!(where instanceof BinaryOperationExpression)) {
+            return result;
+        }
+        String operator = ((BinaryOperationExpression) where).getOperator();
+        if (((BinaryOperationExpression) where).getLeft() instanceof 
ColumnSegment && isRowNumberColumn((ColumnSegment) ((BinaryOperationExpression) 
where).getLeft(), rowNumberAlias)
+                && isCompareCondition(operator)) {
+            result.add((BinaryOperationExpression) where);
+            return result;
+        }
+        if ("and".equalsIgnoreCase(operator) || 
"&&".equalsIgnoreCase(operator) || "||".equalsIgnoreCase(operator) || 
"or".equalsIgnoreCase(operator)) {
+            Collection<BinaryOperationExpression> left = 
getRowNumberPredicates(((BinaryOperationExpression) where).getLeft(), 
rowNumberAlias);

Review comment:
       Refactoring

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionUtil.java
##########
@@ -0,0 +1,45 @@
+/*
+ * 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.sql.parser.sql.common.util;
+
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenExpression;
+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.InExpression;
+
+public final class ExpressionUtil {
+    
+    /**
+     * Get left value if left value of expression is ColumnSegment.

Review comment:
       Consider merging this one with `ExpressionBuildUtil.java`

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/TopPaginationContextEngineTest.java
##########
@@ -76,25 +76,23 @@ public void 
assertCreatePaginationContextWhenRowNumberPredicatePresentAndOperato
     public void assertCreatePaginationContextWhenPredicateInRightValue() {
         String name = "rowNumberAlias";
         ColumnSegment columnSegment = new ColumnSegment(0, 10, new 
IdentifierValue(name));
-        PredicateSegment predicateSegment = new PredicateSegment(0, 10, 
columnSegment, new PredicateInRightValue(0, 10, Collections.emptyList()));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(predicateSegment);
-        Collection<AndPredicate> andPredicates = 
Collections.singleton(andPredicate);
-        PaginationContext paginationContext = 
topPaginationContextEngine.createPaginationContext(new TopProjectionSegment(0, 
10, null, name), andPredicates, Collections.emptyList());
+        InExpression inExpression = new InExpression();
+        inExpression.setLeft(new ColumnSegment(0, 10, new 
IdentifierValue(name)));
+        inExpression.setRight(new ListExpression());
+        PaginationContext paginationContext = 
topPaginationContextEngine.createPaginationContext(new TopProjectionSegment(0, 
10, null, name), inExpression, Collections.emptyList());
         assertFalse(paginationContext.getOffsetSegment().isPresent());
         assertFalse(paginationContext.getRowCountSegment().isPresent());
     }
     
     @Test
     public void 
assertCreatePaginationContextWhenParameterMarkerRowNumberValueSegment() {
         String name = "rowNumberAlias";
-        ColumnSegment columnSegment = new ColumnSegment(0, 10, new 
IdentifierValue(name));
-        PredicateCompareRightValue predicateCompareRightValue = new 
PredicateCompareRightValue(0, 10, ">", new ParameterMarkerExpressionSegment(0, 
10, 0));
-        PredicateSegment predicateSegment = new PredicateSegment(0, 10, 
columnSegment, predicateCompareRightValue);
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(predicateSegment);
-        Collection<AndPredicate> andPredicates = 
Collections.singleton(andPredicate);
-        PaginationContext paginationContext = 
topPaginationContextEngine.createPaginationContext(new TopProjectionSegment(0, 
10, null, name), andPredicates, Collections.singletonList(1));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(">");
+        expression.setRight(new ParameterMarkerExpressionSegment(0, 10, 0));
+        expression.setLeft(new ColumnSegment(0, 10, new 
IdentifierValue(name)));
+        

Review comment:
       Remove.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionBuildUtil.java
##########
@@ -0,0 +1,76 @@
+/*
+ * 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.sql.parser.sql.common.util;
+
+import lombok.RequiredArgsConstructor;
+import 
org.apache.shardingsphere.sql.parser.sql.common.constant.LogicalOperator;
+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.predicate.AndPredicate;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.OrPredicateSegment;
+
+import java.util.Optional;
+
+@RequiredArgsConstructor
+public final class ExpressionBuildUtil {
+    
+    private final ExpressionSegment expression;
+    
+    /**
+     * Extract andPredicates.
+     *
+     * @return OrPredicateSegment.
+     */
+    public OrPredicateSegment extractAndPredicates() {
+        OrPredicateSegment orPredicate = new OrPredicateSegment();
+        if (expression instanceof BinaryOperationExpression) {
+            String operator = ((BinaryOperationExpression) 
expression).getOperator();
+            Optional<LogicalOperator> logicalOperator = 
LogicalOperator.valueFrom(operator);
+            if (logicalOperator.isPresent() && LogicalOperator.OR == 
logicalOperator.get()) {
+                ExpressionBuildUtil leftUtil = new 
ExpressionBuildUtil(((BinaryOperationExpression) expression).getLeft());
+                ExpressionBuildUtil rightUtil = new 
ExpressionBuildUtil(((BinaryOperationExpression) expression).getRight());
+                
orPredicate.getAndPredicates().addAll(leftUtil.extractAndPredicates().getAndPredicates());
+                
orPredicate.getAndPredicates().addAll(rightUtil.extractAndPredicates().getAndPredicates());
+            } else if (logicalOperator.isPresent() && LogicalOperator.AND == 
logicalOperator.get()) {
+                ExpressionBuildUtil leftUtil = new 
ExpressionBuildUtil(((BinaryOperationExpression) expression).getLeft());
+                ExpressionBuildUtil rightUtil = new 
ExpressionBuildUtil(((BinaryOperationExpression) expression).getRight());
+                for (AndPredicate eachLeft : 
leftUtil.extractAndPredicates().getAndPredicates()) {

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/OracleVisitor.java
##########
@@ -236,120 +234,141 @@ public final ASTNode visitExpr(final ExprContext ctx) {
         if (null != ctx.booleanPrimary()) {
             return visit(ctx.booleanPrimary());
         }
+        if (null != ctx.LP_()) {
+            return visit(ctx.expr(0));
+        }
         if (null != ctx.logicalOperator()) {
-            return new PredicateBuildUtils(visit(ctx.expr(0)), 
visit(ctx.expr(1)), ctx.logicalOperator().getText()).mergePredicate();
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));

Review comment:
       A function is needed here.

##########
File path: 
shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/impl/ShardingUpdateStatementValidator.java
##########
@@ -95,27 +93,35 @@ public void postValidate(final SQLStatement sqlStatement, 
final RouteResult rout
     }
     
     private Optional<Object> getShardingValue(final WhereSegment whereSegment, 
final List<Object> parameters, final String shardingColumn) {
-        for (AndPredicate each : whereSegment.getAndPredicates()) {
-            return getShardingValue(each, parameters, shardingColumn);
+        if (null != whereSegment) {
+            return getShardingValue(whereSegment.getExpr(), parameters, 
shardingColumn);
         }
         return Optional.empty();
     }
     
-    private Optional<Object> getShardingValue(final AndPredicate andPredicate, 
final List<Object> parameters, final String shardingColumn) {
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            if 
(!shardingColumn.equalsIgnoreCase(each.getColumn().getIdentifier().getValue())) 
{
-                continue;
+    private Optional<Object> getShardingValue(final ExpressionSegment 
expression, final List<Object> parameters, final String shardingColumn) {
+        if (expression instanceof InExpression && ((InExpression) 
expression).getLeft() instanceof ColumnSegment) {
+            ColumnSegment column = (ColumnSegment) ((InExpression) 
expression).getLeft();
+            if 
(!shardingColumn.equalsIgnoreCase(column.getIdentifier().getValue())) {
+                return getPredicateInShardingValue(((InExpression) 
expression).getRight(), parameters);
             }
-            PredicateRightValue rightValue = each.getRightValue();
-            if (rightValue instanceof PredicateCompareRightValue) {
-                ExpressionSegment segment = ((PredicateCompareRightValue) 
rightValue).getExpression();
-                return getPredicateCompareShardingValue(segment, parameters);
-            }
-            if (rightValue instanceof PredicateInRightValue) {
-                Collection<ExpressionSegment> segments = 
((PredicateInRightValue) rightValue).getSqlExpressions();
-                return getPredicateInShardingValue(segments, parameters);
+        }
+        if (!(expression instanceof BinaryOperationExpression)) {
+            return Optional.empty();
+        }
+        String operator = ((BinaryOperationExpression) 
expression).getOperator();
+        boolean compare = ">".equalsIgnoreCase(operator) || 
">=".equalsIgnoreCase(operator) || "=".equalsIgnoreCase(operator) || 
"<".equalsIgnoreCase(operator) || "<=".equalsIgnoreCase(operator);
+        if (compare && ((BinaryOperationExpression) expression).getLeft() 
instanceof ColumnSegment) {
+            ColumnSegment column = (ColumnSegment) 
((BinaryOperationExpression) expression).getLeft();
+            if 
(shardingColumn.equalsIgnoreCase(column.getIdentifier().getValue())) {

Review comment:
       Refactoring

##########
File path: 
shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -98,22 +107,45 @@
         return result;
     }
     
-    private Map<Column, Collection<RouteValue>> createRouteValueMap(final 
SQLStatementContext sqlStatementContext, final AndPredicate andPredicate, final 
List<Object> parameters) {
+    private Map<Column, Collection<RouteValue>> createRouteValueMap(final 
SQLStatementContext sqlStatementContext, final AndPredicate expressions, final 
List<Object> parameters) {
         Map<Column, Collection<RouteValue>> result = new HashMap<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<String> tableName = 
sqlStatementContext.getTablesContext().findTableName(each.getColumn(), 
schemaMetaData);
-            if (!tableName.isPresent() || 
!shardingRule.isShardingColumn(each.getColumn().getIdentifier().getValue(), 
tableName.get())) {
-                continue;
+    
+        for (ExpressionSegment each : expressions.getPredicates()) {
+            Optional<RouteValue> routeValue = Optional.empty();
+            Column column = null;
+            if (each instanceof BinaryOperationExpression && 
((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                ColumnSegment columnSegment = (ColumnSegment) 
((BinaryOperationExpression) each).getLeft();
+                Optional<String> tableName = 
sqlStatementContext.getTablesContext().findTableName(columnSegment, 
schemaMetaData);
+                if (tableName.isPresent() && 
shardingRule.isShardingColumn(columnSegment.getIdentifier().getValue(), 
tableName.get())) {

Review comment:
       Refactoring

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/TopPaginationContextEngine.java
##########
@@ -43,47 +41,57 @@
      * Create pagination context.
      * 
      * @param topProjectionSegment top projection segment
-     * @param andPredicates and predicates
+     * @param where where condition
      * @param parameters SQL parameters
      * @return pagination context
      */
-    public PaginationContext createPaginationContext(final 
TopProjectionSegment topProjectionSegment, final Collection<AndPredicate> 
andPredicates, final List<Object> parameters) {
-        Optional<PredicateSegment> rowNumberPredicate = 
getRowNumberPredicate(andPredicates, topProjectionSegment.getAlias());
+    public PaginationContext createPaginationContext(final 
TopProjectionSegment topProjectionSegment, final ExpressionSegment where, final 
List<Object> parameters) {
+        Optional<ExpressionSegment> rowNumberPredicate = null != where ? 
getRowNumberPredicate(where, topProjectionSegment.getAlias()) : 
Optional.empty();
         Optional<PaginationValueSegment> offset = 
rowNumberPredicate.isPresent() ? 
createOffsetWithRowNumber(rowNumberPredicate.get()) : Optional.empty();
         PaginationValueSegment rowCount = topProjectionSegment.getTop();
         return new PaginationContext(offset.orElse(null), rowCount, 
parameters);
     }
     
-    private Optional<PredicateSegment> getRowNumberPredicate(final 
Collection<AndPredicate> andPredicates, final String rowNumberAlias) {
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                if (isRowNumberColumn(predicate, rowNumberAlias) && 
isCompareCondition(predicate)) {
-                    return Optional.of(predicate);
-                }
+    private Optional<ExpressionSegment> getRowNumberPredicate(final 
ExpressionSegment where, final String rowNumberAlias) {
+        if (!(where instanceof BinaryOperationExpression)) {
+            return Optional.empty();
+        }
+        String operator = ((BinaryOperationExpression) where).getOperator();
+        if (((BinaryOperationExpression) where).getLeft() instanceof 
ColumnSegment && isRowNumberColumn((ColumnSegment) ((BinaryOperationExpression) 
where).getLeft(), rowNumberAlias)

Review comment:
       The function is needed.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/TopPaginationContextEngineTest.java
##########
@@ -107,13 +105,12 @@ public void 
assertCreatePaginationContextWhenParameterMarkerRowNumberValueSegmen
     
     private void 
assertCreatePaginationContextWhenRowNumberPredicatePresentAndWithGivenOperator(final
 String operator) {
         String name = "rowNumberAlias";
-        ColumnSegment columnSegment = new ColumnSegment(0, 10, new 
IdentifierValue(name));
-        PredicateCompareRightValue predicateCompareRightValue = new 
PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 
100));
-        PredicateSegment predicateSegment = new PredicateSegment(0, 10, 
columnSegment, predicateCompareRightValue);
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(predicateSegment);
-        Collection<AndPredicate> andPredicates = 
Collections.singleton(andPredicate);
-        PaginationContext paginationContext = 
topPaginationContextEngine.createPaginationContext(new TopProjectionSegment(0, 
10, null, name), andPredicates, Collections.emptyList());
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new 
IdentifierValue(name)));
+        

Review comment:
       Remove.

##########
File path: 
shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/SQLServerVisitor.java
##########
@@ -244,121 +241,141 @@ public final ASTNode visitExpr(final ExprContext ctx) {
         if (null != ctx.booleanPrimary()) {
             return visit(ctx.booleanPrimary());
         }
+        if (null != ctx.LP_()) {
+            return visit(ctx.expr(0));
+        }
         if (null != ctx.logicalOperator()) {
-            return new PredicateBuildUtils(visit(ctx.expr(0)), 
visit(ctx.expr(1)), ctx.logicalOperator().getText()).mergePredicate();
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.expr(0)));
+            result.setRight((ExpressionSegment) visit(ctx.expr(1)));
+            result.setOperator(ctx.logicalOperator().getText());
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
         }
-        // TODO deal with XOR
-        return visit(ctx.expr().get(0));
+        NotExpression result = new NotExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setExpression((ExpressionSegment) visit(ctx.expr(0)));
+        return result;
     }
     
     @Override
     public final ASTNode visitBooleanPrimary(final BooleanPrimaryContext ctx) {
+        if (null != ctx.IS()) {
+            BinaryOperationExpression result = new BinaryOperationExpression();
+            result.setStartIndex(ctx.start.getStartIndex());
+            result.setStopIndex(ctx.stop.getStopIndex());
+            result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+            result.setRight(new 
LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 1, 
ctx.stop.getStopIndex(), new Interval(ctx.IS().getSymbol().getStopIndex() + 1,
+                    ctx.stop.getStopIndex())));
+            result.setOperator("IS");
+            String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+            result.setText(text);
+            return result;
+        }
         if (null != ctx.comparisonOperator() || null != ctx.SAFE_EQ_()) {
             return createCompareSegment(ctx);
         }
-        if (null != ctx.predicate()) {
-            return visit(ctx.predicate());
-        }
-        if (null != ctx.subquery()) {
-            return new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        //TODO deal with IS NOT? (TRUE | FALSE | UNKNOWN | NULL)
-        return new CommonExpressionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ctx.getText());
+        return visit(ctx.predicate());
     }
     
     private ASTNode createCompareSegment(final BooleanPrimaryContext ctx) {
-        ASTNode leftValue = visit(ctx.booleanPrimary());
-        if (!(leftValue instanceof ColumnSegment)) {
-            return leftValue;
-        }
-        PredicateRightValue rightValue = (PredicateRightValue) 
createPredicateRightValue(ctx);
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (ColumnSegment) leftValue, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx) 
{
-        if (null != ctx.subquery()) {
-            new SubquerySegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()));
-        }
-        ASTNode rightValue = visit(ctx.predicate());
-        return createPredicateRightValue(ctx, rightValue);
-    }
-    
-    private ASTNode createPredicateRightValue(final BooleanPrimaryContext ctx, 
final ASTNode rightValue) {
-        if (rightValue instanceof ColumnSegment) {
-            return rightValue;
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.booleanPrimary()));
+        if (null != ctx.predicate()) {
+            result.setRight((ExpressionSegment) visit(ctx.predicate()));
+        } else {
+            result.setRight((ExpressionSegment) visit(ctx.subquery()));
         }
-        return rightValue instanceof SubquerySegment ? new 
PredicateCompareRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(), ctx.comparisonOperator().getText(),
-                new SubqueryExpressionSegment((SubquerySegment) rightValue))
-                : new 
PredicateCompareRightValue(ctx.predicate().start.getStartIndex(), 
ctx.predicate().stop.getStopIndex(), ctx.comparisonOperator().getText(), 
(ExpressionSegment) rightValue);
+        String operator = null != ctx.SAFE_EQ_() ? ctx.SAFE_EQ_().getText() : 
ctx.comparisonOperator().getText();
+        result.setOperator(operator);
+        String text = ctx.start.getInputStream().getText(new 
Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        return result;
     }
     
     @Override
     public final ASTNode visitPredicate(final PredicateContext ctx) {
-        if (null != ctx.IN() && null == ctx.NOT()) {
+        if (null != ctx.IN()) {
             return createInSegment(ctx);
         }
-        if (null != ctx.BETWEEN() && null == ctx.NOT()) {
+        if (null != ctx.BETWEEN()) {
             return createBetweenSegment(ctx);
         }
-        if (1 == ctx.children.size()) {
-            return visit(ctx.bitExpr(0));
+        if (null != ctx.LIKE()) {
+            return createBinaryOperationExpressionFromLike(ctx);
         }
-        return visitRemainPredicate(ctx);
-    }
-    
-    private PredicateSegment createInSegment(final PredicateContext ctx) {
-        ColumnSegment column = (ColumnSegment) visit(ctx.bitExpr(0));
-        PredicateInRightValue predicateInRightValue = null != ctx.subquery() ? 
new PredicateInRightValue(ctx.subquery().start.getStartIndex(), 
ctx.subquery().stop.getStopIndex(),
-                getExpressionSegments(ctx))
-                : new 
PredicateInRightValue(ctx.LP_().getSymbol().getStartIndex(), 
ctx.RP_().getSymbol().getStopIndex(), getExpressionSegments(ctx));
-        return new PredicateSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), column, predicateInRightValue);
+        return visit(ctx.bitExpr(0));
     }
     
-    private Collection<ExpressionSegment> getExpressionSegments(final 
PredicateContext ctx) {
-        Collection<ExpressionSegment> result = new LinkedList<>();
-        if (null != ctx.subquery()) {
-            SubqueryContext subquery = ctx.subquery();
-            result.add(new SubqueryExpressionSegment(new 
SubquerySegment(subquery.getStart().getStartIndex(), 
subquery.getStop().getStopIndex(), (SelectStatement) visit(ctx.subquery()))));
-            return result;
-        }
-        for (ExprContext each : ctx.expr()) {
-            result.add((ExpressionSegment) visit(each));
+    private BinaryOperationExpression 
createBinaryOperationExpressionFromLike(final PredicateContext ctx) {
+        BinaryOperationExpression result = new BinaryOperationExpression();
+        result.setStartIndex(ctx.start.getStartIndex());
+        result.setStopIndex(ctx.stop.getStopIndex());
+        result.setLeft((ExpressionSegment) visit(ctx.bitExpr(0)));
+        ListExpression listExpression = new ListExpression();
+        for (SimpleExprContext each : ctx.simpleExpr()) {
+            listExpression.getItems().add((ExpressionSegment) visit(each));
         }
+        result.setRight(listExpression);

Review comment:
       A function is needed here.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to