You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by pa...@apache.org on 2021/10/09 01:58:26 UTC

[shardingsphere] branch master updated: support project subquery, in subquery and between subquery convert (#12939)

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

panjuan 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 5d6ff2b  support project subquery, in subquery and between subquery convert (#12939)
5d6ff2b is described below

commit 5d6ff2b9808c09eef61d247703bde0f249ae32cc
Author: Zhengqiang Duan <du...@apache.org>
AuthorDate: Sat Oct 9 09:57:41 2021 +0800

    support project subquery, in subquery and between subquery convert (#12939)
    
    * support project subquery, in subquery and between subquery convert
    
    * extract common param
---
 .../segment/expression/ExpressionConverter.java    | 12 ++++
 ...verter.java => BetweenExpressionConverter.java} | 21 ++++---
 .../impl/ExistsSubqueryExpressionConverter.java    |  2 +-
 ...onConverter.java => InExpressionConverter.java} | 20 ++++---
 .../expression/impl/ListExpressionConverter.java   |  6 +-
 ...erter.java => SubqueryExpressionConverter.java} | 14 ++---
 .../segment/projection/ProjectionsConverter.java   |  8 +++
 .../impl/AggregationProjectionConverter.java       | 65 ++++++++++++++++++++++
 .../impl/SubqueryProjectionConverter.java}         | 26 ++++++---
 .../statement/SelectStatementConverterTest.java    | 28 ++++++++++
 10 files changed, 167 insertions(+), 35 deletions(-)

diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/ExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/ExpressionConverter.java
index 2ef03dc..6645d6b 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/ExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/ExpressionConverter.java
@@ -19,18 +19,24 @@ package org.apache.shardingsphere.infra.optimize.converter.segment.expression;
 
 import org.apache.calcite.sql.SqlNode;
 import org.apache.shardingsphere.infra.optimize.converter.segment.SQLSegmentConverter;
+import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.BetweenExpressionConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.BinaryOperationExpressionConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.ColumnConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.ExistsSubqueryExpressionConverter;
+import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.InExpressionConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.ListExpressionConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.LiteralExpressionConverter;
+import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.SubqueryExpressionConverter;
 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.ExistsSubqueryExpression;
 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.complex.CommonExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 
 import java.util.Optional;
 
@@ -57,6 +63,12 @@ public final class ExpressionConverter implements SQLSegmentConverter<Expression
             return new ColumnConverter().convert((ColumnSegment) segment);
         } else if (segment instanceof ExistsSubqueryExpression) {
             return new ExistsSubqueryExpressionConverter().convert((ExistsSubqueryExpression) segment);
+        } else if (segment instanceof SubqueryExpressionSegment) {
+            return new SubqueryExpressionConverter().convert((SubqueryExpressionSegment) segment);
+        } else if (segment instanceof InExpression) {
+            return new InExpressionConverter().convert((InExpression) segment);
+        } else if (segment instanceof BetweenExpression) {
+            return new BetweenExpressionConverter().convert((BetweenExpression) segment);
         }
         throw new UnsupportedOperationException("unsupported TableSegment type: " + segment.getClass());
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/BetweenExpressionConverter.java
similarity index 61%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/BetweenExpressionConverter.java
index f5d37ff..1afa590 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/BetweenExpressionConverter.java
@@ -22,22 +22,29 @@ import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.converter.segment.SQLSegmentConverter;
-import org.apache.shardingsphere.infra.optimize.converter.statement.SelectStatementConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
+import org.apache.shardingsphere.infra.optimize.converter.segment.expression.ExpressionConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenExpression;
 
+import java.util.Collection;
+import java.util.LinkedList;
 import java.util.Optional;
 
 /**
- * Exists subquery expression converter.
+ * Between expression converter.
  */
-public final class ExistsSubqueryExpressionConverter implements SQLSegmentConverter<ExistsSubqueryExpression, SqlNode> {
+public final class BetweenExpressionConverter implements SQLSegmentConverter<BetweenExpression, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final ExistsSubqueryExpression expression) {
+    public Optional<SqlNode> convert(final BetweenExpression expression) {
         if (null == expression) {
             return Optional.empty();
         }
-        SqlBasicCall sqlNode = new SqlBasicCall(SqlStdOperatorTable.EXISTS, new SqlNode[]{new SelectStatementConverter().convert(expression.getSubquery().getSelect())}, SqlParserPos.ZERO);
-        return expression.isNot() ? Optional.of(new SqlBasicCall(SqlStdOperatorTable.NOT, new SqlNode[] {sqlNode}, SqlParserPos.ZERO)) : Optional.of(sqlNode); 
+        Collection<SqlNode> sqlNodes = new LinkedList<>();
+        ExpressionConverter expressionConverter = new ExpressionConverter();
+        expressionConverter.convert(expression.getLeft()).ifPresent(sqlNodes::add);
+        expressionConverter.convert(expression.getBetweenExpr()).ifPresent(sqlNodes::add);
+        expressionConverter.convert(expression.getAndExpr()).ifPresent(sqlNodes::add);
+        SqlBasicCall sqlNode = new SqlBasicCall(SqlStdOperatorTable.BETWEEN, sqlNodes.toArray(new SqlNode[]{}), SqlParserPos.ZERO);
+        return expression.isNot() ? Optional.of(new SqlBasicCall(SqlStdOperatorTable.NOT, new SqlNode[]{sqlNode}, SqlParserPos.ZERO)) : Optional.of(sqlNode);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
index f5d37ff..5726769 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
@@ -38,6 +38,6 @@ public final class ExistsSubqueryExpressionConverter implements SQLSegmentConver
             return Optional.empty();
         }
         SqlBasicCall sqlNode = new SqlBasicCall(SqlStdOperatorTable.EXISTS, new SqlNode[]{new SelectStatementConverter().convert(expression.getSubquery().getSelect())}, SqlParserPos.ZERO);
-        return expression.isNot() ? Optional.of(new SqlBasicCall(SqlStdOperatorTable.NOT, new SqlNode[] {sqlNode}, SqlParserPos.ZERO)) : Optional.of(sqlNode); 
+        return expression.isNot() ? Optional.of(new SqlBasicCall(SqlStdOperatorTable.NOT, new SqlNode[]{sqlNode}, SqlParserPos.ZERO)) : Optional.of(sqlNode);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/InExpressionConverter.java
similarity index 64%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/InExpressionConverter.java
index f5d37ff..22c3fc1 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/InExpressionConverter.java
@@ -22,22 +22,28 @@ import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.converter.segment.SQLSegmentConverter;
-import org.apache.shardingsphere.infra.optimize.converter.statement.SelectStatementConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
+import org.apache.shardingsphere.infra.optimize.converter.segment.expression.ExpressionConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
 
+import java.util.Collection;
+import java.util.LinkedList;
 import java.util.Optional;
 
 /**
- * Exists subquery expression converter.
+ * In expression converter.
  */
-public final class ExistsSubqueryExpressionConverter implements SQLSegmentConverter<ExistsSubqueryExpression, SqlNode> {
+public final class InExpressionConverter implements SQLSegmentConverter<InExpression, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final ExistsSubqueryExpression expression) {
+    public Optional<SqlNode> convert(final InExpression expression) {
         if (null == expression) {
             return Optional.empty();
         }
-        SqlBasicCall sqlNode = new SqlBasicCall(SqlStdOperatorTable.EXISTS, new SqlNode[]{new SelectStatementConverter().convert(expression.getSubquery().getSelect())}, SqlParserPos.ZERO);
-        return expression.isNot() ? Optional.of(new SqlBasicCall(SqlStdOperatorTable.NOT, new SqlNode[] {sqlNode}, SqlParserPos.ZERO)) : Optional.of(sqlNode); 
+        Collection<SqlNode> sqlNodes = new LinkedList<>();
+        ExpressionConverter expressionConverter = new ExpressionConverter();
+        expressionConverter.convert(expression.getLeft()).ifPresent(sqlNodes::add);
+        expressionConverter.convert(expression.getRight()).ifPresent(sqlNodes::add);
+        SqlBasicCall sqlNode = new SqlBasicCall(SqlStdOperatorTable.IN, sqlNodes.toArray(new SqlNode[]{}), SqlParserPos.ZERO);
+        return expression.isNot() ? Optional.of(new SqlBasicCall(SqlStdOperatorTable.NOT, new SqlNode[]{sqlNode}, SqlParserPos.ZERO)) : Optional.of(sqlNode);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ListExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ListExpressionConverter.java
index 13e5586..5f049b5 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ListExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ListExpressionConverter.java
@@ -36,12 +36,12 @@ public final class ListExpressionConverter implements SQLSegmentConverter<ListEx
     @Override
     public Optional<SqlNode> convert(final ListExpression segment) {
         SqlNode left = null;
-        for (ExpressionSegment item : segment.getItems()) {
-            Optional<SqlNode> optional = new ExpressionConverter().convert(item);
+        for (ExpressionSegment each : segment.getItems()) {
+            Optional<SqlNode> optional = new ExpressionConverter().convert(each);
             if (!optional.isPresent()) {
                 continue;
             }
-            if (left == null) {
+            if (null == left) {
                 left = optional.get();
                 continue;
             }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/SubqueryExpressionConverter.java
similarity index 62%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/SubqueryExpressionConverter.java
index f5d37ff..2733756 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/SubqueryExpressionConverter.java
@@ -17,27 +17,23 @@
 
 package org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl;
 
-import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.converter.segment.SQLSegmentConverter;
 import org.apache.shardingsphere.infra.optimize.converter.statement.SelectStatementConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 
 import java.util.Optional;
 
 /**
- * Exists subquery expression converter.
+ * Subquery expression converter.
  */
-public final class ExistsSubqueryExpressionConverter implements SQLSegmentConverter<ExistsSubqueryExpression, SqlNode> {
+public final class SubqueryExpressionConverter implements SQLSegmentConverter<SubqueryExpressionSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final ExistsSubqueryExpression expression) {
+    public Optional<SqlNode> convert(final SubqueryExpressionSegment expression) {
         if (null == expression) {
             return Optional.empty();
         }
-        SqlBasicCall sqlNode = new SqlBasicCall(SqlStdOperatorTable.EXISTS, new SqlNode[]{new SelectStatementConverter().convert(expression.getSubquery().getSelect())}, SqlParserPos.ZERO);
-        return expression.isNot() ? Optional.of(new SqlBasicCall(SqlStdOperatorTable.NOT, new SqlNode[] {sqlNode}, SqlParserPos.ZERO)) : Optional.of(sqlNode); 
+        return Optional.of(new SelectStatementConverter().convert(expression.getSubquery().getSelect()));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/ProjectionsConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/ProjectionsConverter.java
index d8842f2..a9763c9 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/ProjectionsConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/ProjectionsConverter.java
@@ -21,14 +21,18 @@ import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.converter.segment.SQLSegmentConverter;
+import org.apache.shardingsphere.infra.optimize.converter.segment.projection.impl.AggregationProjectionConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.projection.impl.ColumnProjectionConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.projection.impl.ExpressionProjectionConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.projection.impl.ShorthandProjectionConverter;
+import org.apache.shardingsphere.infra.optimize.converter.segment.projection.impl.SubqueryProjectionConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
 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.ShorthandProjectionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -55,6 +59,10 @@ public final class ProjectionsConverter implements SQLSegmentConverter<Projectio
             return new ExpressionProjectionConverter().convert((ExpressionProjectionSegment) segment);
         } else if (segment instanceof ShorthandProjectionSegment) {
             return new ShorthandProjectionConverter().convert((ShorthandProjectionSegment) segment);
+        } else if (segment instanceof SubqueryProjectionSegment) {
+            return new SubqueryProjectionConverter().convert((SubqueryProjectionSegment) segment);
+        } else if (segment instanceof AggregationProjectionSegment) {
+            return new AggregationProjectionConverter().convert((AggregationProjectionSegment) segment);
         }
         // TODO process other projection
         return Optional.empty();
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/AggregationProjectionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/AggregationProjectionConverter.java
new file mode 100644
index 0000000..7ac0bc2
--- /dev/null
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/AggregationProjectionConverter.java
@@ -0,0 +1,65 @@
+/*
+ * 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.infra.optimize.converter.segment.projection.impl;
+
+import com.google.common.base.Preconditions;
+import org.apache.calcite.sql.SqlAggFunction;
+import org.apache.calcite.sql.SqlBasicCall;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.shardingsphere.infra.optimize.converter.segment.SQLSegmentConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.TreeMap;
+
+/**
+ * Aggregation projection converter. 
+ */
+public final class AggregationProjectionConverter implements SQLSegmentConverter<AggregationProjectionSegment, SqlNode> {
+    
+    private static final Map<String, SqlAggFunction> REGISTRY = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+    
+    static {
+        register(SqlStdOperatorTable.MAX);
+        register(SqlStdOperatorTable.MIN);
+        register(SqlStdOperatorTable.SUM);
+        register(SqlStdOperatorTable.COUNT);
+        register(SqlStdOperatorTable.AVG);
+    }
+    
+    private static void register(final SqlAggFunction sqlAggFunction) {
+        REGISTRY.put(sqlAggFunction.getName(), sqlAggFunction);
+    }
+    
+    @Override
+    public Optional<SqlNode> convert(final AggregationProjectionSegment segment) {
+        if (null == segment) {
+            return Optional.empty();
+        }
+        return Optional.of(new SqlBasicCall(convertOperator(segment.getType().name()), new SqlNode[]{SqlIdentifier.star(SqlParserPos.ZERO)}, SqlParserPos.ZERO));
+    }
+    
+    private SqlAggFunction convertOperator(final String operator) {
+        Preconditions.checkState(REGISTRY.containsKey(operator), "Unsupported SQL operator: `%s`", operator);
+        return REGISTRY.get(operator);
+    }
+}
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/SubqueryProjectionConverter.java
similarity index 58%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/SubqueryProjectionConverter.java
index f5d37ff..e2bdef7 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ExistsSubqueryExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/SubqueryProjectionConverter.java
@@ -15,29 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl;
+package org.apache.shardingsphere.infra.optimize.converter.segment.projection.impl;
 
 import org.apache.calcite.sql.SqlBasicCall;
+import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.converter.segment.SQLSegmentConverter;
 import org.apache.shardingsphere.infra.optimize.converter.statement.SelectStatementConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 
+import java.util.Collection;
+import java.util.LinkedList;
 import java.util.Optional;
 
 /**
- * Exists subquery expression converter.
+ * Subquery projection converter. 
  */
-public final class ExistsSubqueryExpressionConverter implements SQLSegmentConverter<ExistsSubqueryExpression, SqlNode> {
+public final class SubqueryProjectionConverter implements SQLSegmentConverter<SubqueryProjectionSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final ExistsSubqueryExpression expression) {
-        if (null == expression) {
+    public Optional<SqlNode> convert(final SubqueryProjectionSegment segment) {
+        if (null == segment) {
             return Optional.empty();
         }
-        SqlBasicCall sqlNode = new SqlBasicCall(SqlStdOperatorTable.EXISTS, new SqlNode[]{new SelectStatementConverter().convert(expression.getSubquery().getSelect())}, SqlParserPos.ZERO);
-        return expression.isNot() ? Optional.of(new SqlBasicCall(SqlStdOperatorTable.NOT, new SqlNode[] {sqlNode}, SqlParserPos.ZERO)) : Optional.of(sqlNode); 
+        SqlNode sqlNode = new SelectStatementConverter().convert(segment.getSubquery().getSelect());
+        return segment.getAlias().isPresent() ? convert(sqlNode, segment.getAlias().get()) : Optional.of(sqlNode);
+    }
+    
+    private Optional<SqlNode> convert(final SqlNode sqlNode, final String alias) {
+        Collection<SqlNode> sqlNodes = new LinkedList<>();
+        sqlNodes.add(sqlNode);
+        sqlNodes.add(new SqlIdentifier(alias, SqlParserPos.ZERO));
+        return Optional.of(new SqlBasicCall(SqlStdOperatorTable.AS, sqlNodes.toArray(new SqlNode[]{}), SqlParserPos.ZERO));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/test/java/org/apache/shardingsphere/infra/optimize/converter/statement/SelectStatementConverterTest.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/test/java/org/apache/shardingsphere/infra/optimize/converter/statement/SelectStatementConverterTest.java
index a92e0fe..5a97bb9 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/test/java/org/apache/shardingsphere/infra/optimize/converter/statement/SelectStatementConverterTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/test/java/org/apache/shardingsphere/infra/optimize/converter/statement/SelectStatementConverterTest.java
@@ -204,6 +204,34 @@ public final class SelectStatementConverterTest {
         assertTrue(expected.equalsDeep(actual, Litmus.THROW));
     }
     
+    @Test
+    public void assertConvertProjectionSubquery() {
+        String sql = "SELECT t_order_federate.order_id, t_order_federate.user_id, (SELECT COUNT(*) FROM t_user_info) FROM t_order_federate";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        SqlNode expected = parse(sql, new MySQLDatabaseType());
+        SqlNode actual = SQLNodeConvertEngine.convert(sqlStatement);
+        assertTrue(expected.equalsDeep(actual, Litmus.THROW));
+    }
+    
+    @Test
+    public void assertConvertInSubquery() {
+        String sql = "SELECT t_order_federate.order_id, t_order_federate.user_id FROM t_order_federate WHERE user_id IN (SELECT * FROM t_user_info)";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        SqlNode expected = parse(sql, new MySQLDatabaseType());
+        SqlNode actual = SQLNodeConvertEngine.convert(sqlStatement);
+        assertTrue(expected.equalsDeep(actual, Litmus.THROW));
+    }
+    
+    @Test
+    public void assertConvertBetweenAndSubquery() {
+        String 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 information = 'before') AND (SELECT user_id FROM t_user_info WHERE information = 'after')";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        SqlNode expected = parse(sql, new MySQLDatabaseType());
+        SqlNode actual = SQLNodeConvertEngine.convert(sqlStatement);
+        assertTrue(expected.equalsDeep(actual, Litmus.THROW));
+    }
+    
     @SneakyThrows(SqlParseException.class)
     private SqlNode parse(final String sql, final DatabaseType databaseType) {
         return SqlParser.create(sql, Config.DEFAULT.withConformance(getSQLConformance(databaseType)).withLex(getLex(databaseType))).parseQuery();