You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by GitBox <gi...@apache.org> on 2020/09/09 09:08:11 UTC

[GitHub] [shardingsphere] jingshanglu opened a new pull request #7353: Improve the Statement definition

jingshanglu opened a new pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353


   Improve the Statement definition
   
   Changes proposed in this pull request:
   - Improve the from definition
   - Improve the where definition
   - Improve the expr definition
   


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] tristaZero merged pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
tristaZero merged pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353






----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] jingshanglu commented on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
jingshanglu commented on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-690983807






----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] tristaZero commented on a change in pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
tristaZero commented on a change in pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#discussion_r486032788



##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java
##########
@@ -81,50 +102,72 @@
     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 = null;
+        if (expression instanceof BinaryOperationExpression && ((BinaryOperationExpression) expression).getLeft() instanceof ColumnSegment) {
+            column = (ColumnSegment) ((BinaryOperationExpression) expression).getLeft();
+        } else if (expression instanceof InExpression && ((InExpression) expression).getLeft() instanceof ColumnSegment) {
+            column = (ColumnSegment) ((InExpression) expression).getLeft();
+        } else if (expression instanceof BetweenExpression && ((BetweenExpression) expression).getLeft() instanceof ColumnSegment) {
+            column = (ColumnSegment) ((BetweenExpression) expression).getLeft();
+        }
+        if (null == column) {
+            return Optional.empty();
+        }
+        Optional<String> tableName = sqlStatementContext.getTablesContext().findTableName(column, schemaMetaData);
+        return tableName.isPresent() && encryptRule.findEncryptor(tableName.get(), column.getIdentifier().getValue()).isPresent()
+                ? createEncryptCondition(expression, tableName.get()) : Optional.empty();
     }
     
-    private Optional<EncryptCondition> createEncryptCondition(final PredicateSegment predicateSegment, final String tableName) {
-        if (predicateSegment.getRightValue() instanceof PredicateCompareRightValue) {
-            PredicateCompareRightValue compareRightValue = (PredicateCompareRightValue) predicateSegment.getRightValue();
-            return isSupportedOperator(compareRightValue.getOperator()) ? createCompareEncryptCondition(tableName, predicateSegment, compareRightValue) : Optional.empty();
+    private Optional<EncryptCondition> createEncryptCondition(final ExpressionSegment expression, final String tableName) {
+        if (expression instanceof BinaryOperationExpression) {
+            String operator = ((BinaryOperationExpression) expression).getOperator();

Review comment:
       A concrete class for `operator` is recommended.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -75,10 +98,18 @@
     }
     
     private Optional<ShadowCondition> createShadowCondition(final AndPredicate andPredicate) {
-        for (PredicateSegment predicate : andPredicate.getPredicates()) {
+        for (ExpressionSegment predicate : andPredicate.getPredicates()) {
+            ColumnSegment column = null;
+            if (predicate instanceof BinaryOperationExpression && ((BinaryOperationExpression) predicate).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) predicate).getLeft();
+            } else if (predicate instanceof InExpression && ((InExpression) predicate).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) predicate).getLeft();

Review comment:
       The similar handling appears many times, so do you think it is possible to exact a function?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/insert/values/expression/DerivedParameterMarkerExpressionSegment.java
##########
@@ -31,4 +31,9 @@
     public DerivedParameterMarkerExpressionSegment(final int parameterMarkerIndex) {
         super(0, 0, parameterMarkerIndex);
     }
+    
+    @Override
+    public String getText() {
+        return null;

Review comment:
       Why do we need this interface?

##########
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,185 @@ 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)));
+        String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        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);
+        if (null != ctx.REGEXP()) {
+            return createBinaryOperationExpressionFromRegexp(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 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());
+            String text = ctx.start.getInputStream().getText(new Interval(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex()));
+            listExpression.setText(text);
+            for (ExprContext each : ctx.expr()) {
+                listExpression.getItems().add((ExpressionSegment) visit(each));
+            }
+            result.setRight(listExpression);
+        }
+        Boolean operator = null != ctx.NOT() ? true : false;
+        result.setNot(operator);
+        String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
+        result.setText(text);
+        return result;
     }
     
-    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)));
+        String operator;
+        if (null != ctx.SOUNDS()) {
+            

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/table/TablesContext.java
##########
@@ -44,6 +45,18 @@ public TablesContext(final SimpleTableSegment tableSegment) {
         this(null == tableSegment ? Collections.emptyList() : Collections.singletonList(tableSegment));
     }
     
+    public TablesContext(final Collection<SimpleTableSegment> tableSegments) {
+        Map<String, SimpleTableSegment> tableMaps = new HashMap<>(1, 1);
+        Collection<SimpleTableSegment> realtables = new LinkedList<>();
+        for (SimpleTableSegment each : tableSegments) {
+            if (!tableMaps.containsKey(each.getTableName().getIdentifier().getValue())) {
+                tableMaps.put(each.getTableName().getIdentifier().getValue(), each);
+                realtables.add(each);
+            }
+        }
+        this.tables = realtables;

Review comment:
       `realtable`? I suppose we do not have this concept. Do you mean `actualTable`?




----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] coveralls edited a comment on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
coveralls edited a comment on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-689492635


   ## Pull Request Test Coverage Report for [Build 14701](https://coveralls.io/builds/33389173)
   
   * **784** of **1133**   **(69.2%)**  changed or added relevant lines in **44** files are covered.
   * **96** unchanged lines in **25** files lost coverage.
   * Overall coverage increased (+**0.02%**) to **34.149%**
   
   ---
   
   |  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
   | :-----|--------------|--------|---: |
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FEncryptPredicateColumnTokenGenerator.java#L76) | 17 | 18 | 94.44%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-dialect%2Fshardingsphere-sql-parser-mysql%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fmysql%2Fvisitor%2Fimpl%2FMySQLDMLVisitor.java#L585) | 50 | 51 | 98.04%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/AggregateExpression.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FAggregateExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BetweenExpression.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBetweenExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BinaryOperationExpression.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBinaryOperationExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/NotExpression.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FNotExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/predicate/AndPredicate.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fpredicate%2FAndPredicate.java#L37) | 0 | 1 | 0.0%
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L56) | 4 | 6 | 66.67%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ListExpression.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FListExpression.java#L28) | 0 | 2 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fgeneric%2Ftable%2FJoinTableSegment.java#L31) | 0 | 2 | 0.0%
   <!-- | **Total:** | **784** | **1133** | **69.2%** | -->
   
   |  Files with Coverage Reduction | New Missed Lines | % |
   | :-----|--------------|--: |
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Fcondition%2FEncryptConditionEngine.java#L136) | 1 | 83.64% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Fcondition%2FShadowConditionEngine.java#L127) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-rewrite/src/main/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FShadowPredicateColumnTokenGenerator.java#L74) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L59) | 1 | 57.14% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/impl/ConditionValueCompareOperatorGenerator.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2Fimpl%2FConditionValueCompareOperatorGenerator.java#L64) | 1 | 90.48% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/impl/ShardingUpdateStatementValidator.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fvalidator%2Fimpl%2FShardingUpdateStatementValidator.java#L125) | 1 | 52.78% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngine.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FRowNumberPaginationContextEngine.java#L88) | 1 | 85.19% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/TopPaginationContextEngine.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FTopPaginationContextEngine.java#L74) | 1 | 69.7% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/SelectStatementContext.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fstatement%2Fdml%2FSelectStatementContext.java#L102) | 1 | 95.71% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java](https://coveralls.io/builds/33389173/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-dialect%2Fshardingsphere-sql-parser-mysql%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fmysql%2Fvisitor%2Fimpl%2FMySQLDMLVisitor.java#L525) | 1 | 94.83% |
   <!-- | **Total:** | **96** |  | -->
   
   |  Totals | [![Coverage Status](https://coveralls.io/builds/33389173/badge)](https://coveralls.io/builds/33389173) |
   | :-- | --: |
   | Change from base [Build 14672](https://coveralls.io/builds/33380890): |  0.02% |
   | Covered Lines: | 35560 |
   | Relevant Lines: | 104133 |
   
   ---
   ##### 💛  - [Coveralls](https://coveralls.io)
   


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] coveralls edited a comment on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
coveralls edited a comment on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-689492635






----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] coveralls commented on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
coveralls commented on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-689492635


   ## Pull Request Test Coverage Report for [Build 14607](https://coveralls.io/builds/33328685)
   
   * **851** of **1253**   **(67.92%)**  changed or added relevant lines in **50** files are covered.
   * **112** unchanged lines in **27** files lost coverage.
   * Overall coverage increased (+**0.07%**) to **34.184%**
   
   ---
   
   |  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
   | :-----|--------------|--------|---: |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/insert/values/expression/DerivedLiteralExpressionSegment.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Finsert%2Fvalues%2Fexpression%2FDerivedLiteralExpressionSegment.java#L37) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/insert/values/expression/DerivedParameterMarkerExpressionSegment.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Finsert%2Fvalues%2Fexpression%2FDerivedParameterMarkerExpressionSegment.java#L37) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-dialect%2Fshardingsphere-sql-parser-mysql%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fmysql%2Fvisitor%2Fimpl%2FMySQLDMLVisitor.java#L584) | 50 | 51 | 98.04%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/column/ColumnSegment.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fcolumn%2FColumnSegment.java#L67) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/AggregateExpression.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FAggregateExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BetweenExpression.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBetweenExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BinaryOperationExpression.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBinaryOperationExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/NotExpression.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FNotExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/complex/CommonTableExpressionSegment.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2Fcomplex%2FCommonTableExpressionSegment.java#L51) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/simple/LiteralExpressionSegment.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2Fsimple%2FLiteralExpressionSegment.java#L40) | 0 | 1 | 0.0%
   <!-- | **Total:** | **851** | **1253** | **67.92%** | -->
   
   |  Files with Coverage Reduction | New Missed Lines | % |
   | :-----|--------------|--: |
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Fcondition%2FEncryptConditionEngine.java#L157) | 1 | 76.71% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Fcondition%2FShadowConditionEngine.java#L146) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-rewrite/src/main/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FShadowPredicateColumnTokenGenerator.java#L98) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L59) | 1 | 57.14% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/impl/ConditionValueCompareOperatorGenerator.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2Fimpl%2FConditionValueCompareOperatorGenerator.java#L64) | 1 | 90.48% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/impl/ShardingUpdateStatementValidator.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fvalidator%2Fimpl%2FShardingUpdateStatementValidator.java#L125) | 1 | 52.78% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngine.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FRowNumberPaginationContextEngine.java#L88) | 1 | 85.19% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/TopPaginationContextEngine.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FTopPaginationContextEngine.java#L74) | 1 | 69.7% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/SelectStatementContext.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fstatement%2Fdml%2FSelectStatementContext.java#L102) | 1 | 95.71% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java](https://coveralls.io/builds/33328685/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-dialect%2Fshardingsphere-sql-parser-mysql%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fmysql%2Fvisitor%2Fimpl%2FMySQLDMLVisitor.java#L524) | 1 | 94.83% |
   <!-- | **Total:** | **112** |  | -->
   
   |  Totals | [![Coverage Status](https://coveralls.io/builds/33328685/badge)](https://coveralls.io/builds/33328685) |
   | :-- | --: |
   | Change from base [Build 14602](https://coveralls.io/builds/33327497): |  0.07% |
   | Covered Lines: | 35590 |
   | Relevant Lines: | 104112 |
   
   ---
   ##### 💛  - [Coveralls](https://coveralls.io)
   


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] tristaZero merged pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
tristaZero merged pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353


   


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] tristaZero commented on a change in pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
tristaZero commented on a change in pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#discussion_r486801178



##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove

##########
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.

##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -73,21 +78,25 @@
         List<ShardingCondition> result = new ArrayList<>();
         Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
         if (whereSegment.isPresent()) {
-            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getAndPredicates(), parameters));
+            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getExpr(), parameters));
         }
         Collection<WhereSegment> subqueryWhereSegments = sqlStatementContext.getSqlStatement() instanceof SelectStatement
                 ? WhereSegmentExtractUtils.getSubqueryWhereSegments((SelectStatement) sqlStatementContext.getSqlStatement()) : Collections.emptyList();
         for (WhereSegment each : subqueryWhereSegments) {
-            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getAndPredicates(), parameters);
+            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getExpr(), parameters);
             if (!result.containsAll(subqueryShardingConditions)) {
                 result.addAll(subqueryShardingConditions);
             }
         }
         return result;
     }
     
-    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final Collection<AndPredicate> andPredicates, final List<Object> parameters) {
+    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final ExpressionSegment expressionSegment, final List<Object> parameters) {
         Collection<ShardingCondition> result = new LinkedList<>();
+    

Review comment:
       Remove

##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove

##########
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.

##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -73,21 +78,25 @@
         List<ShardingCondition> result = new ArrayList<>();
         Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
         if (whereSegment.isPresent()) {
-            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getAndPredicates(), parameters));
+            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getExpr(), parameters));
         }
         Collection<WhereSegment> subqueryWhereSegments = sqlStatementContext.getSqlStatement() instanceof SelectStatement
                 ? WhereSegmentExtractUtils.getSubqueryWhereSegments((SelectStatement) sqlStatementContext.getSqlStatement()) : Collections.emptyList();
         for (WhereSegment each : subqueryWhereSegments) {
-            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getAndPredicates(), parameters);
+            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getExpr(), parameters);
             if (!result.containsAll(subqueryShardingConditions)) {
                 result.addAll(subqueryShardingConditions);
             }
         }
         return result;
     }
     
-    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final Collection<AndPredicate> andPredicates, final List<Object> parameters) {
+    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final ExpressionSegment expressionSegment, final List<Object> parameters) {
         Collection<ShardingCondition> result = new LinkedList<>();
+    

Review comment:
       Remove

##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove

##########
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.

##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -73,21 +78,25 @@
         List<ShardingCondition> result = new ArrayList<>();
         Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
         if (whereSegment.isPresent()) {
-            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getAndPredicates(), parameters));
+            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getExpr(), parameters));
         }
         Collection<WhereSegment> subqueryWhereSegments = sqlStatementContext.getSqlStatement() instanceof SelectStatement
                 ? WhereSegmentExtractUtils.getSubqueryWhereSegments((SelectStatement) sqlStatementContext.getSqlStatement()) : Collections.emptyList();
         for (WhereSegment each : subqueryWhereSegments) {
-            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getAndPredicates(), parameters);
+            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getExpr(), parameters);
             if (!result.containsAll(subqueryShardingConditions)) {
                 result.addAll(subqueryShardingConditions);
             }
         }
         return result;
     }
     
-    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final Collection<AndPredicate> andPredicates, final List<Object> parameters) {
+    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final ExpressionSegment expressionSegment, final List<Object> parameters) {
         Collection<ShardingCondition> result = new LinkedList<>();
+    

Review comment:
       Remove

##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove

##########
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.

##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -73,21 +78,25 @@
         List<ShardingCondition> result = new ArrayList<>();
         Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
         if (whereSegment.isPresent()) {
-            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getAndPredicates(), parameters));
+            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getExpr(), parameters));
         }
         Collection<WhereSegment> subqueryWhereSegments = sqlStatementContext.getSqlStatement() instanceof SelectStatement
                 ? WhereSegmentExtractUtils.getSubqueryWhereSegments((SelectStatement) sqlStatementContext.getSqlStatement()) : Collections.emptyList();
         for (WhereSegment each : subqueryWhereSegments) {
-            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getAndPredicates(), parameters);
+            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getExpr(), parameters);
             if (!result.containsAll(subqueryShardingConditions)) {
                 result.addAll(subqueryShardingConditions);
             }
         }
         return result;
     }
     
-    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final Collection<AndPredicate> andPredicates, final List<Object> parameters) {
+    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final ExpressionSegment expressionSegment, final List<Object> parameters) {
         Collection<ShardingCondition> result = new LinkedList<>();
+    

Review comment:
       Remove

##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove

##########
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.

##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -73,21 +78,25 @@
         List<ShardingCondition> result = new ArrayList<>();
         Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
         if (whereSegment.isPresent()) {
-            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getAndPredicates(), parameters));
+            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getExpr(), parameters));
         }
         Collection<WhereSegment> subqueryWhereSegments = sqlStatementContext.getSqlStatement() instanceof SelectStatement
                 ? WhereSegmentExtractUtils.getSubqueryWhereSegments((SelectStatement) sqlStatementContext.getSqlStatement()) : Collections.emptyList();
         for (WhereSegment each : subqueryWhereSegments) {
-            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getAndPredicates(), parameters);
+            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getExpr(), parameters);
             if (!result.containsAll(subqueryShardingConditions)) {
                 result.addAll(subqueryShardingConditions);
             }
         }
         return result;
     }
     
-    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final Collection<AndPredicate> andPredicates, final List<Object> parameters) {
+    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final ExpressionSegment expressionSegment, final List<Object> parameters) {
         Collection<ShardingCondition> result = new LinkedList<>();
+    

Review comment:
       Remove

##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove

##########
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.

##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -73,21 +78,25 @@
         List<ShardingCondition> result = new ArrayList<>();
         Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
         if (whereSegment.isPresent()) {
-            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getAndPredicates(), parameters));
+            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getExpr(), parameters));
         }
         Collection<WhereSegment> subqueryWhereSegments = sqlStatementContext.getSqlStatement() instanceof SelectStatement
                 ? WhereSegmentExtractUtils.getSubqueryWhereSegments((SelectStatement) sqlStatementContext.getSqlStatement()) : Collections.emptyList();
         for (WhereSegment each : subqueryWhereSegments) {
-            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getAndPredicates(), parameters);
+            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getExpr(), parameters);
             if (!result.containsAll(subqueryShardingConditions)) {
                 result.addAll(subqueryShardingConditions);
             }
         }
         return result;
     }
     
-    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final Collection<AndPredicate> andPredicates, final List<Object> parameters) {
+    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final ExpressionSegment expressionSegment, final List<Object> parameters) {
         Collection<ShardingCondition> result = new LinkedList<>();
+    

Review comment:
       Remove

##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove

##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove

##########
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.

##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -73,21 +78,25 @@
         List<ShardingCondition> result = new ArrayList<>();
         Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
         if (whereSegment.isPresent()) {
-            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getAndPredicates(), parameters));
+            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getExpr(), parameters));
         }
         Collection<WhereSegment> subqueryWhereSegments = sqlStatementContext.getSqlStatement() instanceof SelectStatement
                 ? WhereSegmentExtractUtils.getSubqueryWhereSegments((SelectStatement) sqlStatementContext.getSqlStatement()) : Collections.emptyList();
         for (WhereSegment each : subqueryWhereSegments) {
-            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getAndPredicates(), parameters);
+            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getExpr(), parameters);
             if (!result.containsAll(subqueryShardingConditions)) {
                 result.addAll(subqueryShardingConditions);
             }
         }
         return result;
     }
     
-    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final Collection<AndPredicate> andPredicates, final List<Object> parameters) {
+    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final ExpressionSegment expressionSegment, final List<Object> parameters) {
         Collection<ShardingCondition> result = new LinkedList<>();
+    

Review comment:
       Remove

##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove

##########
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.

##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -73,21 +78,25 @@
         List<ShardingCondition> result = new ArrayList<>();
         Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
         if (whereSegment.isPresent()) {
-            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getAndPredicates(), parameters));
+            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getExpr(), parameters));
         }
         Collection<WhereSegment> subqueryWhereSegments = sqlStatementContext.getSqlStatement() instanceof SelectStatement
                 ? WhereSegmentExtractUtils.getSubqueryWhereSegments((SelectStatement) sqlStatementContext.getSqlStatement()) : Collections.emptyList();
         for (WhereSegment each : subqueryWhereSegments) {
-            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getAndPredicates(), parameters);
+            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getExpr(), parameters);
             if (!result.containsAll(subqueryShardingConditions)) {
                 result.addAll(subqueryShardingConditions);
             }
         }
         return result;
     }
     
-    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final Collection<AndPredicate> andPredicates, final List<Object> parameters) {
+    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final ExpressionSegment expressionSegment, final List<Object> parameters) {
         Collection<ShardingCondition> result = new LinkedList<>();
+    

Review comment:
       Remove




----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] coveralls edited a comment on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
coveralls edited a comment on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-689492635






----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] tristaZero commented on a change in pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
tristaZero commented on a change in pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#discussion_r487343637



##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -73,21 +78,25 @@
         List<ShardingCondition> result = new ArrayList<>();
         Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
         if (whereSegment.isPresent()) {
-            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getAndPredicates(), parameters));
+            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getExpr(), parameters));
         }
         Collection<WhereSegment> subqueryWhereSegments = sqlStatementContext.getSqlStatement() instanceof SelectStatement
                 ? WhereSegmentExtractUtils.getSubqueryWhereSegments((SelectStatement) sqlStatementContext.getSqlStatement()) : Collections.emptyList();
         for (WhereSegment each : subqueryWhereSegments) {
-            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getAndPredicates(), parameters);
+            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getExpr(), parameters);
             if (!result.containsAll(subqueryShardingConditions)) {
                 result.addAll(subqueryShardingConditions);
             }
         }
         return result;
     }
     
-    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final Collection<AndPredicate> andPredicates, final List<Object> parameters) {
+    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final ExpressionSegment expressionSegment, final List<Object> parameters) {
         Collection<ShardingCondition> result = new LinkedList<>();
+    

Review comment:
       Remove




----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] coveralls edited a comment on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
coveralls edited a comment on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-689492635


   ## Pull Request Test Coverage Report for [Build 14697](https://coveralls.io/builds/33387442)
   
   * **795** of **1149**   **(69.19%)**  changed or added relevant lines in **43** files are covered.
   * **97** unchanged lines in **26** files lost coverage.
   * Overall coverage increased (+**0.03%**) to **34.153%**
   
   ---
   
   |  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
   | :-----|--------------|--------|---: |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-dialect%2Fshardingsphere-sql-parser-mysql%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fmysql%2Fvisitor%2Fimpl%2FMySQLDMLVisitor.java#L585) | 50 | 51 | 98.04%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/AggregateExpression.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FAggregateExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BetweenExpression.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBetweenExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BinaryOperationExpression.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBinaryOperationExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/NotExpression.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FNotExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/predicate/AndPredicate.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fpredicate%2FAndPredicate.java#L37) | 0 | 1 | 0.0%
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FEncryptPredicateColumnTokenGenerator.java#L107) | 24 | 26 | 92.31%
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L56) | 4 | 6 | 66.67%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ListExpression.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FListExpression.java#L28) | 0 | 2 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fgeneric%2Ftable%2FJoinTableSegment.java#L31) | 0 | 2 | 0.0%
   <!-- | **Total:** | **795** | **1149** | **69.19%** | -->
   
   |  Files with Coverage Reduction | New Missed Lines | % |
   | :-----|--------------|--: |
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Fcondition%2FEncryptConditionEngine.java#L142) | 1 | 81.97% |
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FEncryptPredicateColumnTokenGenerator.java#L78) | 1 | 92.86% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Fcondition%2FShadowConditionEngine.java#L130) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-rewrite/src/main/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FShadowPredicateColumnTokenGenerator.java#L83) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L59) | 1 | 57.14% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/impl/ConditionValueCompareOperatorGenerator.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2Fimpl%2FConditionValueCompareOperatorGenerator.java#L64) | 1 | 90.48% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/impl/ShardingUpdateStatementValidator.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fvalidator%2Fimpl%2FShardingUpdateStatementValidator.java#L125) | 1 | 52.78% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngine.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FRowNumberPaginationContextEngine.java#L88) | 1 | 85.19% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/TopPaginationContextEngine.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FTopPaginationContextEngine.java#L74) | 1 | 69.7% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/SelectStatementContext.java](https://coveralls.io/builds/33387442/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fstatement%2Fdml%2FSelectStatementContext.java#L102) | 1 | 95.71% |
   <!-- | **Total:** | **97** |  | -->
   
   |  Totals | [![Coverage Status](https://coveralls.io/builds/33387442/badge)](https://coveralls.io/builds/33387442) |
   | :-- | --: |
   | Change from base [Build 14672](https://coveralls.io/builds/33380890): |  0.03% |
   | Covered Lines: | 35570 |
   | Relevant Lines: | 104149 |
   
   ---
   ##### 💛  - [Coveralls](https://coveralls.io)
   


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] tristaZero merged pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
tristaZero merged pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353


   


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] tristaZero merged pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
tristaZero merged pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353






----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] jingshanglu commented on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
jingshanglu commented on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-690983807


   @tristaZero The operator is complex, because there are many operator are string, such as `like`,`OPERATOR (anyOperator) ` ,  it is better to combined with the definition of the new segment. mybe it's better to split into separate pr.


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] coveralls edited a comment on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
coveralls edited a comment on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-689492635


   ## Pull Request Test Coverage Report for [Build 14653](https://coveralls.io/builds/33362461)
   
   * **790** of **1146**   **(68.94%)**  changed or added relevant lines in **44** files are covered.
   * **96** unchanged lines in **25** files lost coverage.
   * Overall coverage increased (+**0.06%**) to **34.147%**
   
   ---
   
   |  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
   | :-----|--------------|--------|---: |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-dialect%2Fshardingsphere-sql-parser-mysql%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fmysql%2Fvisitor%2Fimpl%2FMySQLDMLVisitor.java#L584) | 50 | 51 | 98.04%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/AggregateExpression.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FAggregateExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BetweenExpression.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBetweenExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BinaryOperationExpression.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBinaryOperationExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/NotExpression.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FNotExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/predicate/AndPredicate.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fpredicate%2FAndPredicate.java#L37) | 0 | 1 | 0.0%
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FEncryptPredicateColumnTokenGenerator.java#L81) | 19 | 21 | 90.48%
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L56) | 4 | 6 | 66.67%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ListExpression.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FListExpression.java#L28) | 0 | 2 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fitem%2FBinaryOperationProjection.java#L30) | 0 | 2 | 0.0%
   <!-- | **Total:** | **790** | **1146** | **68.94%** | -->
   
   |  Files with Coverage Reduction | New Missed Lines | % |
   | :-----|--------------|--: |
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Fcondition%2FEncryptConditionEngine.java#L142) | 1 | 81.97% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Fcondition%2FShadowConditionEngine.java#L131) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-rewrite/src/main/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FShadowPredicateColumnTokenGenerator.java#L83) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L59) | 1 | 57.14% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/impl/ConditionValueCompareOperatorGenerator.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2Fimpl%2FConditionValueCompareOperatorGenerator.java#L64) | 1 | 90.48% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/impl/ShardingUpdateStatementValidator.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fvalidator%2Fimpl%2FShardingUpdateStatementValidator.java#L125) | 1 | 52.78% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngine.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FRowNumberPaginationContextEngine.java#L88) | 1 | 85.19% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/TopPaginationContextEngine.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FTopPaginationContextEngine.java#L74) | 1 | 69.7% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/SelectStatementContext.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fstatement%2Fdml%2FSelectStatementContext.java#L102) | 1 | 95.71% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java](https://coveralls.io/builds/33362461/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-dialect%2Fshardingsphere-sql-parser-mysql%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fmysql%2Fvisitor%2Fimpl%2FMySQLDMLVisitor.java#L524) | 1 | 94.83% |
   <!-- | **Total:** | **96** |  | -->
   
   |  Totals | [![Coverage Status](https://coveralls.io/builds/33362461/badge)](https://coveralls.io/builds/33362461) |
   | :-- | --: |
   | Change from base [Build 14649](https://coveralls.io/builds/33360750): |  0.06% |
   | Covered Lines: | 35565 |
   | Relevant Lines: | 104154 |
   
   ---
   ##### 💛  - [Coveralls](https://coveralls.io)
   


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] jingshanglu commented on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
jingshanglu commented on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-690983807


   @tristaZero The operator is complex, because there are many operator are string, such as `like`,`OPERATOR (anyOperator) ` ,  it is better to combined with the definition of the new segment. mybe it's better to split into separate pr.


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] tristaZero commented on a change in pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
tristaZero commented on a change in pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#discussion_r486801178



##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove

##########
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.

##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
##########
@@ -73,21 +78,25 @@
         List<ShardingCondition> result = new ArrayList<>();
         Optional<WhereSegment> whereSegment = ((WhereAvailable) sqlStatementContext).getWhere();
         if (whereSegment.isPresent()) {
-            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getAndPredicates(), parameters));
+            result.addAll(createShardingConditions(sqlStatementContext, whereSegment.get().getExpr(), parameters));
         }
         Collection<WhereSegment> subqueryWhereSegments = sqlStatementContext.getSqlStatement() instanceof SelectStatement
                 ? WhereSegmentExtractUtils.getSubqueryWhereSegments((SelectStatement) sqlStatementContext.getSqlStatement()) : Collections.emptyList();
         for (WhereSegment each : subqueryWhereSegments) {
-            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getAndPredicates(), parameters);
+            Collection<ShardingCondition> subqueryShardingConditions = createShardingConditions(sqlStatementContext, each.getExpr(), parameters);
             if (!result.containsAll(subqueryShardingConditions)) {
                 result.addAll(subqueryShardingConditions);
             }
         }
         return result;
     }
     
-    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final Collection<AndPredicate> andPredicates, final List<Object> parameters) {
+    private Collection<ShardingCondition> createShardingConditions(final SQLStatementContext sqlStatementContext, final ExpressionSegment expressionSegment, final List<Object> parameters) {
         Collection<ShardingCondition> result = new LinkedList<>();
+    

Review comment:
       Remove




----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] tristaZero commented on a change in pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
tristaZero commented on a change in pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#discussion_r486801178



##########
File path: shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java
##########
@@ -55,37 +60,51 @@ protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStat
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
         Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
-        for (AndPredicate each : ((WhereAvailable) sqlStatementContext).getWhere().get().getAndPredicates()) {
+        Collection<AndPredicate> andPredicates = new LinkedList<>();
+        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
+        ExpressionBuildUtil util = new ExpressionBuildUtil(expression);
+        andPredicates.addAll(util.extractAndPredicates().getAndPredicates());
+        for (AndPredicate each : andPredicates) {
             result.addAll(generateSQLTokens(sqlStatementContext, each));
         }
         return result;
     }
     
     private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
         Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        for (PredicateSegment each : andPredicate.getPredicates()) {
-            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, each);
-            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(each.getColumn().getIdentifier().getValue()).isPresent()) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            ColumnSegment column;
+            if (each instanceof BinaryOperationExpression && ((BinaryOperationExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
+            } else if (each instanceof InExpression && ((InExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((InExpression) each).getLeft();
+            } else if (each instanceof BetweenExpression && ((BetweenExpression) each).getLeft() instanceof ColumnSegment) {
+                column = (ColumnSegment) ((BetweenExpression) each).getLeft();
+            } else {
+                continue;
+            }
+            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column);

Review comment:
       Please extract a function for this one.

##########
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,47 @@ 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())) {

Review comment:
       An expressive name is needed.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setOperator(operator);
+        expression.setRight(new LiteralExpressionSegment(0, 10, 100));
+        expression.setLeft(new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)));
         

Review comment:
       Please remove it.

##########
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 class ExpressionBuildUtil {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java
##########
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.List;
+import java.util.Optional;
 
-/**
- * Predicate segment.
- */
-@RequiredArgsConstructor
 @Getter
-public final class PredicateSegment implements SQLSegment {
+@Setter
+public class JoinTableSegment implements TableSegment {

Review comment:
       Final?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContextTest.java
##########
@@ -47,29 +47,31 @@
     @Mock
     private WhereSegment whereSegment;
     
-    @Mock
-    private AndPredicate andPredicate;
-    
-    @Mock
-    private PredicateSegment predicateSegment;
-    
     @Mock
     private ColumnSegment columnSegment;
     
     @Test
     public void assertNewInstance() {
         when(columnSegment.getOwner()).thenReturn(Optional.of(new OwnerSegment(0, 0, new IdentifierValue("tbl_2"))));
-        when(predicateSegment.getColumn()).thenReturn(columnSegment);
-        when(andPredicate.getPredicates()).thenReturn(Collections.singletonList(predicateSegment));
-        when(whereSegment.getAndPredicates()).thenReturn(Lists.newLinkedList(Arrays.asList(andPredicate)));
-        SimpleTableSegment simpleTableSegment = new SimpleTableSegment(0, 0, new IdentifierValue("tbl_1"));
+        BinaryOperationExpression expression = new BinaryOperationExpression();
+        expression.setLeft(columnSegment);
+        

Review comment:
       A redundant line is needed to remove.

##########
File path: shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java
##########
@@ -56,7 +59,12 @@
         if (!whereSegment.isPresent()) {
             return Optional.empty();
         }
-        for (AndPredicate each : whereSegment.get().getAndPredicates()) {
+    

Review comment:
       Please remove it.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
##########
@@ -133,14 +134,16 @@ private void assertCreatePaginationContextWhenRowNumberAliasPresentAndRowNumberP
     }
     
     private void assertCreatePaginationContextWhenOffsetSegmentInstanceOfNumberLiteralRowNumberValueSegmentWithGivenOperator(final String operator) {
-        PredicateCompareRightValue predicateCompareRightValue = new PredicateCompareRightValue(0, 10, operator, new LiteralExpressionSegment(0, 10, 100));
-        AndPredicate andPredicate = new AndPredicate();
-        andPredicate.getPredicates().add(new PredicateSegment(0, 10, new ColumnSegment(0, 10, new IdentifierValue(ROW_NUMBER_COLUMN_NAME)), predicateCompareRightValue));
         Projection projectionWithRowNumberAlias = new ColumnProjection(null, ROW_NUMBER_COLUMN_NAME, ROW_NUMBER_COLUMN_ALIAS);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.singleton(projectionWithRowNumberAlias));
+    

Review comment:
       Please remove

##########
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,88 @@ 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 {
+                stopIndex = null != ctx.RP_() ? ctx.RP_().getSymbol().getStopIndex() : ctx.tableReference().start.getStopIndex();
+            }
+    

Review comment:
       Please remove it.

##########
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)));

Review comment:
       Please extract a function 

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.segment.dml.item;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+
+import java.util.Optional;
+
+@Setter
+@Getter
+public class BinaryOperationProjection implements ProjectionSegment, AliasAvailable {

Review comment:
       Final ?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/DeleteMultiTableSegment.java
##########
@@ -15,40 +15,35 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.segment.dml;
+package org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 
-import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
 
-@Getter
 @Setter
-public final class JoinedTableSegment implements SQLSegment {
+@Getter
+public class DeleteMultiTableSegment implements TableSegment {

Review comment:
       Fianl?

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
##########
@@ -17,293 +17,191 @@
 
 package org.apache.shardingsphere.sql.parser.sql.common.util;
 
-import com.google.common.base.Preconditions;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinSpecificationSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.JoinedTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableReferenceSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.TableFactorSegment;
+import lombok.Getter;
 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;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.PredicateSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateBetweenRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateCompareRightValue;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.value.PredicateInRightValue;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerAvailable;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
 public final class TableExtractUtils {
+    
+    @Getter
+    private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
+    
+    @Getter
+    private Collection<TableSegment> tableContext = new LinkedList<>();
+    
     /**
-     * Get table that should be rewrited from SelectStatement.
+     * Extract table that should be rewrited from SelectStatement.
      *
      * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
      */
-    public static Collection<SimpleTableSegment> getTablesFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        Collection<TableSegment> allTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            allTables.addAll(getTablesFromTableReference(each));
-            realTables.addAll(getRealTablesFromTableReference(each));
+    public void extractTablesFromSelect(final SelectStatement selectStatement) {
+        if (null != selectStatement.getFrom()) {
+            extractTablesFromTableSegment(selectStatement.getFrom());
         }
         if (selectStatement.getWhere().isPresent()) {
-            allTables.addAll(getAllTablesFromWhere(selectStatement.getWhere().get(), realTables));
+            extractTablesFromExpression(selectStatement.getWhere().get().getExpr());
+        }
+        if (null != selectStatement.getProjections()) {
+            extractTablesFromProjections(selectStatement.getProjections());
         }
-        result.addAll(getAllTablesFromProjections(selectStatement.getProjections(), realTables));
         if (selectStatement.getGroupBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems(), realTables));
+            extractTablesFromOrderByItems(selectStatement.getGroupBy().get().getGroupByItems());
         }
         if (selectStatement.getOrderBy().isPresent()) {
-            result.addAll(getAllTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems(), realTables));
-        }
-        for (TableSegment each : allTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+            extractTablesFromOrderByItems(selectStatement.getOrderBy().get().getOrderByItems());
         }
-        return result;
     }
     
-    /**
-     * Get real table that should be rewrited from SelectStatement.
-     *
-     * @param selectStatement SelectStatement.
-     * @return SimpleTableSegment collection
-     */
-    public static Collection<SimpleTableSegment> getSimpleTableFromSelect(final SelectStatement selectStatement) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        for (TableReferenceSegment each : selectStatement.getTableReferences()) {
-            realTables.addAll(getRealTablesFromTableReference(each));
+    private void extractTablesFromTableSegment(final TableSegment tableSegment) {
+        if (tableSegment instanceof SimpleTableSegment) {
+            tableContext.add(tableSegment);
+            rewriteTables.add((SimpleTableSegment) tableSegment);
         }
-        for (TableSegment each : realTables) {
-            if (each instanceof SubqueryTableSegment) {
-                result.addAll(getSimpleTableFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect()));
-            } else {
-                result.add((SimpleTableSegment) each);
-            }
+        if (tableSegment instanceof SubqueryTableSegment) {
+            tableContext.add(tableSegment);
+            TableExtractUtils utils = new TableExtractUtils();
+            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(utils.getRewriteTables());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
+        if (tableSegment instanceof JoinTableSegment) {
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
+            extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getRight());
+            extractTablesFromExpression(((JoinTableSegment) tableSegment).getCondition());
         }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getTablesFromJoinTable(each, result));
-            }
-        }
-        return result;
     }
     
-    private static Collection<TableSegment> getRealTablesFromTableReference(final TableReferenceSegment tableReferenceSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableReferenceSegment.getTableFactor()) {
-            result.addAll(getRealTablesFromTableFactor(tableReferenceSegment.getTableFactor()));
-        }
-        if (null != tableReferenceSegment.getJoinedTables()) {
-            for (JoinedTableSegment each : tableReferenceSegment.getJoinedTables()) {
-                result.addAll(getRealTablesFromJoinTable(each));
+    private void extractTablesFromExpression(final ExpressionSegment expressionSegment) {
+        if (expressionSegment instanceof ColumnSegment) {
+            if (((ColumnSegment) expressionSegment).getOwner().isPresent() && needRewrite(((ColumnSegment) expressionSegment).getOwner().get())) {
+                OwnerSegment ownerSegment = ((ColumnSegment) expressionSegment).getOwner().get();
+                rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
-        }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getTablesFromTableReference(each));
+        if (expressionSegment instanceof ListExpression) {
+            for (ExpressionSegment each : ((ListExpression) expressionSegment).getItems()) {
+                extractTablesFromExpression(each);
             }
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromTableFactor(final TableFactorSegment tableFactorSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SimpleTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof BetweenExpression) {
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getBetweenExpr());
+            extractTablesFromExpression(((BetweenExpression) expressionSegment).getAndExpr());
         }
-        if (null != tableFactorSegment.getTable() && tableFactorSegment.getTable() instanceof SubqueryTableSegment) {
-            result.add(tableFactorSegment.getTable());
+        if (expressionSegment instanceof InExpression) {
+            extractTablesFromExpression(((InExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((InExpression) expressionSegment).getRight());
         }
-        if (null != tableFactorSegment.getTableReferences() && !tableFactorSegment.getTableReferences().isEmpty()) {
-            for (TableReferenceSegment each: tableFactorSegment.getTableReferences()) {
-                result.addAll(getRealTablesFromTableReference(each));
-            }
+        if (expressionSegment instanceof SubqueryExpressionSegment) {
+            extractTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect());
         }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getTablesFromJoinTable(final JoinedTableSegment joinedTableSegment, final Collection<TableSegment> tableSegments) {
-        Collection<TableSegment> result = new LinkedList<>();
-        Collection<TableSegment> realTables = new LinkedList<>();
-        realTables.addAll(tableSegments);
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-            realTables.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
-        }
-        if (null != joinedTableSegment.getJoinSpecification()) {
-            result.addAll(getTablesFromJoinSpecification(joinedTableSegment.getJoinSpecification(), realTables));
-        }
-        return result;
-    }
-    
-    private static Collection<TableSegment> getRealTablesFromJoinTable(final JoinedTableSegment joinedTableSegment) {
-        Collection<TableSegment> result = new LinkedList<>();
-        if (null != joinedTableSegment.getTableFactor()) {
-            result.addAll(getTablesFromTableFactor(joinedTableSegment.getTableFactor()));
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getLeft());
+            extractTablesFromExpression(((BinaryOperationExpression) expressionSegment).getRight());
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getTablesFromJoinSpecification(final JoinSpecificationSegment joinSpecificationSegment, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        Collection<AndPredicate> andPredicates = joinSpecificationSegment.getAndPredicates();
-        for (AndPredicate each : andPredicates) {
-            for (PredicateSegment e : each.getPredicates()) {
-                if (null != e.getColumn() && (e.getColumn().getOwner().isPresent())) {
-                    OwnerSegment ownerSegment = e.getColumn().getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+    private void extractTablesFromProjections(final ProjectionsSegment projections) {
+        for (ProjectionSegment each : projections.getProjections()) {
+            if (each instanceof SubqueryProjectionSegment) {
+                extractTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+            } else if (each instanceof OwnerAvailable) {
+                if (((OwnerAvailable) each).getOwner().isPresent() && needRewrite(((OwnerAvailable) each).getOwner().get())) {
+                    OwnerSegment ownerSegment = ((OwnerAvailable) each).getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
-                if (null != e.getRightValue() && (e.getRightValue() instanceof ColumnSegment) && ((ColumnSegment) e.getRightValue()).getOwner().isPresent()) {
-                    OwnerSegment ownerSegment = ((ColumnSegment) e.getRightValue()).getOwner().get();
-                    if (isTable(ownerSegment, tableSegments)) {
-                        result.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
-                    }
+            } else if (each instanceof ColumnProjectionSegment) {
+                if (((ColumnProjectionSegment) each).getColumn().getOwner().isPresent() && needRewrite(((ColumnProjectionSegment) each).getColumn().getOwner().get())) {
+                    OwnerSegment ownerSegment = ((ColumnProjectionSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(ownerSegment.getStartIndex(), ownerSegment.getStopIndex(), ownerSegment.getIdentifier()));
                 }
             }
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromWhere(final WhereSegment where, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        for (AndPredicate each : where.getAndPredicates()) {
-            for (PredicateSegment predicate : each.getPredicates()) {
-                result.addAll(getAllTablesFromPredicate(predicate, tableSegments));
-            }
-        }
-        return result;
-    }
-    
-    private static Collection<SimpleTableSegment> getAllTablesFromPredicate(final PredicateSegment predicate, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (predicate.getColumn().getOwner().isPresent() && isTable(predicate.getColumn().getOwner().get(), tableSegments)) {
-            OwnerSegment segment = predicate.getColumn().getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
-        }
-        if (predicate.getRightValue() instanceof PredicateCompareRightValue) {
-            if (((PredicateCompareRightValue) predicate.getRightValue()).getExpression() instanceof SubqueryExpressionSegment) {
-                result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) ((PredicateCompareRightValue) predicate.getRightValue()).getExpression()).getSubquery().getSelect()));
-            }
-        }
-        if (predicate.getRightValue() instanceof PredicateInRightValue) {
-            for (ExpressionSegment expressionSegment : ((PredicateInRightValue) predicate.getRightValue()).getSqlExpressions()) {
-                if (expressionSegment instanceof SubqueryExpressionSegment) {
-                    result.addAll(TableExtractUtils.getTablesFromSelect(((SubqueryExpressionSegment) expressionSegment).getSubquery().getSelect()));
+    private void extractTablesFromOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        for (OrderByItemSegment each : orderByItems) {
+            if (each instanceof ColumnOrderByItemSegment) {
+                Optional<OwnerSegment> owner = ((ColumnOrderByItemSegment) each).getColumn().getOwner();
+                if (owner.isPresent() && needRewrite(owner.get())) {
+                    OwnerSegment segment = ((ColumnOrderByItemSegment) each).getColumn().getOwner().get();
+                    rewriteTables.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
                 }
             }
-        } 
-        if (predicate.getRightValue() instanceof PredicateBetweenRightValue) {
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getBetweenExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));    
-            }
-            if (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression() instanceof SubqueryExpressionSegment) {
-                SelectStatement subquerySelect = ((SubqueryExpressionSegment) (((PredicateBetweenRightValue) predicate.getRightValue()).getAndExpression())).getSubquery().getSelect();
-                result.addAll(TableExtractUtils.getTablesFromSelect(subquerySelect));
-            }
-        } 
-        if (predicate.getRightValue() instanceof ColumnSegment) {
-            Preconditions.checkState(((ColumnSegment) predicate.getRightValue()).getOwner().isPresent());
-            OwnerSegment segment = ((ColumnSegment) predicate.getRightValue()).getOwner().get();
-            result.add(new SimpleTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getIdentifier()));
         }
-        return result;
     }
     
-    private static Collection<SimpleTableSegment> getAllTablesFromProjections(final ProjectionsSegment projections, final Collection<TableSegment> tableSegments) {
-        Collection<SimpleTableSegment> result = new LinkedList<>();
-        if (null == projections || projections.getProjections().isEmpty()) {
-            return result;
-        }
-        for (ProjectionSegment each : projections.getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                result.addAll(getTablesFromSelect(((SubqueryProjectionSegment) each).getSubquery().getSelect()));
-            } else {
-                Optional<SimpleTableSegment> table = getTableSegment(each, tableSegments);
-                table.ifPresent(result::add);
-            }
+    /**
+     * Extract table that should be rewrited from DeleteStatement.
+     *
+     * @param deleteStatement DeleteStatement.
+     */
+    public void extractTablesFromDelete(final DeleteStatement deleteStatement) {
+        

Review comment:
       Remove




----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] coveralls edited a comment on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
coveralls edited a comment on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-689492635


   ## Pull Request Test Coverage Report for [Build 14706](https://coveralls.io/builds/33390998)
   
   * **784** of **1135**   **(69.07%)**  changed or added relevant lines in **44** files are covered.
   * **116** unchanged lines in **28** files lost coverage.
   * Overall coverage increased (+**0.02%**) to **34.151%**
   
   ---
   
   |  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
   | :-----|--------------|--------|---: |
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FEncryptPredicateColumnTokenGenerator.java#L76) | 17 | 18 | 94.44%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-dialect%2Fshardingsphere-sql-parser-mysql%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fmysql%2Fvisitor%2Fimpl%2FMySQLDMLVisitor.java#L585) | 50 | 51 | 98.04%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/AggregateExpression.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FAggregateExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BetweenExpression.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBetweenExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BinaryOperationExpression.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBinaryOperationExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/NotExpression.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FNotExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/predicate/AndPredicate.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fpredicate%2FAndPredicate.java#L37) | 0 | 1 | 0.0%
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L56) | 4 | 6 | 66.67%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ListExpression.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FListExpression.java#L28) | 0 | 2 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/JoinTableSegment.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fgeneric%2Ftable%2FJoinTableSegment.java#L31) | 0 | 2 | 0.0%
   <!-- | **Total:** | **784** | **1135** | **69.07%** | -->
   
   |  Files with Coverage Reduction | New Missed Lines | % |
   | :-----|--------------|--: |
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Fcondition%2FEncryptConditionEngine.java#L136) | 1 | 83.64% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Fcondition%2FShadowConditionEngine.java#L127) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-rewrite/src/main/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FShadowPredicateColumnTokenGenerator.java#L75) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L59) | 1 | 57.14% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/impl/ConditionValueCompareOperatorGenerator.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2Fimpl%2FConditionValueCompareOperatorGenerator.java#L64) | 1 | 90.48% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/impl/ShardingUpdateStatementValidator.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fvalidator%2Fimpl%2FShardingUpdateStatementValidator.java#L125) | 1 | 52.78% |
   | [shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/sctl/hint/ShardingCTLHintBackendHandler.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-proxy%2Fshardingsphere-proxy-backend%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fproxy%2Fbackend%2Ftext%2Fsctl%2Fhint%2FShardingCTLHintBackendHandler.java#L51) | 1 | 90.0% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngine.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FRowNumberPaginationContextEngine.java#L88) | 1 | 85.19% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/TopPaginationContextEngine.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FTopPaginationContextEngine.java#L74) | 1 | 69.7% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/SelectStatementContext.java](https://coveralls.io/builds/33390998/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fstatement%2Fdml%2FSelectStatementContext.java#L102) | 1 | 95.71% |
   <!-- | **Total:** | **116** |  | -->
   
   |  Totals | [![Coverage Status](https://coveralls.io/builds/33390998/badge)](https://coveralls.io/builds/33390998) |
   | :-- | --: |
   | Change from base [Build 14672](https://coveralls.io/builds/33380890): |  0.02% |
   | Covered Lines: | 35564 |
   | Relevant Lines: | 104137 |
   
   ---
   ##### 💛  - [Coveralls](https://coveralls.io)
   


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] jingshanglu commented on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
jingshanglu commented on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-690983807


   @tristaZero The operator is complex, because there are many operator are string, such as `like`,`OPERATOR (anyOperator) ` ,  it is better to combined with the definition of the new segment. mybe it's better to split into separate pr.


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] coveralls edited a comment on pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
coveralls edited a comment on pull request #7353:
URL: https://github.com/apache/shardingsphere/pull/7353#issuecomment-689492635


   ## Pull Request Test Coverage Report for [Build 14675](https://coveralls.io/builds/33381661)
   
   * **790** of **1146**   **(68.94%)**  changed or added relevant lines in **44** files are covered.
   * **96** unchanged lines in **25** files lost coverage.
   * Overall coverage increased (+**0.06%**) to **34.187%**
   
   ---
   
   |  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
   | :-----|--------------|--------|---: |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-dialect%2Fshardingsphere-sql-parser-mysql%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fmysql%2Fvisitor%2Fimpl%2FMySQLDMLVisitor.java#L585) | 50 | 51 | 98.04%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/AggregateExpression.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FAggregateExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BetweenExpression.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBetweenExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/BinaryOperationExpression.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FBinaryOperationExpression.java#L28) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/NotExpression.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FNotExpression.java#L25) | 0 | 1 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/predicate/AndPredicate.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fpredicate%2FAndPredicate.java#L37) | 0 | 1 | 0.0%
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/impl/EncryptPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FEncryptPredicateColumnTokenGenerator.java#L81) | 19 | 21 | 90.48%
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L56) | 4 | 6 | 66.67%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/ListExpression.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fexpr%2FListExpression.java#L28) | 0 | 2 | 0.0%
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/BinaryOperationProjection.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-statement%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fsql%2Fcommon%2Fsegment%2Fdml%2Fitem%2FBinaryOperationProjection.java#L30) | 0 | 2 | 0.0%
   <!-- | **Total:** | **790** | **1146** | **68.94%** | -->
   
   |  Files with Coverage Reduction | New Missed Lines | % |
   | :-----|--------------|--: |
   | [shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-features%2Fshardingsphere-encrypt%2Fshardingsphere-encrypt-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fencrypt%2Frewrite%2Fcondition%2FEncryptConditionEngine.java#L142) | 1 | 81.97% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-common/src/main/java/org/apache/shardingsphere/shadow/condition/ShadowConditionEngine.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Fcondition%2FShadowConditionEngine.java#L131) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-rewrite/src/main/java/org/apache/shardingsphere/shadow/rewrite/token/generator/impl/ShadowPredicateColumnTokenGenerator.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-features%2Fshardingsphere-shadow%2Fshardingsphere-shadow-rewrite%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fshadow%2Frewrite%2Ftoken%2Fgenerator%2Fimpl%2FShadowPredicateColumnTokenGenerator.java#L83) | 1 | 0% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/ConditionValueGeneratorFactory.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2FConditionValueGeneratorFactory.java#L59) | 1 | 57.14% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/generator/impl/ConditionValueCompareOperatorGenerator.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fcondition%2Fgenerator%2Fimpl%2FConditionValueCompareOperatorGenerator.java#L64) | 1 | 90.48% |
   | [shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/impl/ShardingUpdateStatementValidator.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-features%2Fshardingsphere-sharding%2Fshardingsphere-sharding-route%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsharding%2Froute%2Fengine%2Fvalidator%2Fimpl%2FShardingUpdateStatementValidator.java#L125) | 1 | 52.78% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/RowNumberPaginationContextEngine.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FRowNumberPaginationContextEngine.java#L88) | 1 | 85.19% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/pagination/engine/TopPaginationContextEngine.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fsegment%2Fselect%2Fpagination%2Fengine%2FTopPaginationContextEngine.java#L74) | 1 | 69.7% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/SelectStatementContext.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-binder%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fbinder%2Fstatement%2Fdml%2FSelectStatementContext.java#L102) | 1 | 95.71% |
   | [shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/impl/MySQLDMLVisitor.java](https://coveralls.io/builds/33381661/source?filename=shardingsphere-sql-parser%2Fshardingsphere-sql-parser-dialect%2Fshardingsphere-sql-parser-mysql%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fshardingsphere%2Fsql%2Fparser%2Fmysql%2Fvisitor%2Fimpl%2FMySQLDMLVisitor.java#L525) | 1 | 94.83% |
   <!-- | **Total:** | **96** |  | -->
   
   |  Totals | [![Coverage Status](https://coveralls.io/builds/33381661/badge)](https://coveralls.io/builds/33381661) |
   | :-- | --: |
   | Change from base [Build 14672](https://coveralls.io/builds/33380890): |  0.06% |
   | Covered Lines: | 35628 |
   | Relevant Lines: | 104216 |
   
   ---
   ##### 💛  - [Coveralls](https://coveralls.io)
   


----------------------------------------------------------------
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:
users@infra.apache.org



[GitHub] [shardingsphere] tristaZero commented on a change in pull request #7353: Improve the Statement definition

Posted by GitBox <gi...@apache.org>.
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:
users@infra.apache.org