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/06/28 00:58:59 UTC

[shardingsphere] branch master updated: Convert ss ast to calcite ast (#10889)

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 7e9e107  Convert ss ast to calcite ast (#10889)
7e9e107 is described below

commit 7e9e1070f6f7d5424508f9ba7a8b1a9cd8375271
Author: mygui <gu...@gmail.com>
AuthorDate: Mon Jun 28 08:58:18 2021 +0800

    Convert ss ast to calcite ast (#10889)
    
    * to #8284
    add a SqlNodeConverter class to convert ss ast to calcite ast.
    
    * use ast SqlNodeConverter implementation to convert ast instead of all in one
    
    * refactor sql node converter
    
    * modify  according to code style
    
    * refactor offset and row count sql node converter
    
    * fix code style checking error
---
 .../shardingsphere-infra-optimize/pom.xml          |  30 ++++
 .../core/convert/converter/SqlNodeConverter.java   |   4 +-
 .../convert/converter/SqlNodeConverterUtil.java    |  63 ++++++++
 ...ter.java => AbstractLimitSqlNodeConverter.java} |  22 ++-
 ...BinaryOperationExpressionSqlNodeConverter.java} |  24 +--
 ...java => ColumnOrderByItemSqlNodeConverter.java} |  22 +--
 ....java => ColumnProjectionSqlNodeConverter.java} |  15 +-
 ...eConverter.java => ColumnSqlNodeConverter.java} |  22 +--
 .../converter/impl/DistinctSqlNodeConverter.java   |   5 +-
 ... => ExpressionOrderByItemSqlNodeConverter.java} |  15 +-
 ...a => ExpressionProjectionSqlNodeConverter.java} |  18 +--
 .../converter/impl/ExpressionSqlNodeConverter.java |  55 +++++++
 ...Converter.java => GroupBySqlNodeConverter.java} |  22 +--
 ...eConverter.java => HavingSqlNodeConverter.java} |  12 +-
 .../converter/impl/JoinTableSqlNodeConverter.java  |  75 +++++++++
 ...er.java => ListExpressionSqlNodeConverter.java} |  36 +++--
 ...java => LiteralExpressionSqlNodeConverter.java} |  20 ++-
 .../converter/impl/OffsetSqlNodeConverter.java     |  18 +--
 ...Converter.java => OrderBySqlNodeConverter.java} |  19 +--
 .../impl/PaginationValueSqlConverter.java          |   5 +-
 .../impl/ProjectionsSqlNodeConverter.java          |  57 +++++++
 .../converter/impl/RowCountSqlNodeConverter.java   |  16 +-
 .../impl/SelectStatementSqlNodeConverter.java      |  31 +++-
 ...erter.java => SimpleTableSqlNodeConverter.java} |  27 ++--
 ...ter.java => SubqueryTableSqlNodeConverter.java} |  14 +-
 .../converter/impl/TableSqlNodeConverter.java      |  45 ++++++
 ...deConverter.java => WhereSqlNodeConverter.java} |  14 +-
 .../optimize/core/operator/BinarySqlOperator.java  |  72 +++++++++
 .../SelectStatementSqlNodeConverterTest.java       | 167 +++++++++++++++++++++
 29 files changed, 769 insertions(+), 176 deletions(-)

diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/pom.xml b/shardingsphere-infra/shardingsphere-infra-optimize/pom.xml
index a18a0b3..7dab38a 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/pom.xml
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/pom.xml
@@ -43,5 +43,35 @@
             <groupId>org.apache.calcite</groupId>
             <artifactId>calcite-core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-sql-parser-sql92</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-sql-parser-mysql</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-sql-parser-postgresql</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-sql-parser-oracle</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-sql-parser-sqlserver</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/SqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/SqlNodeConverter.java
index c0c38d3..97a2529 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/SqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/SqlNodeConverter.java
@@ -25,12 +25,12 @@ import java.util.Optional;
 /**
  * SqlNode converter.
  */
-public interface SqlNodeConverter<T extends ASTNode> {
+public interface SqlNodeConverter<T extends ASTNode, R extends SqlNode> {
     
     /**
      *  Convert.
      * @param astNode ast node
      * @return sqlNode optional
      */
-    Optional<SqlNode> convert(T astNode);
+    Optional<R> convert(T astNode);
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/SqlNodeConverterUtil.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/SqlNodeConverterUtil.java
new file mode 100644
index 0000000..09a2bca
--- /dev/null
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/SqlNodeConverterUtil.java
@@ -0,0 +1,63 @@
+/*
+ * 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.core.convert.converter;
+
+import com.google.common.collect.Lists;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.shardingsphere.infra.optimize.core.convert.converter.impl.ColumnOrderByItemSqlNodeConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ExpressionOrderByItemSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.IndexOrderByItemSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.TextOrderByItemSegment;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Utility for sql node converter.
+ */
+public final class SqlNodeConverterUtil {
+    
+    /**
+     * Convert order by items.
+     * @param orderByItems order by item list.
+     * @return a collection of order by item <code>SqlNode</code>
+     */
+    public static List<SqlNode> convertOrderByItems(final Collection<OrderByItemSegment> orderByItems) {
+        List<SqlNode> sqlNodes = Lists.newArrayList();
+        for (OrderByItemSegment orderByItemSegment : orderByItems) {
+            Optional<SqlNode> optional = Optional.empty();
+            if (orderByItemSegment instanceof ColumnOrderByItemSegment) {
+                optional = new ColumnOrderByItemSqlNodeConverter().convert((ColumnOrderByItemSegment) orderByItemSegment);
+            } else if (orderByItemSegment instanceof ExpressionOrderByItemSegment) {
+                throw new UnsupportedOperationException("unsupported ExpressionOrderByItemSegment");
+            } else if (orderByItemSegment instanceof IndexOrderByItemSegment) {
+                throw new UnsupportedOperationException("unsupported IndexOrderByItemSegment");
+            } else if (orderByItemSegment instanceof TextOrderByItemSegment) {
+                throw new UnsupportedOperationException("unsupported TextOrderByItemSegment");
+            }
+
+            if (optional.isPresent()) {
+                sqlNodes.add(optional.get());
+            }
+        }
+        return sqlNodes;
+    }
+}
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/AbstractLimitSqlNodeConverter.java
similarity index 58%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/AbstractLimitSqlNodeConverter.java
index ad50960..b6e1e80 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/AbstractLimitSqlNodeConverter.java
@@ -19,20 +19,32 @@ package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
 import org.apache.calcite.sql.SqlNode;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.PaginationValueSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
 
 import java.util.Optional;
+import java.util.function.Function;
 
 /**
- * Row count sql node converter.
+ * Abstract limit sql node converter.
  */
-public final class RowCountSqlNodeConverter implements SqlNodeConverter<LimitSegment> {
+public abstract class AbstractLimitSqlNodeConverter implements SqlNodeConverter<LimitSegment, SqlNode> {
+
+    private Function<LimitSegment, Optional<PaginationValueSegment>> function;
+    
+    protected AbstractLimitSqlNodeConverter(final Function<LimitSegment, Optional<PaginationValueSegment>> function) {
+        this.function = function;
+    }
     
     @Override
-    public Optional<SqlNode> convert(final LimitSegment limitSegment) {
-        if (null == limitSegment || !limitSegment.getRowCount().isPresent()) {
+    public final Optional<SqlNode> convert(final LimitSegment limit) {
+        if (null == limit) {
+            return Optional.empty();
+        }
+        Optional<PaginationValueSegment> paginationValue = function.apply(limit);
+        if (!paginationValue.isPresent()) {
             return Optional.empty();
         }
-        return new PaginationValueSqlConverter().convert(limitSegment.getRowCount().get());
+        return new PaginationValueSqlConverter().convert(paginationValue.get());
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/BinaryOperationExpressionSqlNodeConverter.java
similarity index 54%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/BinaryOperationExpressionSqlNodeConverter.java
index fc2e57a..85571c0 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/BinaryOperationExpressionSqlNodeConverter.java
@@ -17,26 +17,28 @@
 
 package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
+import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.SqlSelectKeyword;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
+import org.apache.shardingsphere.infra.optimize.core.operator.BinarySqlOperator;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
 
-import java.util.Collections;
 import java.util.Optional;
 
 /**
- * Distinct sql node converter.
+ * Binary operation expression converter.
  */
-public final class DistinctSqlNodeConverter implements SqlNodeConverter<ProjectionsSegment> {
+public final class BinaryOperationExpressionSqlNodeConverter implements SqlNodeConverter<BinaryOperationExpression, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final ProjectionsSegment projectionsSegment) {
-        if (projectionsSegment.isDistinctRow()) {
-            return Optional.of(new SqlNodeList(Collections.singletonList(SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO)), SqlParserPos.ZERO));
-        }
-        return Optional.empty();
+    public Optional<SqlNode> convert(final BinaryOperationExpression binaryOperationExpression) {
+        SqlNode left = new ExpressionSqlNodeConverter().convert(binaryOperationExpression.getLeft()).get();
+        SqlNode right = new ExpressionSqlNodeConverter().convert(binaryOperationExpression.getRight()).get();
+        String operator = binaryOperationExpression.getOperator();
+        BinarySqlOperator binarySqlOperator = BinarySqlOperator.value(operator);
+        SqlNode sqlNode = new SqlBasicCall(binarySqlOperator.getSqlBinaryOperator(), new SqlNode[] {left, right},
+                SqlParserPos.ZERO);
+        return Optional.of(sqlNode);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ColumnOrderByItemSqlNodeConverter.java
similarity index 58%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ColumnOrderByItemSqlNodeConverter.java
index fc2e57a..76d38eb 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ColumnOrderByItemSqlNodeConverter.java
@@ -17,26 +17,28 @@
 
 package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
+import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.SqlSelectKeyword;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.constant.OrderDirection;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
 
-import java.util.Collections;
+import java.util.Objects;
 import java.util.Optional;
 
 /**
- * Distinct sql node converter.
+ *  Column of order by converter. 
  */
-public final class DistinctSqlNodeConverter implements SqlNodeConverter<ProjectionsSegment> {
+public final class ColumnOrderByItemSqlNodeConverter implements SqlNodeConverter<ColumnOrderByItemSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final ProjectionsSegment projectionsSegment) {
-        if (projectionsSegment.isDistinctRow()) {
-            return Optional.of(new SqlNodeList(Collections.singletonList(SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO)), SqlParserPos.ZERO));
+    public Optional<SqlNode> convert(final ColumnOrderByItemSegment columnOrderBy) {
+        Optional<SqlNode> optional = new ColumnSqlNodeConverter().convert(columnOrderBy.getColumn());
+        if (optional.isPresent() && Objects.equals(OrderDirection.DESC, columnOrderBy.getOrderDirection())) {
+            optional = Optional.of(new SqlBasicCall(SqlStdOperatorTable.DESC, new SqlNode[] {optional.get()}, SqlParserPos.ZERO));
         }
-        return Optional.empty();
+        return optional;
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ColumnProjectionSqlNodeConverter.java
similarity index 70%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ColumnProjectionSqlNodeConverter.java
index ad50960..ac6e671 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ColumnProjectionSqlNodeConverter.java
@@ -19,20 +19,19 @@ package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
 import org.apache.calcite.sql.SqlNode;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 
 import java.util.Optional;
 
 /**
- * Row count sql node converter.
+ * Column projection converter. 
  */
-public final class RowCountSqlNodeConverter implements SqlNodeConverter<LimitSegment> {
+public final class ColumnProjectionSqlNodeConverter implements SqlNodeConverter<ColumnProjectionSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final LimitSegment limitSegment) {
-        if (null == limitSegment || !limitSegment.getRowCount().isPresent()) {
-            return Optional.empty();
-        }
-        return new PaginationValueSqlConverter().convert(limitSegment.getRowCount().get());
+    public Optional<SqlNode> convert(final ColumnProjectionSegment columnProjection) {
+        ColumnSegment column = columnProjection.getColumn();
+        return new ColumnSqlNodeConverter().convert(column);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ColumnSqlNodeConverter.java
similarity index 60%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ColumnSqlNodeConverter.java
index fc2e57a..08f790d 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ColumnSqlNodeConverter.java
@@ -17,26 +17,28 @@
 
 package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.SqlSelectKeyword;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
 
-import java.util.Collections;
 import java.util.Optional;
 
 /**
- * Distinct sql node converter.
+ * Column converter.
  */
-public final class DistinctSqlNodeConverter implements SqlNodeConverter<ProjectionsSegment> {
+public final class ColumnSqlNodeConverter implements SqlNodeConverter<ColumnSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final ProjectionsSegment projectionsSegment) {
-        if (projectionsSegment.isDistinctRow()) {
-            return Optional.of(new SqlNodeList(Collections.singletonList(SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO)), SqlParserPos.ZERO));
+    public Optional<SqlNode> convert(final ColumnSegment columnSegment) {
+        Optional<OwnerSegment> owner = columnSegment.getOwner();
+        String columnName = columnSegment.getIdentifier().getValue();
+        if (owner.isPresent()) {
+            return Optional.of(new SqlIdentifier(ImmutableList.of(owner.get().getIdentifier().getValue(), columnName), SqlParserPos.ZERO));
         }
-        return Optional.empty();
+        return Optional.of(new SqlIdentifier(columnName, SqlParserPos.ZERO));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
index fc2e57a..bd041da 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
@@ -17,7 +17,6 @@
 
 package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
-import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
 import org.apache.calcite.sql.SqlSelectKeyword;
 import org.apache.calcite.sql.parser.SqlParserPos;
@@ -30,10 +29,10 @@ import java.util.Optional;
 /**
  * Distinct sql node converter.
  */
-public final class DistinctSqlNodeConverter implements SqlNodeConverter<ProjectionsSegment> {
+public final class DistinctSqlNodeConverter implements SqlNodeConverter<ProjectionsSegment, SqlNodeList> {
     
     @Override
-    public Optional<SqlNode> convert(final ProjectionsSegment projectionsSegment) {
+    public Optional<SqlNodeList> convert(final ProjectionsSegment projectionsSegment) {
         if (projectionsSegment.isDistinctRow()) {
             return Optional.of(new SqlNodeList(Collections.singletonList(SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO)), SqlParserPos.ZERO));
         }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ExpressionOrderByItemSqlNodeConverter.java
similarity index 71%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ExpressionOrderByItemSqlNodeConverter.java
index a7a7c0f..37b202b 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ExpressionOrderByItemSqlNodeConverter.java
@@ -19,20 +19,15 @@ package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
 import org.apache.calcite.sql.SqlNode;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ExpressionOrderByItemSegment;
 
 import java.util.Optional;
 
-/**
- * Offset sql node converter.
- */
-public final class OffsetSqlNodeConverter implements SqlNodeConverter<LimitSegment> {
+public final class ExpressionOrderByItemSqlNodeConverter implements SqlNodeConverter<ExpressionOrderByItemSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final LimitSegment limitSegment) {
-        if (null == limitSegment || !limitSegment.getOffset().isPresent()) {
-            return Optional.empty();
-        }
-        return new PaginationValueSqlConverter().convert(limitSegment.getOffset().get());
+    public Optional<SqlNode> convert(final ExpressionOrderByItemSegment astNode) {
+        // TODO 
+        return Optional.empty();
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ExpressionProjectionSqlNodeConverter.java
similarity index 66%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ExpressionProjectionSqlNodeConverter.java
index ad50960..3a4e9c2 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ExpressionProjectionSqlNodeConverter.java
@@ -17,22 +17,20 @@
 
 package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
+import org.apache.calcite.sql.SqlCharStringLiteral;
 import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
 
 import java.util.Optional;
 
-/**
- * Row count sql node converter.
- */
-public final class RowCountSqlNodeConverter implements SqlNodeConverter<LimitSegment> {
+public final class ExpressionProjectionSqlNodeConverter implements SqlNodeConverter<ExpressionProjectionSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final LimitSegment limitSegment) {
-        if (null == limitSegment || !limitSegment.getRowCount().isPresent()) {
-            return Optional.empty();
-        }
-        return new PaginationValueSqlConverter().convert(limitSegment.getRowCount().get());
+    public Optional<SqlNode> convert(final ExpressionProjectionSegment expressionProjection) {
+        // TODO expression has not been parsed now.
+        String expression = expressionProjection.getText();
+        return Optional.of(SqlCharStringLiteral.createCharString(expression, SqlParserPos.ZERO));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ExpressionSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ExpressionSqlNodeConverter.java
new file mode 100644
index 0000000..42ef3af
--- /dev/null
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ExpressionSqlNodeConverter.java
@@ -0,0 +1,55 @@
+/*
+ * 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.core.convert.converter.impl;
+
+import org.apache.calcite.sql.SqlNode;
+import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.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 java.util.Optional;
+
+/**
+ * Expression converter entry.
+ */
+public final class ExpressionSqlNodeConverter implements SqlNodeConverter<ExpressionSegment, SqlNode> {
+    
+    @Override
+    public Optional<SqlNode> convert(final ExpressionSegment expression) {
+        if (expression == null) {
+            return Optional.empty();
+        }
+        if (expression instanceof LiteralExpressionSegment) {
+            return new LiteralExpressionSqlNodeConverter().convert((LiteralExpressionSegment) expression);
+        } else if (expression instanceof CommonExpressionSegment) {
+            // TODO 
+            throw new UnsupportedOperationException("unsupported CommonExpressionSegment");
+        } else if (expression instanceof ListExpression) {
+            return new ListExpressionSqlNodeConverter().convert((ListExpression) expression);
+        } else if (expression instanceof BinaryOperationExpression) {
+            return new BinaryOperationExpressionSqlNodeConverter().convert((BinaryOperationExpression) expression);
+        } else if (expression instanceof ColumnSegment) {
+            return new ColumnSqlNodeConverter().convert((ColumnSegment) expression);
+        }
+        throw new UnsupportedOperationException("unsupportd TableSegment type: " + expression.getClass());
+    }
+}
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/GroupBySqlNodeConverter.java
similarity index 58%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/GroupBySqlNodeConverter.java
index fc2e57a..5f7622c 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/GroupBySqlNodeConverter.java
@@ -19,24 +19,28 @@ package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.SqlSelectKeyword;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
+import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverterUtil;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.GroupBySegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
 
-import java.util.Collections;
+import java.util.Collection;
+import java.util.List;
 import java.util.Optional;
 
 /**
- * Distinct sql node converter.
+ * Group by converter.
  */
-public final class DistinctSqlNodeConverter implements SqlNodeConverter<ProjectionsSegment> {
+public final class GroupBySqlNodeConverter implements SqlNodeConverter<GroupBySegment, SqlNodeList> {
     
     @Override
-    public Optional<SqlNode> convert(final ProjectionsSegment projectionsSegment) {
-        if (projectionsSegment.isDistinctRow()) {
-            return Optional.of(new SqlNodeList(Collections.singletonList(SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO)), SqlParserPos.ZERO));
+    public Optional<SqlNodeList> convert(final GroupBySegment groupBy) {
+        if (groupBy == null || groupBy.getGroupByItems() == null || groupBy.getGroupByItems().isEmpty()) {
+            return Optional.empty();
         }
-        return Optional.empty();
+        Collection<OrderByItemSegment> groupByItems = groupBy.getGroupByItems();
+        List<SqlNode> groupBySqlNodes = SqlNodeConverterUtil.convertOrderByItems(groupByItems);
+        return Optional.of(new SqlNodeList(groupBySqlNodes, SqlParserPos.ZERO));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/HavingSqlNodeConverter.java
similarity index 75%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/HavingSqlNodeConverter.java
index a7a7c0f..e9a7dea 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/HavingSqlNodeConverter.java
@@ -19,20 +19,20 @@ package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
 import org.apache.calcite.sql.SqlNode;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.HavingSegment;
 
 import java.util.Optional;
 
 /**
- * Offset sql node converter.
+ * Having converter.
  */
-public final class OffsetSqlNodeConverter implements SqlNodeConverter<LimitSegment> {
+public final class HavingSqlNodeConverter implements SqlNodeConverter<HavingSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final LimitSegment limitSegment) {
-        if (null == limitSegment || !limitSegment.getOffset().isPresent()) {
+    public Optional<SqlNode> convert(final HavingSegment having) {
+        if (having == null) {
             return Optional.empty();
         }
-        return new PaginationValueSqlConverter().convert(limitSegment.getOffset().get());
+        return new ExpressionSqlNodeConverter().convert(having.getExpr());
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/JoinTableSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/JoinTableSqlNodeConverter.java
new file mode 100644
index 0000000..57c7687
--- /dev/null
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/JoinTableSqlNodeConverter.java
@@ -0,0 +1,75 @@
+/*
+ * 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.core.convert.converter.impl;
+
+import org.apache.calcite.sql.JoinConditionType;
+import org.apache.calcite.sql.JoinType;
+import org.apache.calcite.sql.SqlJoin;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
+
+import java.util.Optional;
+
+/**
+ * Join converter.
+ */
+public final class JoinTableSqlNodeConverter implements SqlNodeConverter<JoinTableSegment, SqlNode> {
+
+    private static final String JOIN_TYPE_INNER = "INNER";
+
+    private static final String JOIN_TYPE_LEFT = "LEFT";
+
+    private static final String JOIN_TYPE_RIGHT = "RIGHT";
+
+    private static final String JOIN_TYPE_FULL = "FULL";
+    
+    @Override
+    public Optional<SqlNode> convert(final JoinTableSegment join) {
+        SqlNode left = new TableSqlNodeConverter().convert(join.getLeft()).get();
+        SqlNode right = new TableSqlNodeConverter().convert(join.getRight()).get();
+        ExpressionSegment expressionSegment = join.getCondition();
+        Optional<SqlNode> condition = new ExpressionSqlNodeConverter().convert(expressionSegment);
+        SqlLiteral conditionType = condition.isPresent() ? JoinConditionType.NONE.symbol(SqlParserPos.ZERO)
+                : JoinConditionType.ON.symbol(SqlParserPos.ZERO);
+        SqlLiteral joinTypeSqlNode = convertJoinType(join.getJoinType());
+        SqlNode sqlNode = new SqlJoin(SqlParserPos.ZERO, left,
+                SqlLiteral.createBoolean(false, SqlParserPos.ZERO),
+                joinTypeSqlNode, right, conditionType, condition.orElse(null));
+        return Optional.of(sqlNode);
+    }
+    
+    private SqlLiteral convertJoinType(final String joinType) {
+        if (joinType == null) {
+            return JoinType.COMMA.symbol(SqlParserPos.ZERO);
+        } else if (JOIN_TYPE_INNER.equals(joinType)) {
+            return JoinType.INNER.symbol(SqlParserPos.ZERO);
+        } else if (JOIN_TYPE_LEFT.equals(joinType)) {
+            return JoinType.LEFT.symbol(SqlParserPos.ZERO);
+        } else if (JOIN_TYPE_RIGHT.equals(joinType)) {
+            return JoinType.RIGHT.symbol(SqlParserPos.ZERO);
+        } else if (JOIN_TYPE_FULL.equals(joinType)) {
+            return JoinType.FULL.symbol(SqlParserPos.ZERO);
+        } else {
+            throw new UnsupportedOperationException("unsupported join type " + joinType);
+        }
+    }
+}
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/PaginationValueSqlConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ListExpressionSqlNodeConverter.java
similarity index 54%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/PaginationValueSqlConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ListExpressionSqlNodeConverter.java
index bee8086..911ff25 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/PaginationValueSqlConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ListExpressionSqlNodeConverter.java
@@ -17,27 +17,37 @@
 
 package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
-import org.apache.calcite.sql.SqlDynamicParam;
-import org.apache.calcite.sql.SqlLiteral;
+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.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.NumberLiteralPaginationValueSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.PaginationValueSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.ParameterMarkerLimitValueSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 
+import java.util.List;
 import java.util.Optional;
 
-public final class PaginationValueSqlConverter implements SqlNodeConverter<PaginationValueSegment> {
+/**
+ * List expression converter.
+ */
+public final class ListExpressionSqlNodeConverter implements SqlNodeConverter<ListExpression, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final PaginationValueSegment paginationValue) {
-        if (paginationValue instanceof NumberLiteralPaginationValueSegment) {
-            NumberLiteralPaginationValueSegment offsetValue = (NumberLiteralPaginationValueSegment) paginationValue;
-            return Optional.of(SqlLiteral.createExactNumeric(String.valueOf(offsetValue.getValue()), SqlParserPos.ZERO));
-        } else {
-            ParameterMarkerLimitValueSegment offsetParam = (ParameterMarkerLimitValueSegment) paginationValue;
-            return Optional.of(new SqlDynamicParam(offsetParam.getParameterIndex(), SqlParserPos.ZERO));
+    public Optional<SqlNode> convert(final ListExpression expression) {
+        List<ExpressionSegment> items = expression.getItems();
+        SqlNode left = null;
+        for (ExpressionSegment item : items) {
+            Optional<SqlNode> optional = new ExpressionSqlNodeConverter().convert(item);
+            if (!optional.isPresent()) {
+                continue;
+            }
+            if (left == null) {
+                left = optional.get();
+                continue;
+            }
+            left = new SqlBasicCall(SqlStdOperatorTable.OR, new SqlNode[] {left, optional.get()}, SqlParserPos.ZERO);
         }
+        return Optional.of(left);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/LiteralExpressionSqlNodeConverter.java
similarity index 63%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/LiteralExpressionSqlNodeConverter.java
index fc2e57a..fd134bd 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/LiteralExpressionSqlNodeConverter.java
@@ -17,25 +17,23 @@
 
 package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
+import org.apache.calcite.sql.SqlLiteral;
 import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.SqlSelectKeyword;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
 
-import java.util.Collections;
 import java.util.Optional;
 
-/**
- * Distinct sql node converter.
- */
-public final class DistinctSqlNodeConverter implements SqlNodeConverter<ProjectionsSegment> {
+public final class LiteralExpressionSqlNodeConverter implements SqlNodeConverter<LiteralExpressionSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final ProjectionsSegment projectionsSegment) {
-        if (projectionsSegment.isDistinctRow()) {
-            return Optional.of(new SqlNodeList(Collections.singletonList(SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO)), SqlParserPos.ZERO));
+    public Optional<SqlNode> convert(final LiteralExpressionSegment literalExpression) {
+        Object literals = literalExpression.getLiterals();
+        if (literals.getClass() == Integer.class) {
+            return Optional.of(SqlLiteral.createExactNumeric(String.valueOf(literalExpression.getLiterals()), SqlParserPos.ZERO));
+        } else if (literals.getClass() == String.class) {
+            return Optional.of(SqlLiteral.createCharString((String) literalExpression.getLiterals(), SqlParserPos.ZERO));
         }
         return Optional.empty();
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java
index a7a7c0f..d4e5d5a 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java
@@ -17,22 +17,12 @@
 
 package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
-import org.apache.calcite.sql.SqlNode;
-import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
-
-import java.util.Optional;
-
 /**
  * Offset sql node converter.
  */
-public final class OffsetSqlNodeConverter implements SqlNodeConverter<LimitSegment> {
-    
-    @Override
-    public Optional<SqlNode> convert(final LimitSegment limitSegment) {
-        if (null == limitSegment || !limitSegment.getOffset().isPresent()) {
-            return Optional.empty();
-        }
-        return new PaginationValueSqlConverter().convert(limitSegment.getOffset().get());
+public final class OffsetSqlNodeConverter extends AbstractLimitSqlNodeConverter {
+
+    public OffsetSqlNodeConverter() {
+        super(limitSegment -> limitSegment.getOffset());
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OrderBySqlNodeConverter.java
similarity index 67%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OrderBySqlNodeConverter.java
index fc2e57a..dfb48f2 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OrderBySqlNodeConverter.java
@@ -19,24 +19,25 @@ package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.SqlSelectKeyword;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
+import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverterUtil;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.OrderBySegment;
 
-import java.util.Collections;
+import java.util.List;
 import java.util.Optional;
 
 /**
- * Distinct sql node converter.
+ * Order by converter. 
  */
-public final class DistinctSqlNodeConverter implements SqlNodeConverter<ProjectionsSegment> {
+public final class OrderBySqlNodeConverter implements SqlNodeConverter<OrderBySegment, SqlNodeList> {
     
     @Override
-    public Optional<SqlNode> convert(final ProjectionsSegment projectionsSegment) {
-        if (projectionsSegment.isDistinctRow()) {
-            return Optional.of(new SqlNodeList(Collections.singletonList(SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO)), SqlParserPos.ZERO));
+    public Optional<SqlNodeList> convert(final OrderBySegment orderBy) {
+        if (orderBy == null) {
+            return Optional.empty();
         }
-        return Optional.empty();
+        List<SqlNode> orderBySqlNodes = SqlNodeConverterUtil.convertOrderByItems(orderBy.getOrderByItems());
+        return Optional.of(new SqlNodeList(orderBySqlNodes, SqlParserPos.ZERO));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/PaginationValueSqlConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/PaginationValueSqlConverter.java
index bee8086..7b5b984 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/PaginationValueSqlConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/PaginationValueSqlConverter.java
@@ -28,7 +28,10 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.li
 
 import java.util.Optional;
 
-public final class PaginationValueSqlConverter implements SqlNodeConverter<PaginationValueSegment> {
+/**
+ * Pagination value converter.
+ */
+public final class PaginationValueSqlConverter implements SqlNodeConverter<PaginationValueSegment, SqlNode> {
     
     @Override
     public Optional<SqlNode> convert(final PaginationValueSegment paginationValue) {
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ProjectionsSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ProjectionsSqlNodeConverter.java
new file mode 100644
index 0000000..ddd503e
--- /dev/null
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/ProjectionsSqlNodeConverter.java
@@ -0,0 +1,57 @@
+/*
+ * 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.core.convert.converter.impl;
+
+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.core.convert.converter.SqlNodeConverter;
+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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Projection converter.
+ */
+public final class ProjectionsSqlNodeConverter implements SqlNodeConverter<ProjectionsSegment, SqlNodeList> {
+    
+    @Override
+    public Optional<SqlNodeList> convert(final ProjectionsSegment projectionsSegment) {
+        Collection<ProjectionSegment> projections = projectionsSegment.getProjections();
+        List<SqlNode> columnNodes = new ArrayList<>(projections.size());
+        for (ProjectionSegment projection : projections) {
+            Optional<SqlNode> optional = Optional.empty();
+            if (projection instanceof ColumnProjectionSegment) {
+                optional = new ColumnProjectionSqlNodeConverter().convert((ColumnProjectionSegment) projection);
+            } else if (projection instanceof ExpressionProjectionSegment) {
+                optional = new ExpressionProjectionSqlNodeConverter().convert((ExpressionProjectionSegment) projection);
+            }
+            // TODO other Projection
+            if (optional.isPresent()) {
+                columnNodes.add(optional.get());
+            }
+        }
+        return Optional.of(new SqlNodeList(columnNodes, SqlParserPos.ZERO));
+    }
+}
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
index ad50960..10a77ba 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
@@ -17,22 +17,12 @@
 
 package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
-import org.apache.calcite.sql.SqlNode;
-import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
-
-import java.util.Optional;
-
 /**
  * Row count sql node converter.
  */
-public final class RowCountSqlNodeConverter implements SqlNodeConverter<LimitSegment> {
+public final class RowCountSqlNodeConverter extends AbstractLimitSqlNodeConverter {
     
-    @Override
-    public Optional<SqlNode> convert(final LimitSegment limitSegment) {
-        if (null == limitSegment || !limitSegment.getRowCount().isPresent()) {
-            return Optional.empty();
-        }
-        return new PaginationValueSqlConverter().convert(limitSegment.getRowCount().get());
+    public RowCountSqlNodeConverter() {
+        super(limitSegment -> limitSegment.getRowCount());
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/SelectStatementSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/SelectStatementSqlNodeConverter.java
index 69333c7..feca3ed 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/SelectStatementSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/SelectStatementSqlNodeConverter.java
@@ -22,6 +22,7 @@ import org.apache.calcite.sql.SqlNodeList;
 import org.apache.calcite.sql.SqlSelect;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.handler.dml.SelectStatementHandler;
 
@@ -30,15 +31,31 @@ import java.util.Optional;
 /**
  * Select statement sql node converter.
  */
-public final class SelectStatementSqlNodeConverter implements SqlNodeConverter<SelectStatement> {
+public final class SelectStatementSqlNodeConverter implements SqlNodeConverter<SelectStatement, SqlNode> {
     
     @Override
     public Optional<SqlNode> convert(final SelectStatement selectStatement) {
-        Optional<SqlNode> distinct = new DistinctSqlNodeConverter().convert(selectStatement.getProjections());
-        Optional<SqlNode> offset = new OffsetSqlNodeConverter().convert(SelectStatementHandler.getLimitSegment(selectStatement).orElse(null));
-        Optional<SqlNode> rowCount = new RowCountSqlNodeConverter().convert(SelectStatementHandler.getLimitSegment(selectStatement).orElse(null));
-        // TODO : prepare other sqlNodes referring to `distinct`.
-        return Optional.of(new SqlSelect(SqlParserPos.ZERO, (SqlNodeList) distinct.orElse(null), null, null, null, null, null,
-                null, null, offset.orElse(null), rowCount.orElse(null), null));
+        Optional<SqlNodeList> distinct = new DistinctSqlNodeConverter().convert(selectStatement.getProjections());
+        Optional<SqlNodeList> projections = new ProjectionsSqlNodeConverter().convert(selectStatement.getProjections());
+        Optional<SqlNode> from = new TableSqlNodeConverter().convert(selectStatement.getFrom());
+        Optional<SqlNode> where = new WhereSqlNodeConverter().convert(selectStatement.getWhere().orElse(null));
+        Optional<SqlNodeList> groupBy = new GroupBySqlNodeConverter().convert(selectStatement.getGroupBy().orElse(null));
+        Optional<SqlNode> having = new HavingSqlNodeConverter().convert(selectStatement.getHaving().orElse(null));
+        Optional<SqlNodeList> orderBy = new OrderBySqlNodeConverter().convert(selectStatement.getOrderBy().orElse(null));
+        Optional<LimitSegment> limit = SelectStatementHandler.getLimitSegment(selectStatement);
+        Optional<SqlNode> offset = new OffsetSqlNodeConverter().convert(limit.orElse(null));
+        Optional<SqlNode> rowCount = new RowCountSqlNodeConverter().convert(limit.orElse(null));
+        return Optional.of(new SqlSelect(SqlParserPos.ZERO, 
+                distinct.orElse(null), 
+                projections.orElse(null), 
+                from.orElse(null), 
+                where.orElse(null), 
+                groupBy.orElse(null), 
+                having.orElse(null),
+                null, 
+                orderBy.orElse(null),
+                offset.orElse(null),
+                rowCount.orElse(null), 
+                null));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/SimpleTableSqlNodeConverter.java
similarity index 50%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/SimpleTableSqlNodeConverter.java
index fc2e57a..bface1a 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/DistinctSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/SimpleTableSqlNodeConverter.java
@@ -17,26 +17,33 @@
 
 package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
+import org.apache.calcite.sql.SqlBasicCall;
+import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.SqlSelectKeyword;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
 
-import java.util.Collections;
 import java.util.Optional;
 
 /**
- * Distinct sql node converter.
+ * Simple table converter.
  */
-public final class DistinctSqlNodeConverter implements SqlNodeConverter<ProjectionsSegment> {
+public final class SimpleTableSqlNodeConverter implements SqlNodeConverter<SimpleTableSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final ProjectionsSegment projectionsSegment) {
-        if (projectionsSegment.isDistinctRow()) {
-            return Optional.of(new SqlNodeList(Collections.singletonList(SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO)), SqlParserPos.ZERO));
+    public Optional<SqlNode> convert(final SimpleTableSegment simpleTable) {
+        TableNameSegment tableName = simpleTable.getTableName();
+        SqlNode tableNameSqlNode = new SqlIdentifier(tableName.getIdentifier().getValue(), SqlParserPos.ZERO);
+        SqlNode sqlNode;
+        if (simpleTable.getAlias().isPresent()) {
+            SqlNode aliasIdentifier = new SqlIdentifier(simpleTable.getAlias().get(), SqlParserPos.ZERO);
+            sqlNode = new SqlBasicCall(SqlStdOperatorTable.AS, new SqlNode[] {tableNameSqlNode, aliasIdentifier}, SqlParserPos.ZERO);
+        } else {
+            sqlNode = tableNameSqlNode;
         }
-        return Optional.empty();
+        return Optional.of(sqlNode);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/SubqueryTableSqlNodeConverter.java
similarity index 68%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/SubqueryTableSqlNodeConverter.java
index a7a7c0f..c265ac3 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/OffsetSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/SubqueryTableSqlNodeConverter.java
@@ -19,20 +19,18 @@ package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
 import org.apache.calcite.sql.SqlNode;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 
 import java.util.Optional;
 
 /**
- * Offset sql node converter.
+ * Subquery converter.
  */
-public final class OffsetSqlNodeConverter implements SqlNodeConverter<LimitSegment> {
+public final class SubqueryTableSqlNodeConverter implements SqlNodeConverter<SubqueryTableSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final LimitSegment limitSegment) {
-        if (null == limitSegment || !limitSegment.getOffset().isPresent()) {
-            return Optional.empty();
-        }
-        return new PaginationValueSqlConverter().convert(limitSegment.getOffset().get());
+    public Optional<SqlNode> convert(final SubqueryTableSegment astNode) {
+        // TODO 
+        return Optional.empty();
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/TableSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/TableSqlNodeConverter.java
new file mode 100644
index 0000000..ab10513
--- /dev/null
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/TableSqlNodeConverter.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
+
+import org.apache.calcite.sql.SqlNode;
+import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
+
+import java.util.Optional;
+
+/**
+ * convert from clause.
+ */
+public final class TableSqlNodeConverter implements SqlNodeConverter<TableSegment, SqlNode> {
+    
+    @Override
+    public Optional<SqlNode> convert(final TableSegment table) {
+        if (table instanceof SimpleTableSegment) {
+            return new SimpleTableSqlNodeConverter().convert((SimpleTableSegment) table);
+        } else if (table instanceof JoinTableSegment) {
+            return new JoinTableSqlNodeConverter().convert((JoinTableSegment) table);
+        } else if (table instanceof SubqueryTableSegment) {
+            return new SubqueryTableSqlNodeConverter().convert((SubqueryTableSegment) table);
+        }
+        throw new UnsupportedOperationException("unsupportd TableSegment type: " + table.getClass());
+    }
+}
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/WhereSqlNodeConverter.java
similarity index 72%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/WhereSqlNodeConverter.java
index ad50960..bce5f99 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/RowCountSqlNodeConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/convert/converter/impl/WhereSqlNodeConverter.java
@@ -19,20 +19,22 @@ package org.apache.shardingsphere.infra.optimize.core.convert.converter.impl;
 
 import org.apache.calcite.sql.SqlNode;
 import org.apache.shardingsphere.infra.optimize.core.convert.converter.SqlNodeConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
 
 import java.util.Optional;
 
 /**
- * Row count sql node converter.
+ * Where converter.
  */
-public final class RowCountSqlNodeConverter implements SqlNodeConverter<LimitSegment> {
+public final class WhereSqlNodeConverter implements SqlNodeConverter<WhereSegment, SqlNode> {
     
     @Override
-    public Optional<SqlNode> convert(final LimitSegment limitSegment) {
-        if (null == limitSegment || !limitSegment.getRowCount().isPresent()) {
+    public Optional<SqlNode> convert(final WhereSegment where) {
+        if (where == null) {
             return Optional.empty();
         }
-        return new PaginationValueSqlConverter().convert(limitSegment.getRowCount().get());
+        ExpressionSegment whereExpr = where.getExpr();
+        return new ExpressionSqlNodeConverter().convert(whereExpr);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/operator/BinarySqlOperator.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/operator/BinarySqlOperator.java
new file mode 100644
index 0000000..bb6eaca
--- /dev/null
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/operator/BinarySqlOperator.java
@@ -0,0 +1,72 @@
+/*
+ * 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.core.operator;
+
+import org.apache.calcite.sql.SqlBinaryOperator;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+
+/**
+ * binary sql operator.
+ */
+public enum BinarySqlOperator {
+
+    EQUALS("=", SqlStdOperatorTable.EQUALS),
+
+    GREATER_THAN(">", SqlStdOperatorTable.GREATER_THAN),
+
+    GREATER_EQUALS_THAN(">=", SqlStdOperatorTable.GREATER_THAN_OR_EQUAL),
+
+    LESS_THAN("<", SqlStdOperatorTable.LESS_THAN),
+
+    LESS_EQUALS_THAN("<=", SqlStdOperatorTable.LESS_THAN_OR_EQUAL),
+
+    AND("AND", SqlStdOperatorTable.AND),
+
+    NONE("", null);
+
+    private final String operator;
+
+    private final SqlBinaryOperator sqlBinaryOperator;
+
+    BinarySqlOperator(final String operator, final SqlBinaryOperator sqlBinaryOperator) {
+        this.operator = operator;
+        this.sqlBinaryOperator = sqlBinaryOperator;
+    }
+
+    /**
+     * Get binary operator. 
+     * @return sql binary operator
+     */
+    public SqlBinaryOperator getSqlBinaryOperator() {
+        return sqlBinaryOperator;
+    }
+
+    /**
+     * convert string to BinarySqlOperator.
+     * @param sqlOperator string type of sqlOperator
+     * @return <code>BinarySqlOperator</code>
+     */
+    public static BinarySqlOperator value(final String sqlOperator) {
+        for (BinarySqlOperator val : values()) {
+            if (val.operator.equalsIgnoreCase(sqlOperator)) {
+                return val;
+            }
+        }
+        throw new UnsupportedOperationException("unsupported sql operator: " + sqlOperator);
+    }
+}
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/test/java/org/apache/shardingsphere/infra/optimize/core/convert/SelectStatementSqlNodeConverterTest.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/test/java/org/apache/shardingsphere/infra/optimize/core/convert/SelectStatementSqlNodeConverterTest.java
new file mode 100644
index 0000000..834bf97
--- /dev/null
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/test/java/org/apache/shardingsphere/infra/optimize/core/convert/SelectStatementSqlNodeConverterTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.core.convert;
+
+import org.apache.calcite.sql.SqlJoin;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlSelect;
+import org.apache.shardingsphere.infra.database.type.DatabaseTypeRegistry;
+import org.apache.shardingsphere.infra.database.type.dialect.MySQLDatabaseType;
+import org.apache.shardingsphere.infra.parser.ShardingSphereSQLParserEngine;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+/**
+ * testcase of converting shardingshphere ast to calcite ast.
+ *
+ * <p>after converting phrase finished, the next phrase is comparing  the converted result with the
+ * result of calcite parser.
+ * </p>
+ */
+public final class SelectStatementSqlNodeConverterTest {
+
+    private ShardingSphereSQLParserEngine sqlStatementParserEngine;
+
+    @Before
+    public void init() {
+        sqlStatementParserEngine = new ShardingSphereSQLParserEngine(DatabaseTypeRegistry.getTrunkDatabaseTypeName(
+                new MySQLDatabaseType()));
+    }
+
+    @Test
+    public void testConvertSimpleSelect() {
+        String sql = "select order_id, user_id from t_order";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        Optional<SqlNode> optional = SqlNodeConvertEngine.convert(sqlStatement);
+        assertTrue(optional.isPresent());
+        Assert.assertThat(optional.get(), instanceOf(SqlSelect.class));
+        SqlSelect sqlSelect = (SqlSelect) optional.get();
+        assertEquals(2, sqlSelect.getSelectList().size());
+        assertNull(sqlSelect.getWhere());
+        assertNull(sqlSelect.getOffset());
+        assertNull(sqlSelect.getFetch());
+        /* 
+         TODO compare ast from calcite parser and ast converted from ss ast if possible
+        SqlParser parser = SqlParser.create(sql);
+        SqlNode calciteSqlNode = parser.parseQuery();
+        Assert.assertNotNull(calciteSqlNode);
+        */
+    }
+
+    @Test
+    public void testConvertSimpleSelectLimit() {
+        String sql = "select order_id, user_id from t_order limit 1, 2";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        Optional<SqlNode> optional = SqlNodeConvertEngine.convert(sqlStatement);
+        assertTrue(optional.isPresent());
+        Assert.assertThat(optional.get(), instanceOf(SqlSelect.class));
+        SqlSelect sqlSelect = (SqlSelect) optional.get();
+        assertEquals(2, sqlSelect.getSelectList().size());
+        assertNull(sqlSelect.getWhere());
+        assertNotNull(sqlSelect.getOffset());
+        assertNotNull(sqlSelect.getFetch());
+    }
+
+    @Test
+    public void testConvertSimpleSelectRowCount() {
+        String sql = "select order_id, user_id from t_order limit 2";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        Optional<SqlNode> optional = SqlNodeConvertEngine.convert(sqlStatement);
+        assertTrue(optional.isPresent());
+        Assert.assertThat(optional.get(), instanceOf(SqlSelect.class));
+        SqlSelect sqlSelect = (SqlSelect) optional.get();
+        assertEquals(2, sqlSelect.getSelectList().size());
+        assertNull(sqlSelect.getWhere());
+        assertNull(sqlSelect.getOffset());
+        assertNotNull(sqlSelect.getFetch());
+    }
+
+    @Test
+    public void testConvertSimpleSelectFilter() {
+        String sql = "select order_id, user_id from t_order where order_id = 10";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        Optional<SqlNode> optional = SqlNodeConvertEngine.convert(sqlStatement);
+        assertTrue(optional.isPresent());
+        Assert.assertThat(optional.get(), instanceOf(SqlSelect.class));
+        SqlSelect sqlSelect = (SqlSelect) optional.get();
+        assertEquals(2, sqlSelect.getSelectList().size());
+        assertNotNull(sqlSelect.getWhere());
+    }
+
+    @Test
+    public void testConvertSimpleSelectFilterGroupBy() {
+        String sql = "select order_id, user_id from t_order where order_id = 10 group by order_id";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        Optional<SqlNode> optional = SqlNodeConvertEngine.convert(sqlStatement);
+        assertTrue(optional.isPresent());
+        Assert.assertThat(optional.get(), instanceOf(SqlSelect.class));
+        SqlSelect sqlSelect = (SqlSelect) optional.get();
+        assertEquals(2, sqlSelect.getSelectList().size());
+        assertNotNull(sqlSelect.getWhere());
+        assertEquals(1, sqlSelect.getGroup().size());
+    }
+
+    @Test
+    public void testConvertSimpleSelectFilterOrderBy() {
+        String sql = "select order_id, user_id from t_order where user_id = 10 order by order_id desc";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        Optional<SqlNode> optional = SqlNodeConvertEngine.convert(sqlStatement);
+        assertTrue(optional.isPresent());
+        assertThat(optional.get(), instanceOf(SqlSelect.class));
+        SqlSelect sqlSelect = (SqlSelect) optional.get();
+        assertEquals(2, sqlSelect.getSelectList().size());
+        assertNotNull(sqlSelect.getWhere());
+        assertEquals(1, sqlSelect.getOrderList().size());
+    }
+
+    @Test
+    public void testConvertInnerJoin() {
+        String sql = "select 10 + 30, o1.order_id + 10, o1.order_id, o1.user_id, o2.status from t_order o1 join t_order_item o2 on "
+                + "o1.order_id = o2.order_id where o1.status='FINISHED' and o2.order_item_id > 1024 and 1=1 order by "
+                + "o1.order_id desc";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        Optional<SqlNode> optional = SqlNodeConvertEngine.convert(sqlStatement);
+        assertTrue(optional.isPresent());
+        assertThat(optional.get(), instanceOf(SqlSelect.class));
+        SqlSelect sqlSelect = (SqlSelect) optional.get();
+        assertThat(sqlSelect.getFrom(), instanceOf(SqlJoin.class));
+        assertEquals(1, sqlSelect.getOrderList().size());
+    }
+
+    @Test
+    public void testConvertLeftOuterJoin() {
+        String sql = "select 10 + 30, o1.order_id + 10, o1.order_id, o1.user_id, o2.status from t_order o1 left outer join t_order_item o2 on "
+                + "o1.order_id = o2.order_id where o1.status='FINISHED' and o2.order_item_id > 1024 and 1=1 order by "
+                + "o1.order_id desc";
+        SQLStatement sqlStatement = sqlStatementParserEngine.parse(sql, false);
+        Optional<SqlNode> optional = SqlNodeConvertEngine.convert(sqlStatement);
+        assertTrue(optional.isPresent());
+        // TODO outer join is not supported by parser of ShardingSphere 
+    }
+}