You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ch...@apache.org on 2025/06/11 10:08:40 UTC

(shardingsphere) branch master updated: Support mysql quantify operator parse and upgrade calcite to 1.40.0 (#35675)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 473967dfd07 Support mysql quantify operator parse and upgrade calcite to 1.40.0 (#35675)
473967dfd07 is described below

commit 473967dfd07b27afe580d0bdb0c338aedd74a3ad
Author: Zhengqiang Duan <du...@apache.org>
AuthorDate: Wed Jun 11 18:08:35 2025 +0800

    Support mysql quantify operator parse and upgrade calcite to 1.40.0 (#35675)
    
    * Support mysql quantify operator parse and upgrade calcite to 1.40.0
    
    * update license and release note
    
    * fix checkstyle
    
    * fix parse it
    
    * fix sql federation it
---
 RELEASE-NOTES.md                                   |  1 +
 distribution/proxy/src/main/release-docs/LICENSE   |  4 +-
 .../dml/expression/ExpressionSegmentBinder.java    |  5 ++
 .../expression/type/OuterJoinExpressionBinder.java |  2 +-
 ....java => QuantifySubqueryExpressionBinder.java} | 25 ++++----
 .../compiler/compiler/SQLStatementCompiler.java    | 19 ++++---
 .../builder/SQLFederationPlannerBuilder.java       |  2 +-
 .../transformation/PushFilterIntoScanRule.java     | 19 +++++++
 .../transformation/PushProjectIntoScanRule.java    |  3 +-
 .../rel/converter/SQLFederationRelConverter.java   |  2 +-
 .../rel/rewriter/LogicalScanRelRewriter.java       |  6 +-
 .../segment/expression/ExpressionConverter.java    | 11 +++-
 .../impl/BinaryOperationExpressionConverter.java   | 66 ++++++++++++++++------
 .../impl/QuantifySubqueryExpressionConverter.java  | 43 ++++++++++++++
 .../resources/cases/federation-query-sql-cases.xml |  8 +--
 .../visitor/statement/MySQLStatementVisitor.java   | 16 +++++-
 .../statement/core/extractor/TableExtractor.java   |  4 ++
 .../dml/expr/QuantifySubqueryExpression.java       | 43 ++++++++++++++
 pom.xml                                            |  2 +-
 .../segment/expression/ExpressionAssert.java       | 14 +++++
 .../jaxb/segment/impl/expr/ExpectedExpression.java |  3 +
 .../expr/ExpectedQuantifySubqueryExpression.java   | 39 +++++++++++++
 .../main/resources/case/dml/select-expression.xml  | 51 +++++++++--------
 23 files changed, 308 insertions(+), 80 deletions(-)

diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 7371dc54191..aaef113477e 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -45,6 +45,7 @@
 1. Encrypt: Use EncryptDerivedColumnSuffix to enhance encrypt table subquery rewrite logic - [#34829](https://github.com/apache/shardingsphere/pull/34829)
 1. Encrypt: Add quotes to encrypt rewrite derived columns - [#34950](https://github.com/apache/shardingsphere/pull/34950)
 1. SQL Router: Improve support for executing tableless SQL with single data source - [#35659](https://github.com/apache/shardingsphere/pull/35659)
+1. SQL Parser: Support mysql quantify operator parse and upgrade calcite to 1.40.0 - [#35675](https://github.com/apache/shardingsphere/pull/35675)
 
 ### Bug Fixes
 
diff --git a/distribution/proxy/src/main/release-docs/LICENSE b/distribution/proxy/src/main/release-docs/LICENSE
index 0c69969089f..84b892828fa 100644
--- a/distribution/proxy/src/main/release-docs/LICENSE
+++ b/distribution/proxy/src/main/release-docs/LICENSE
@@ -222,8 +222,8 @@ The text of each license is the standard Apache 2.0 license.
     avatica-core 1.26.0: https://calcite.apache.org/avatica, Apache 2.0
     avatica-metrics 1.26.0: https://calcite.apache.org/avatica, Apache 2.0
     caffeine 2.9.3: https://github.com/ben-manes/caffeine, Apache 2.0
-    calcite-core 1.39.0: https://calcite.apache.org, Apache 2.0
-    calcite-linq4j 1.39.0: https://calcite.apache.org, Apache 2.0
+    calcite-core 1.40.0: https://calcite.apache.org, Apache 2.0
+    calcite-linq4j 1.40.0: https://calcite.apache.org, Apache 2.0
     commons-codec 1.16.0: https://github.com/apache/commons-codec, Apache 2.0
     commons-dbcp2 2.11.0: https://commons.apache.org/proper/commons-dbcp, Apache 2.0
     commons-exec 1.3: https://github.com/apache/commons-exec, Apache 2.0
diff --git a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/ExpressionSegmentBinder.java b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/ExpressionSegmentBinder.java
index 1a47b2ba240..d81bfcdb47e 100644
--- a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/ExpressionSegmentBinder.java
+++ b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/ExpressionSegmentBinder.java
@@ -34,6 +34,7 @@ import org.apache.shardingsphere.infra.binder.engine.segment.dml.expression.type
 import org.apache.shardingsphere.infra.binder.engine.segment.dml.expression.type.InExpressionBinder;
 import org.apache.shardingsphere.infra.binder.engine.segment.dml.expression.type.NotExpressionBinder;
 import org.apache.shardingsphere.infra.binder.engine.segment.dml.expression.type.OuterJoinExpressionBinder;
+import org.apache.shardingsphere.infra.binder.engine.segment.dml.expression.type.QuantifySubqueryExpressionBinder;
 import org.apache.shardingsphere.infra.binder.engine.segment.dml.expression.type.SubquerySegmentBinder;
 import org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.TableSegmentBinderContext;
 import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
@@ -46,6 +47,7 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.Expr
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.FunctionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.InExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.QuantifySubqueryExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.AggregationDistinctProjectionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.AggregationProjectionSegment;
@@ -109,6 +111,9 @@ public final class ExpressionSegmentBinder {
         if (segment instanceof OuterJoinExpression) {
             return OuterJoinExpressionBinder.bind((OuterJoinExpression) segment, parentSegmentType, binderContext, tableBinderContexts, outerTableBinderContexts);
         }
+        if (segment instanceof QuantifySubqueryExpression) {
+            return QuantifySubqueryExpressionBinder.bind((QuantifySubqueryExpression) segment, binderContext, tableBinderContexts);
+        }
         // TODO support more ExpressionSegment bound
         return segment;
     }
diff --git a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/OuterJoinExpressionBinder.java b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/OuterJoinExpressionBinder.java
index 06eda64bb82..268842ce9ad 100644
--- a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/OuterJoinExpressionBinder.java
+++ b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/OuterJoinExpressionBinder.java
@@ -41,7 +41,7 @@ public final class OuterJoinExpressionBinder {
      * @param binderContext SQL statement binder context
      * @param tableBinderContexts table binder contexts
      * @param outerTableBinderContexts outer table binder contexts
-     * @return bound case when expression
+     * @return bound outer join expression
      */
     public static OuterJoinExpression bind(final OuterJoinExpression segment, final SegmentType parentSegmentType,
                                            final SQLStatementBinderContext binderContext, final Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts,
diff --git a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/OuterJoinExpressionBinder.java b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/QuantifySubqueryExpressionBinder.java
similarity index 54%
copy from infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/OuterJoinExpressionBinder.java
copy to infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/QuantifySubqueryExpressionBinder.java
index 06eda64bb82..bfb192efb0f 100644
--- a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/OuterJoinExpressionBinder.java
+++ b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/QuantifySubqueryExpressionBinder.java
@@ -21,32 +21,27 @@ import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString;
 import com.google.common.collect.Multimap;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType;
 import org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.TableSegmentBinderContext;
 import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.join.OuterJoinExpression;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.QuantifySubqueryExpression;
 
 /**
- * Outer join expression binder.
+ * Quantify subquery expression binder.
  */
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class OuterJoinExpressionBinder {
+public final class QuantifySubqueryExpressionBinder {
     
     /**
-     * Bind outer join expression.
+     * Bind quantify subquery expression.
      *
-     * @param segment outer join expression segment
-     * @param parentSegmentType parent segment type
+     * @param segment quantify subquery expression
      * @param binderContext SQL statement binder context
      * @param tableBinderContexts table binder contexts
-     * @param outerTableBinderContexts outer table binder contexts
-     * @return bound case when expression
+     * @return bound quantify subquery expression
      */
-    public static OuterJoinExpression bind(final OuterJoinExpression segment, final SegmentType parentSegmentType,
-                                           final SQLStatementBinderContext binderContext, final Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts,
-                                           final Multimap<CaseInsensitiveString, TableSegmentBinderContext> outerTableBinderContexts) {
-        ColumnSegment boundColumnName = ColumnSegmentBinder.bind(segment.getColumnName(), parentSegmentType, binderContext, tableBinderContexts, outerTableBinderContexts);
-        return new OuterJoinExpression(segment.getStartIndex(), segment.getStopIndex(), boundColumnName, segment.getJoinOperator(), segment.getText());
+    public static QuantifySubqueryExpression bind(final QuantifySubqueryExpression segment, final SQLStatementBinderContext binderContext,
+                                                  final Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts) {
+        return new QuantifySubqueryExpression(segment.getStartIndex(), segment.getStopIndex(), SubquerySegmentBinder.bind(segment.getSubquery(), binderContext, tableBinderContexts),
+                segment.getQuantifyOperator());
     }
 }
diff --git a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/compiler/SQLStatementCompiler.java b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/compiler/SQLStatementCompiler.java
index 1c055adfb84..d9f2ea77860 100644
--- a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/compiler/SQLStatementCompiler.java
+++ b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/compiler/SQLStatementCompiler.java
@@ -54,26 +54,31 @@ public final class SQLStatementCompiler {
         SqlNode sqlNode = SQLNodeConverterEngine.convert(sqlStatement);
         RelNode logicalPlan = converter.convertQuery(sqlNode, true, true).rel;
         RelDataType resultColumnType = converter.getValidatedNodeType(sqlNode);
-        RelNode rewritePlan = rewrite(logicalPlan, databaseType);
-        RelNode physicalPlan = optimize(rewritePlan, converter);
+        RelNode rewrittenPlan = rewrite(logicalPlan, databaseType);
+        RelNode physicalPlan = optimize(rewrittenPlan, converter, databaseType);
         RelMetadataQueryBase.THREAD_PROVIDERS.remove();
         return new SQLFederationExecutionPlan(physicalPlan, resultColumnType);
     }
     
     private RelNode rewrite(final RelNode logicalPlan, final String databaseType) {
-        RelNode rewrittenPlan = LogicalScanRelRewriter.rewrite(logicalPlan, databaseType);
+        RelNode rewrittenPlan = rewriteTableScan(logicalPlan, databaseType);
         RelOptPlanner hepPlanner = SQLFederationPlannerBuilder.buildHepPlanner();
         hepPlanner.setRoot(rewrittenPlan);
         return hepPlanner.findBestExp();
     }
     
-    private RelNode optimize(final RelNode rewritePlan, final SQLFederationRelConverter converter) {
+    private RelNode optimize(final RelNode logicalPlan, final SQLFederationRelConverter converter, final String databaseType) {
+        RelNode rewrittenPlan = rewriteTableScan(logicalPlan, databaseType);
         RelOptPlanner planner = converter.getCluster().getPlanner();
-        if (rewritePlan.getTraitSet().contains(convention)) {
-            planner.setRoot(rewritePlan);
+        if (rewrittenPlan.getTraitSet().contains(convention)) {
+            planner.setRoot(rewrittenPlan);
         } else {
-            planner.setRoot(planner.changeTraits(rewritePlan, converter.getCluster().traitSet().replace(convention)));
+            planner.setRoot(planner.changeTraits(rewrittenPlan, converter.getCluster().traitSet().replace(convention)));
         }
         return planner.findBestExp();
     }
+    
+    private RelNode rewriteTableScan(final RelNode logicalPlan, final String databaseType) {
+        return LogicalScanRelRewriter.rewrite(logicalPlan, databaseType);
+    }
 }
diff --git a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/builder/SQLFederationPlannerBuilder.java b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/builder/SQLFederationPlannerBuilder.java
index df511483019..a9d33e3ec39 100644
--- a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/builder/SQLFederationPlannerBuilder.java
+++ b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/builder/SQLFederationPlannerBuilder.java
@@ -105,9 +105,9 @@ public final class SQLFederationPlannerBuilder {
         builder.addGroupBegin().addRuleCollection(getFilterRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
         builder.addGroupBegin().addRuleCollection(getProjectRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
         builder.addGroupBegin().addRuleCollection(getAggregationRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
-        builder.addGroupBegin().addRuleCollection(getCalcRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
         builder.addGroupBegin().addRuleCollection(getSubQueryRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
         builder.addGroupBegin().addRuleCollection(getSortRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
+        builder.addGroupBegin().addRuleCollection(getCalcRules()).addGroupEnd().addMatchOrder(HepMatchOrder.BOTTOM_UP);
         builder.addMatchLimit(DEFAULT_MATCH_LIMIT);
         return new HepPlanner(builder.build());
     }
diff --git a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/rule/transformation/PushFilterIntoScanRule.java b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/rule/transformation/PushFilterIntoScanRule.java
index 8ad028f0434..da08cbb7f81 100644
--- a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/rule/transformation/PushFilterIntoScanRule.java
+++ b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/rule/transformation/PushFilterIntoScanRule.java
@@ -24,6 +24,7 @@ import org.apache.calcite.rel.logical.LogicalFilter;
 import org.apache.calcite.rel.rules.TransformationRule;
 import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexSubQuery;
 import org.apache.shardingsphere.sqlfederation.compiler.rel.operator.logical.LogicalScan;
 import org.immutables.value.Value;
 
@@ -54,9 +55,27 @@ public final class PushFilterIntoScanRule extends RelRule<PushFilterIntoScanRule
         }
         LogicalFilter logicalFilter = call.rel(0);
         RexNode condition = logicalFilter.getCondition();
+        if (isConditionContainsRexSubQuery(condition)) {
+            return false;
+        }
         return !(condition instanceof RexCall) || !containsCorrelate(((RexCall) condition).getOperands());
     }
     
+    private boolean isConditionContainsRexSubQuery(final RexNode condition) {
+        if (condition instanceof RexSubQuery) {
+            return true;
+        }
+        if (!(condition instanceof RexCall)) {
+            return false;
+        }
+        for (RexNode each : ((RexCall) condition).getOperands()) {
+            if (each instanceof RexSubQuery) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
     private boolean containsCorrelate(final Collection<RexNode> operands) {
         for (RexNode each : operands) {
             if (each.toString().contains(CORRELATE_REFERENCE)) {
diff --git a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/rule/transformation/PushProjectIntoScanRule.java b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/rule/transformation/PushProjectIntoScanRule.java
index 18c68ca6115..614c4fb20ea 100644
--- a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/rule/transformation/PushProjectIntoScanRule.java
+++ b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/planner/rule/transformation/PushProjectIntoScanRule.java
@@ -24,6 +24,7 @@ import org.apache.calcite.rel.logical.LogicalProject;
 import org.apache.calcite.rel.rules.TransformationRule;
 import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexSubQuery;
 import org.apache.shardingsphere.sqlfederation.compiler.rel.operator.logical.LogicalScan;
 import org.immutables.value.Value;
 
@@ -54,7 +55,7 @@ public final class PushProjectIntoScanRule extends RelRule<PushProjectIntoScanRu
         }
         LogicalProject logicalProject = call.rel(0);
         for (RexNode each : logicalProject.getProjects()) {
-            if (containsCastFunction(each)) {
+            if (each instanceof RexSubQuery || containsCastFunction(each)) {
                 return false;
             }
         }
diff --git a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/rel/converter/SQLFederationRelConverter.java b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/rel/converter/SQLFederationRelConverter.java
index 6b538cff433..8aa4a6dd999 100644
--- a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/rel/converter/SQLFederationRelConverter.java
+++ b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/rel/converter/SQLFederationRelConverter.java
@@ -98,7 +98,7 @@ public final class SQLFederationRelConverter {
                 ? new ShardingSphereViewExpander(sqlParserRule, databaseType, createSqlToRelConverter(catalogReader, validator, cluster, sqlParserRule, databaseType, false))
                 : (rowType, queryString, schemaPath, viewPath) -> null;
         // TODO remove withRemoveSortInSubQuery when calcite can expand view which contains order by correctly
-        Config converterConfig = SqlToRelConverter.config().withTrimUnusedFields(true).withRemoveSortInSubQuery(false).withExpand(true);
+        Config converterConfig = SqlToRelConverter.config().withTrimUnusedFields(true).withRemoveSortInSubQuery(false);
         return new SqlToRelConverter(expander, validator, catalogReader, cluster, StandardConvertletTable.INSTANCE, converterConfig);
     }
     
diff --git a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/rel/rewriter/LogicalScanRelRewriter.java b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/rel/rewriter/LogicalScanRelRewriter.java
index f47f80b2908..8c04ad36e36 100644
--- a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/rel/rewriter/LogicalScanRelRewriter.java
+++ b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/rel/rewriter/LogicalScanRelRewriter.java
@@ -22,6 +22,7 @@ import lombok.RequiredArgsConstructor;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelShuttleImpl;
 import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.logical.LogicalTableScan;
 import org.apache.shardingsphere.sqlfederation.compiler.rel.operator.logical.LogicalScan;
 
 /**
@@ -34,7 +35,10 @@ public final class LogicalScanRelRewriter extends RelShuttleImpl {
     
     @Override
     public RelNode visit(final TableScan tableScan) {
-        return new LogicalScan(tableScan, databaseType);
+        if (tableScan instanceof LogicalTableScan) {
+            return new LogicalScan(tableScan, databaseType);
+        }
+        return tableScan;
     }
     
     /**
diff --git a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/ExpressionConverter.java b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/ExpressionConverter.java
index 19a37bce9bb..59cb8451573 100644
--- a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/ExpressionConverter.java
+++ b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/ExpressionConverter.java
@@ -35,6 +35,7 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.InEx
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.IntervalExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.QuantifySubqueryExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.RowExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.TypeCastExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.UnaryOperationExpression;
@@ -50,7 +51,9 @@ import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segmen
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.CaseWhenExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.CollateExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.ColumnConverter;
+import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.ExistsSubqueryExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.ExtractArgExpressionConverter;
+import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.FunctionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.InExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.IntervalExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.ListExpressionConverter;
@@ -58,13 +61,12 @@ import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segmen
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.MatchExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.NotExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.ParameterMarkerExpressionConverter;
+import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.QuantifySubqueryExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.RowExpressionConverter;
+import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.SubqueryExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.TypeCastExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.UnaryOperationExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.VariableSegmentConverter;
-import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.ExistsSubqueryExpressionConverter;
-import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.FunctionConverter;
-import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.impl.SubqueryExpressionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.projection.impl.AggregationProjectionConverter;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.projection.impl.DataTypeConverter;
 
@@ -157,6 +159,9 @@ public final class ExpressionConverter {
         if (segment instanceof IntervalExpression) {
             return IntervalExpressionConverter.convert((IntervalExpression) segment);
         }
+        if (segment instanceof QuantifySubqueryExpression) {
+            return QuantifySubqueryExpressionConverter.convert((QuantifySubqueryExpression) segment);
+        }
         throw new UnsupportedSQLOperationException("unsupported TableSegment type: " + segment.getClass());
     }
 }
diff --git a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/BinaryOperationExpressionConverter.java b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/BinaryOperationExpressionConverter.java
index 8a2793f1d97..d3543529340 100644
--- a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/BinaryOperationExpressionConverter.java
+++ b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/BinaryOperationExpressionConverter.java
@@ -30,6 +30,7 @@ import org.apache.calcite.sql.SqlOperator;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.QuantifySubqueryExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.operator.common.SQLExtensionOperatorTable;
 import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.ExpressionConverter;
@@ -79,6 +80,7 @@ public final class BinaryOperationExpressionConverter {
         register(SqlStdOperatorTable.CONCAT);
         register(SqlStdOperatorTable.PATTERN_ALTER);
         register(SqlStdOperatorTable.MOD);
+        SqlStdOperatorTable.QUANTIFY_OPERATORS.forEach(BinaryOperationExpressionConverter::register);
         register(SQLExtensionOperatorTable.DIV);
         register(SQLExtensionOperatorTable.CARET);
         register(SQLExtensionOperatorTable.AMPERSAND);
@@ -119,27 +121,57 @@ public final class BinaryOperationExpressionConverter {
     }
     
     private static SqlOperator convertOperator(final BinaryOperationExpression segment) {
-        String operator = segment.getOperator();
-        if ("IS".equalsIgnoreCase(operator)) {
-            String literals = String.valueOf(((LiteralExpressionSegment) segment.getRight()).getLiterals());
-            if ("NULL".equalsIgnoreCase(literals)) {
-                operator = "IS NULL";
-            } else if ("NOT NULL".equalsIgnoreCase(literals)) {
-                operator = "IS NOT NULL";
-            } else if ("FALSE".equalsIgnoreCase(literals)) {
-                operator = "IS FALSE";
-            } else if ("NOT FALSE".equalsIgnoreCase(literals)) {
-                operator = "IS NOT FALSE";
-            } else if ("TRUE".equalsIgnoreCase(literals)) {
-                operator = "IS TRUE";
-            } else if ("NOT TRUE".equalsIgnoreCase(literals)) {
-                operator = "IS NOT TRUE";
-            }
-        }
+        String operator = getOperator(segment);
         Preconditions.checkState(REGISTRY.containsKey(operator), "Unsupported SQL operator: `%s`", operator);
         return REGISTRY.get(operator);
     }
     
+    private static String getOperator(final BinaryOperationExpression segment) {
+        String result = null;
+        if ("IS".equalsIgnoreCase(segment.getOperator())) {
+            result = findIsOperator(segment).orElse(null);
+        }
+        if (segment.getRight() instanceof QuantifySubqueryExpression) {
+            result = findQuantifyOperator(segment.getOperator(), (QuantifySubqueryExpression) segment.getRight()).orElse(null);
+        }
+        return null == result ? segment.getOperator() : result;
+    }
+    
+    private static Optional<String> findIsOperator(final BinaryOperationExpression segment) {
+        String literals = String.valueOf(((LiteralExpressionSegment) segment.getRight()).getLiterals());
+        if ("NULL".equalsIgnoreCase(literals)) {
+            return Optional.of(SqlStdOperatorTable.IS_NULL.getName());
+        } else if ("NOT NULL".equalsIgnoreCase(literals)) {
+            return Optional.of(SqlStdOperatorTable.IS_NOT_NULL.getName());
+        } else if ("FALSE".equalsIgnoreCase(literals)) {
+            return Optional.of(SqlStdOperatorTable.IS_FALSE.getName());
+        } else if ("NOT FALSE".equalsIgnoreCase(literals)) {
+            return Optional.of(SqlStdOperatorTable.IS_NOT_FALSE.getName());
+        } else if ("TRUE".equalsIgnoreCase(literals)) {
+            return Optional.of(SqlStdOperatorTable.IS_TRUE.getName());
+        } else if ("NOT TRUE".equalsIgnoreCase(literals)) {
+            return Optional.of(SqlStdOperatorTable.IS_NOT_TRUE.getName());
+        }
+        return Optional.empty();
+    }
+    
+    private static Optional<String> findQuantifyOperator(final String operator, final QuantifySubqueryExpression quantifySubquery) {
+        if ("=".equals(operator)) {
+            return "ALL".equalsIgnoreCase(quantifySubquery.getQuantifyOperator()) ? Optional.of(SqlStdOperatorTable.ALL_EQ.getName()) : Optional.of(SqlStdOperatorTable.SOME_EQ.getName());
+        } else if (">".equals(operator)) {
+            return "ALL".equalsIgnoreCase(quantifySubquery.getQuantifyOperator()) ? Optional.of(SqlStdOperatorTable.ALL_GT.getName()) : Optional.of(SqlStdOperatorTable.SOME_GT.getName());
+        } else if (">=".equals(operator)) {
+            return "ALL".equalsIgnoreCase(quantifySubquery.getQuantifyOperator()) ? Optional.of(SqlStdOperatorTable.ALL_GE.getName()) : Optional.of(SqlStdOperatorTable.SOME_GE.getName());
+        } else if ("<".equals(operator)) {
+            return "ALL".equalsIgnoreCase(quantifySubquery.getQuantifyOperator()) ? Optional.of(SqlStdOperatorTable.ALL_LT.getName()) : Optional.of(SqlStdOperatorTable.SOME_LT.getName());
+        } else if ("<=".equals(operator)) {
+            return "ALL".equalsIgnoreCase(quantifySubquery.getQuantifyOperator()) ? Optional.of(SqlStdOperatorTable.ALL_LE.getName()) : Optional.of(SqlStdOperatorTable.SOME_LE.getName());
+        } else if ("!=".equals(operator) || "<>".equals(operator)) {
+            return "ALL".equalsIgnoreCase(quantifySubquery.getQuantifyOperator()) ? Optional.of(SqlStdOperatorTable.ALL_NE.getName()) : Optional.of(SqlStdOperatorTable.SOME_NE.getName());
+        }
+        return Optional.empty();
+    }
+    
     private static List<SqlNode> convertSqlNodes(final BinaryOperationExpression segment, final SqlOperator operator) {
         SqlNode left = ExpressionConverter.convert(segment.getLeft()).orElseThrow(IllegalStateException::new);
         List<SqlNode> result = new LinkedList<>();
diff --git a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/QuantifySubqueryExpressionConverter.java b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/QuantifySubqueryExpressionConverter.java
new file mode 100644
index 00000000000..d78dd3cb454
--- /dev/null
+++ b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/expression/impl/QuantifySubqueryExpressionConverter.java
@@ -0,0 +1,43 @@
+/*
+ * 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.sqlfederation.compiler.sql.ast.converter.segment.expression.impl;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.QuantifySubqueryExpression;
+import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.statement.select.SelectStatementConverter;
+
+import java.util.Optional;
+
+/**
+ * Quantify subquery expression converter.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class QuantifySubqueryExpressionConverter {
+    
+    /**
+     * Convert quantify subquery expression to sql node.
+     *
+     * @param expression quantify subquery expression
+     * @return sql node
+     */
+    public static Optional<SqlNode> convert(final QuantifySubqueryExpression expression) {
+        return null == expression ? Optional.empty() : Optional.of(new SelectStatementConverter().convert(expression.getSubquery().getSelect()));
+    }
+}
diff --git a/kernel/sql-federation/compiler/src/test/resources/cases/federation-query-sql-cases.xml b/kernel/sql-federation/compiler/src/test/resources/cases/federation-query-sql-cases.xml
index 58542f2ca53..4a2520d521b 100644
--- a/kernel/sql-federation/compiler/src/test/resources/cases/federation-query-sql-cases.xml
+++ b/kernel/sql-federation/compiler/src/test/resources/cases/federation-query-sql-cases.xml
@@ -46,15 +46,15 @@
     </test-case>
     
     <test-case sql="SELECT t_order_federate.order_id, t_order_federate.user_id FROM t_order_federate WHERE EXISTS (SELECT * FROM t_user_info WHERE t_order_federate.user_id = t_user_info.user_id)">
-        <assertion expected-result="EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NOT NULL($t3)], proj#0..1=[{exprs}], $condition=[$t4])   EnumerableCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{1}])     EnumerableScan(table=[[federate_jdbc, t_order_federate]], sql=[SELECT * FROM `federate_jdbc`.`t_order_federate`], dynamicParameters=[null])     EnumerableAggregate(group=[{}], agg#0=[MIN($0)])       EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], expr#3=[$cor0], [...]
+        <assertion expected-result="EnumerableCalc(expr#0..3=[{inputs}], proj#0..1=[{exprs}])   EnumerableCorrelate(correlation=[$cor0], joinType=[inner], requiredColumns=[{1}])     EnumerableScan(table=[[federate_jdbc, t_order_federate]], sql=[SELECT * FROM &#x60;federate_jdbc&#x60;.&#x60;t_order_federate&#x60;], dynamicParameters=[null])     EnumerableAggregate(group=[{0}])       EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], expr#3=[$cor0], expr#4=[$t3.user_id], expr#5=[CAST($t4) [...]
     </test-case>
     
     <test-case sql="SELECT t_order_federate.order_id, t_order_federate.user_id FROM t_order_federate WHERE t_order_federate.user_id IN (SELECT t_user_info.user_id FROM t_user_info)">
-        <assertion expected-result="EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])   EnumerableHashJoin(condition=[=($1, $2)], joinType=[inner])     EnumerableScan(table=[[federate_jdbc, t_order_federate]], sql=[SELECT `order_id`, `user_id` FROM `federate_jdbc`.`t_order_federate`], dynamicParameters=[null])     EnumerableAggregate(group=[{0}])       EnumerableScan(table=[[federate_jdbc, t_user_info]], sql=[SELECT `user_id` FROM `federate_jdbc`.`t_user_info`], dynamicParameters [...]
+        <assertion expected-result="EnumerableCalc(expr#0..3=[{inputs}], proj#0..1=[{exprs}])   EnumerableHashJoin(condition=[=($1, $3)], joinType=[inner])     EnumerableScan(table=[[federate_jdbc, t_order_federate]], sql=[SELECT * FROM &#x60;federate_jdbc&#x60;.&#x60;t_order_federate&#x60;], dynamicParameters=[null])     EnumerableAggregate(group=[{0}])       EnumerableCalc(expr#0..1=[{inputs}], user_id=[$t0])         EnumerableScan(table=[[federate_jdbc, t_user_info]], sql=[SELECT * FR [...]
     </test-case>
     
     <test-case sql="SELECT t_order_federate.order_id, t_order_federate.user_id FROM t_order_federate WHERE user_id BETWEEN (SELECT user_id FROM t_user_info WHERE user_id = 1) AND (SELECT user_id FROM t_user_info WHERE user_id = 3)">
-        <assertion expected-result="EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])   EnumerableNestedLoopJoin(condition=[&lt;=($1, $2)], joinType=[inner])     EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])       EnumerableNestedLoopJoin(condition=[>=($1, $2)], joinType=[inner])         EnumerableScan(table=[[federate_jdbc, t_order_federate]], sql=[SELECT `order_id`, `user_id` FROM `federate_jdbc`.`t_order_federate`], dynamicParameters=[null])         EnumerableAggre [...]
+        <assertion expected-result="EnumerableScan(table=[[federate_jdbc, t_order_federate]], sql=[SELECT &#x60;order_id&#x60;, &#x60;user_id&#x60; FROM &#x60;federate_jdbc&#x60;.&#x60;t_order_federate&#x60; WHERE &#x60;user_id&#x60; &gt;= (((SELECT &#x60;user_id&#x60; FROM &#x60;federate_jdbc&#x60;.&#x60;t_user_info&#x60; WHERE &#x60;user_id&#x60; = 1))) AND &#x60;user_id&#x60; &lt;= (((SELECT &#x60;user_id&#x60; FROM &#x60;federate_jdbc&#x60;.&#x60;t_user_info&#x60; WHERE &#x60;user_id [...]
     </test-case>
     
     <test-case sql="SELECT order_id, user_id FROM t_order_federate UNION SELECT 1, user_id FROM t_user_info WHERE information = 'before'">
@@ -386,7 +386,7 @@
     </test-case>
     
     <test-case sql="SELECT * FROM t_order o WHERE o.order_id IN (SELECT i.order_id FROM t_order_item i INNER JOIN t_product p ON i.product_id = p.product_id WHERE p.product_id = 10) ORDER BY order_id">
-        <assertion expected-result="EnumerableSort(sort0=[$0], dir0=[ASC])   EnumerableCalc(expr#0..6=[{inputs}], proj#0..5=[{exprs}])     EnumerableHashJoin(condition=[=($0, $6)], joinType=[inner])       EnumerableScan(table=[[federate_jdbc, t_order]], sql=[SELECT * FROM `federate_jdbc`.`t_order`], dynamicParameters=[null])       EnumerableAggregate(group=[{0}])         EnumerableCalc(expr#0..2=[{inputs}], order_id=[$t0])           EnumerableHashJoin(condition=[=($1, $2)], joinType=[inn [...]
+        <assertion expected-result="EnumerableSort(sort0=[$0], dir0=[ASC])   EnumerableCalc(expr#0..6=[{inputs}], proj#0..5=[{exprs}])     EnumerableHashJoin(condition=[=($0, $6)], joinType=[inner])       EnumerableScan(table=[[federate_jdbc, t_order]], sql=[SELECT * FROM &#x60;federate_jdbc&#x60;.&#x60;t_order&#x60;], dynamicParameters=[null])       EnumerableAggregate(group=[{0}])         EnumerableCalc(expr#0..11=[{inputs}], expr#12=[CAST($t6):INTEGER], expr#13=[10], expr#14=[=($t12,  [...]
     </test-case>
     
     <test-case sql="SELECT MAX(p.price) AS max_price, MIN(p.price) AS min_price, SUM(p.price) AS sum_price, AVG(p.price) AS avg_price, COUNT(1) AS count FROM t_order o INNER JOIN t_order_item i ON o.order_id = i.order_id INNER JOIN t_product p ON i.product_id = p.product_id GROUP BY o.order_id HAVING SUM(p.price) &gt; 10 ORDER BY max_price">
diff --git a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
index bac6c709dfe..4f7ee200b00 100644
--- a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
+++ b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
@@ -183,6 +183,7 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.Inte
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.IntervalUnit;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.QuantifySubqueryExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.RowExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.UnaryOperationExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ValuesExpression;
@@ -506,14 +507,25 @@ public abstract class MySQLStatementVisitor extends MySQLStatementBaseVisitor<AS
         if (null != ctx.predicate()) {
             right = (ExpressionSegment) visit(ctx.predicate());
         } else {
-            right = new SubqueryExpressionSegment(
-                    new SubquerySegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), (SelectStatement) visit(ctx.subquery()), getOriginalText(ctx.subquery())));
+            right = createRightExpression(ctx);
         }
         String operator = null == ctx.SAFE_EQ_() ? ctx.comparisonOperator().getText() : ctx.SAFE_EQ_().getText();
         String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
         return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
     }
     
+    private ExpressionSegment createRightExpression(final BooleanPrimaryContext ctx) {
+        SubqueryExpressionSegment result = new SubqueryExpressionSegment(
+                new SubquerySegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), (SelectStatement) visit(ctx.subquery()), getOriginalText(ctx.subquery())));
+        if (null != ctx.ANY() || null != ctx.ALL()) {
+            int startIndex = null == ctx.ANY() ? ctx.ALL().getSymbol().getStartIndex() : ctx.ANY().getSymbol().getStartIndex();
+            String quantifyOperator = null == ctx.ANY() ? ctx.ALL().getText() : ctx.ANY().getText();
+            return new QuantifySubqueryExpression(startIndex, result.getStopIndex(), result.getSubquery(), quantifyOperator);
+        } else {
+            return result;
+        }
+    }
+    
     @Override
     public final ASTNode visitPredicate(final PredicateContext ctx) {
         if (null != ctx.IN()) {
diff --git a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/extractor/TableExtractor.java b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/extractor/TableExtractor.java
index 310f2238af6..60227c13f87 100644
--- a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/extractor/TableExtractor.java
+++ b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/extractor/TableExtractor.java
@@ -34,6 +34,7 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.Func
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.InExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.QuantifySubqueryExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.TypeCastExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonTableExpressionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubqueryExpressionSegment;
@@ -193,6 +194,9 @@ public final class TableExtractor {
         if (expressionSegment instanceof TypeCastExpression) {
             extractTablesFromExpression(((TypeCastExpression) expressionSegment).getExpression());
         }
+        if (expressionSegment instanceof QuantifySubqueryExpression) {
+            extractTablesFromExpression(((QuantifySubqueryExpression) expressionSegment).getSubquery());
+        }
     }
     
     private void extractTablesFromCaseWhenExpression(final CaseWhenExpression expressionSegment) {
diff --git a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dml/expr/QuantifySubqueryExpression.java b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dml/expr/QuantifySubqueryExpression.java
new file mode 100644
index 00000000000..32a91211422
--- /dev/null
+++ b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dml/expr/QuantifySubqueryExpression.java
@@ -0,0 +1,43 @@
+/*
+ * 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.statement.core.segment.dml.expr;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
+
+/**
+ * Quantify subquery expression.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class QuantifySubqueryExpression implements ExpressionSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final SubquerySegment subquery;
+    
+    private final String quantifyOperator;
+    
+    @Override
+    public String getText() {
+        return quantifyOperator + " (" + subquery.getText() + ")";
+    }
+}
diff --git a/pom.xml b/pom.xml
index 22ae415fcf9..c3a09519c51 100644
--- a/pom.xml
+++ b/pom.xml
@@ -71,7 +71,7 @@
         <checker-qual.version>3.39.0</checker-qual.version>
         <error_prone_annotations.version>2.22.0</error_prone_annotations.version>
         <j2objc-annotations.version>1.3</j2objc-annotations.version>
-        <calcite.version>1.39.0</calcite.version>
+        <calcite.version>1.40.0</calcite.version>
         
         <commons-lang3.version>3.15.0</commons-lang3.version>
         <commons-codec.version>1.16.0</commons-codec.version>
diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java
index 65e605d6776..f339cb97fd0 100644
--- a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java
+++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java
@@ -34,6 +34,7 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.Inte
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.KeyValueSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.QuantifySubqueryExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.RowExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.TypeCastExpression;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.UnaryOperationExpression;
@@ -81,6 +82,7 @@ import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.s
 import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedMatchExpression;
 import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedMultisetExpression;
 import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedNotExpression;
+import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedQuantifySubqueryExpression;
 import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedRowExpression;
 import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedTypeCastExpression;
 import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedUnaryOperationExpression;
@@ -479,6 +481,16 @@ public final class ExpressionAssert {
         }
     }
     
+    private static void assertQuantifySubqueryExpression(final SQLCaseAssertContext assertContext, final QuantifySubqueryExpression actual, final ExpectedQuantifySubqueryExpression expected) {
+        if (null == expected) {
+            assertNull(actual, assertContext.getText("Actual quantify subquery expression should not exist."));
+        } else {
+            assertNotNull(actual, assertContext.getText("Actual quantify subquery expression should exist."));
+            assertThat(assertContext.getText("Quantify operator assertion error: "), actual.getQuantifyOperator(), is(expected.getOperator()));
+            assertSubquery(assertContext, actual.getSubquery(), expected.getSubquery());
+        }
+    }
+    
     /**
      * Assert expression by actual expression segment class type.
      *
@@ -709,6 +721,8 @@ public final class ExpressionAssert {
             assertJsonNullClauseSegment(assertContext, (JsonNullClauseSegment) actual, expected.getJsonNullClauseSegment());
         } else if (actual instanceof IntervalExpression) {
             assertIntervalExpression(assertContext, (IntervalExpression) actual, expected.getIntervalExpression());
+        } else if (actual instanceof QuantifySubqueryExpression) {
+            assertQuantifySubqueryExpression(assertContext, (QuantifySubqueryExpression) actual, expected.getQuantifySubqueryExpression());
         } else {
             throw new UnsupportedOperationException(String.format("Unsupported expression: %s", actual.getClass().getName()));
         }
diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java
index 50e62624462..c320167320f 100644
--- a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java
+++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java
@@ -116,6 +116,9 @@ public final class ExpectedExpression extends AbstractExpectedSQLSegment {
     @XmlElement(name = "interval-expression")
     private ExpectedIntervalExpression intervalExpression;
     
+    @XmlElement(name = "quantify-subquery-expression")
+    private ExpectedQuantifySubqueryExpression quantifySubqueryExpression;
+    
     @XmlElement(name = "multiset-expression")
     private ExpectedMultisetExpression multisetExpression;
     
diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedQuantifySubqueryExpression.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedQuantifySubqueryExpression.java
new file mode 100644
index 00000000000..d9d379fdd78
--- /dev/null
+++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedQuantifySubqueryExpression.java
@@ -0,0 +1,39 @@
+/*
+ * 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.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.simple.ExpectedSubquery;
+
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * Expected quantify subquery expression.
+ */
+@Getter
+@Setter
+public final class ExpectedQuantifySubqueryExpression extends AbstractExpectedSQLSegment {
+    
+    @XmlElement
+    private ExpectedSubquery subquery;
+    
+    @XmlElement
+    private String operator;
+}
diff --git a/test/it/parser/src/main/resources/case/dml/select-expression.xml b/test/it/parser/src/main/resources/case/dml/select-expression.xml
index 7fb29ec6360..f40c12b919a 100644
--- a/test/it/parser/src/main/resources/case/dml/select-expression.xml
+++ b/test/it/parser/src/main/resources/case/dml/select-expression.xml
@@ -1016,30 +1016,33 @@
                     </left>
                     <operator>&gt;</operator>
                     <right>
-                        <subquery start-index="49" stop-index="98">
-                            <select>
-                                <from start-index="69" stop-index="80">
-                                    <simple-table name="t_order_item" start-index="69" stop-index="80" />
-                                </from>
-                                <projections distinct-row="false" start-index="57" stop-index="62">
-                                    <column-projection name="status" start-index="57" stop-index="62" />
-                                </projections>
-                                <where start-index="82" stop-index="97">
-                                    <expr>
-                                        <binary-operation-expression start-index="88" stop-index="97">
-                                            <left>
-                                                <column name="status" start-index="88" stop-index="93" />
-                                            </left>
-                                            <operator>&gt;</operator>
-                                            <right>
-                                                <literal-expression value="1" start-index="97" stop-index="97" />
-                                                <parameter-marker-expression parameter-index="0" start-index="97" stop-index="97" />
-                                            </right>
-                                        </binary-operation-expression>
-                                    </expr>
-                                </where>
-                            </select>
-                        </subquery>
+                        <quantify-subquery-expression>
+                            <operator>ALL</operator>
+                            <subquery start-index="49" stop-index="98">
+                                <select>
+                                    <from start-index="69" stop-index="80">
+                                        <simple-table name="t_order_item" start-index="69" stop-index="80" />
+                                    </from>
+                                    <projections distinct-row="false" start-index="57" stop-index="62">
+                                        <column-projection name="status" start-index="57" stop-index="62" />
+                                    </projections>
+                                    <where start-index="82" stop-index="97">
+                                        <expr>
+                                            <binary-operation-expression start-index="88" stop-index="97">
+                                                <left>
+                                                    <column name="status" start-index="88" stop-index="93" />
+                                                </left>
+                                                <operator>&gt;</operator>
+                                                <right>
+                                                    <literal-expression value="1" start-index="97" stop-index="97" />
+                                                    <parameter-marker-expression parameter-index="0" start-index="97" stop-index="97" />
+                                                </right>
+                                            </binary-operation-expression>
+                                        </expr>
+                                    </where>
+                                </select>
+                            </subquery>
+                        </quantify-subquery-expression>
                     </right>
                 </binary-operation-expression>
             </expr>