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/18 03:04:07 UTC

[shardingsphere] branch master updated: optimize select group by having with calcite (#10848)

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 514117f  optimize select group by having with calcite (#10848)
514117f is described below

commit 514117f16278fb76ddd891a23d3db804039371bd
Author: Zhengqiang Duan <st...@gmail.com>
AuthorDate: Fri Jun 18 11:03:36 2021 +0800

    optimize select group by having with calcite (#10848)
    
    * optimize select group by having with calcite
    
    * fix ut error
    
    * optimize for code review
    
    * optimize for code review
---
 .../merge/dal/show/LogicTablesMergedResult.java    |  3 +-
 .../merge/dal/show/ShowIndexMergedResult.java      |  3 +-
 .../merge/dql/ShardingDQLResultMerger.java         | 15 ----
 .../dql/groupby/GroupByMemoryMergedResult.java     | 19 +++--
 .../having/HavingDecoratorMergedResult.java        | 84 -------------------
 .../engine/type/ShardingRouteEngineFactory.java    | 11 ++-
 .../binder/segment/select/having/HavingColumn.java | 36 ---------
 .../segment/select/having/HavingContext.java       | 37 ---------
 .../select/having/engine/HavingContextEngine.java  | 93 ----------------------
 .../statement/dml/SelectStatementContext.java      | 20 +----
 .../federate/schema/row/FederateRowEnumerator.java |  6 +-
 .../federate/schema/row/FederateRowExecutor.java   |  8 +-
 .../schema/table/FederateFilterableTable.java      |  3 +-
 .../generator/FederateExecutionSQLGenerator.java   | 11 ++-
 .../result/impl/memory/MemoryMergedResult.java     | 13 +--
 .../result/impl/memory/MemoryQueryResultRow.java   | 13 ---
 .../memory/fixture/TestMemoryMergedResult.java     |  5 +-
 .../core/metadata/FederateTableMetadata.java       | 16 +++-
 .../generator/generic/RemoveTokenGenerator.java    | 11 +--
 .../DatabaseCommunicationEngineTest.java           |  3 +-
 .../segment/dml/predicate/HavingSegment.java       |  4 +-
 .../resources/scenario/sharding/case/select.xml    |  9 +--
 22 files changed, 62 insertions(+), 361 deletions(-)

diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dal/show/LogicTablesMergedResult.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dal/show/LogicTablesMergedResult.java
index ee98148..0719da8 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dal/show/LogicTablesMergedResult.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dal/show/LogicTablesMergedResult.java
@@ -19,7 +19,6 @@ package org.apache.shardingsphere.sharding.merge.dal.show;
 
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
-import org.apache.shardingsphere.infra.merge.result.MergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryMergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryQueryResultRow;
 import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
@@ -46,7 +45,7 @@ public class LogicTablesMergedResult extends MemoryMergedResult<ShardingRule> {
     
     @Override
     protected final List<MemoryQueryResultRow> init(final ShardingRule shardingRule, final ShardingSphereSchema schema,
-                                                    final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults, final MergedResult mergedResult) throws SQLException {
+                                                    final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults) throws SQLException {
         List<MemoryQueryResultRow> result = new LinkedList<>();
         Set<String> tableNames = new HashSet<>();
         for (QueryResult each : queryResults) {
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dal/show/ShowIndexMergedResult.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dal/show/ShowIndexMergedResult.java
index 09da310..5d96993 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dal/show/ShowIndexMergedResult.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dal/show/ShowIndexMergedResult.java
@@ -19,7 +19,6 @@ package org.apache.shardingsphere.sharding.merge.dal.show;
 
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
-import org.apache.shardingsphere.infra.merge.result.MergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryMergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryQueryResultRow;
 import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
@@ -44,7 +43,7 @@ public class ShowIndexMergedResult extends MemoryMergedResult<ShardingRule> {
     
     @Override
     protected final List<MemoryQueryResultRow> init(final ShardingRule shardingRule, final ShardingSphereSchema schema,
-                                                    final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults, final MergedResult mergedResult) throws SQLException {
+                                                    final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults) throws SQLException {
         List<MemoryQueryResultRow> result = new LinkedList<>();
         for (QueryResult each : queryResults) {
             while (each.next()) {
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/ShardingDQLResultMerger.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/ShardingDQLResultMerger.java
index 891fb25..3c5544f 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/ShardingDQLResultMerger.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/ShardingDQLResultMerger.java
@@ -18,7 +18,6 @@
 package org.apache.shardingsphere.sharding.merge.dql;
 
 import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.infra.binder.segment.select.having.HavingContext;
 import org.apache.shardingsphere.infra.binder.segment.select.orderby.OrderByItem;
 import org.apache.shardingsphere.infra.binder.segment.select.pagination.PaginationContext;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
@@ -31,7 +30,6 @@ import org.apache.shardingsphere.infra.merge.result.MergedResult;
 import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
 import org.apache.shardingsphere.sharding.merge.dql.groupby.GroupByMemoryMergedResult;
 import org.apache.shardingsphere.sharding.merge.dql.groupby.GroupByStreamMergedResult;
-import org.apache.shardingsphere.sharding.merge.dql.groupby.having.HavingDecoratorMergedResult;
 import org.apache.shardingsphere.sharding.merge.dql.iterator.IteratorStreamMergedResult;
 import org.apache.shardingsphere.sharding.merge.dql.orderby.OrderByStreamMergedResult;
 import org.apache.shardingsphere.sharding.merge.dql.pagination.LimitDecoratorMergedResult;
@@ -117,19 +115,6 @@ public final class ShardingDQLResultMerger implements ResultMerger {
     }
     
     private MergedResult decorate(final List<QueryResult> queryResults, final SelectStatementContext selectStatementContext, final MergedResult mergedResult) throws SQLException {
-        MergedResult decoratedMergedResult = decorateHavingContext(queryResults, selectStatementContext, mergedResult);
-        return decoratePaginationContext(queryResults, selectStatementContext, decoratedMergedResult);
-    }
-    
-    private MergedResult decorateHavingContext(final List<QueryResult> queryResults, final SelectStatementContext selectStatementContext, final MergedResult mergedResult) throws SQLException {
-        HavingContext havingContext = selectStatementContext.getHavingContext();
-        if (!havingContext.isHasHaving() || 1 == queryResults.size()) {
-            return mergedResult;
-        }
-        return new HavingDecoratorMergedResult(selectStatementContext, mergedResult);
-    }
-    
-    private MergedResult decoratePaginationContext(final List<QueryResult> queryResults, final SelectStatementContext selectStatementContext, final MergedResult mergedResult) throws SQLException {
         PaginationContext paginationContext = selectStatementContext.getPaginationContext();
         if (!paginationContext.isHasPagination() || 1 == queryResults.size()) {
             return mergedResult;
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/groupby/GroupByMemoryMergedResult.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/groupby/GroupByMemoryMergedResult.java
index adbbea5..5f719ff 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/groupby/GroupByMemoryMergedResult.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/groupby/GroupByMemoryMergedResult.java
@@ -20,21 +20,20 @@ package org.apache.shardingsphere.sharding.merge.dql.groupby;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection;
+import org.apache.shardingsphere.infra.binder.segment.select.projection.impl.AggregationDistinctProjection;
+import org.apache.shardingsphere.infra.binder.segment.select.projection.impl.AggregationProjection;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
-import org.apache.shardingsphere.infra.merge.result.MergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryMergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryQueryResultRow;
+import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
+import org.apache.shardingsphere.infra.metadata.schema.model.ColumnMetaData;
+import org.apache.shardingsphere.infra.metadata.schema.model.TableMetaData;
 import org.apache.shardingsphere.sharding.merge.dql.groupby.aggregation.AggregationUnit;
 import org.apache.shardingsphere.sharding.merge.dql.groupby.aggregation.AggregationUnitFactory;
 import org.apache.shardingsphere.sharding.rule.ShardingRule;
-import org.apache.shardingsphere.infra.metadata.schema.model.ColumnMetaData;
-import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
-import org.apache.shardingsphere.infra.metadata.schema.model.TableMetaData;
-import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection;
-import org.apache.shardingsphere.infra.binder.segment.select.projection.impl.AggregationDistinctProjection;
-import org.apache.shardingsphere.infra.binder.segment.select.projection.impl.AggregationProjection;
-import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
-import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.sql.parser.sql.common.constant.AggregationType;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 
@@ -58,7 +57,7 @@ public final class GroupByMemoryMergedResult extends MemoryMergedResult<Sharding
     
     @Override
     protected List<MemoryQueryResultRow> init(final ShardingRule shardingRule, final ShardingSphereSchema schema, 
-                                              final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults, final MergedResult mergedResult) throws SQLException {
+                                              final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults) throws SQLException {
         SelectStatementContext selectStatementContext = (SelectStatementContext) sqlStatementContext;
         Map<GroupByValue, MemoryQueryResultRow> dataMap = new HashMap<>(1024);
         Map<GroupByValue, Map<AggregationProjection, AggregationUnit>> aggregationMap = new HashMap<>(1024);
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/groupby/having/HavingDecoratorMergedResult.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/groupby/having/HavingDecoratorMergedResult.java
deleted file mode 100644
index f90b209..0000000
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/groupby/having/HavingDecoratorMergedResult.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.sharding.merge.dql.groupby.having;
-
-import groovy.lang.GroovyShell;
-import groovy.lang.Script;
-import org.apache.shardingsphere.infra.binder.segment.select.having.HavingColumn;
-import org.apache.shardingsphere.infra.binder.segment.select.having.HavingContext;
-import org.apache.shardingsphere.infra.binder.segment.select.projection.ProjectionsContext;
-import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
-import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
-import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
-import org.apache.shardingsphere.infra.merge.result.MergedResult;
-import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryMergedResult;
-import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryQueryResultRow;
-import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
-import org.apache.shardingsphere.sharding.rule.ShardingRule;
-
-import java.sql.SQLException;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Decorator merged result for having.
- */
-public final class HavingDecoratorMergedResult extends MemoryMergedResult<ShardingRule> {
-    
-    private static final GroovyShell SHELL = new GroovyShell();
-    
-    public HavingDecoratorMergedResult(final SQLStatementContext sqlStatementContext, final MergedResult mergedResult) throws SQLException {
-        super(sqlStatementContext, mergedResult);
-    }
-    
-    @Override
-    protected List<MemoryQueryResultRow> init(final ShardingRule rule, final ShardingSphereSchema schema, final SQLStatementContext sqlStatementContext, 
-                                              final List<QueryResult> queryResults, final MergedResult mergedResult) throws SQLException {
-        SelectStatementContext selectStatementContext = (SelectStatementContext) sqlStatementContext;
-        HavingContext havingContext = selectStatementContext.getHavingContext();
-        ProjectionsContext projectionsContext = selectStatementContext.getProjectionsContext();
-        List<MemoryQueryResultRow> result = new LinkedList<>();
-        while (mergedResult.next()) {
-            MemoryQueryResultRow memoryResultSetRow = new MemoryQueryResultRow(mergedResult, projectionsContext.getProjections().size());
-            if (havingContext.isHasHaving()) {
-                // TODO support more expr scenario, like in, between and ... 
-                Object evaluate = evaluate(generateHavingExpression(havingContext, memoryResultSetRow));
-                if (evaluate instanceof Boolean && ((Boolean) evaluate)) {
-                    result.add(memoryResultSetRow);
-                }
-            } else {
-                result.add(memoryResultSetRow);
-            }
-        }
-        return result;
-    }
-    
-    private String generateHavingExpression(final HavingContext havingContext, final MemoryQueryResultRow memoryResultSetRow) {
-        String expression = havingContext.getHavingExpression().toLowerCase();
-        expression = expression.replaceAll("\\s+=\\s+", " == ").replaceAll("\\s+and\\s+", " && ").replaceAll("\\s+or\\s+", " || ");
-        for (HavingColumn each : havingContext.getColumns()) {
-            expression = expression.replace(each.getSegment().getIdentifier().getValue().toLowerCase(), memoryResultSetRow.getCell(each.getIndex()).toString());
-        }
-        return expression;
-    }
-    
-    private Object evaluate(final String expression) {
-        Script script = SHELL.parse(expression);
-        return script.run();
-    }
-}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/ShardingRouteEngineFactory.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/ShardingRouteEngineFactory.java
index 6ab73d4..d06b785 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/ShardingRouteEngineFactory.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/ShardingRouteEngineFactory.java
@@ -169,7 +169,7 @@ public final class ShardingRouteEngineFactory {
         if (!shardingRule.tableRuleExists(tableNames)) {
             return new SingleTablesRoutingEngine(tableNames, sqlStatement);
         }
-        if (shardingRule.isAllShardingTables(tableNames) && 1 == tableNames.size() || shardingRule.isAllBindingTables(tableNames)) {
+        if (isShardingStandardQuery(sqlStatementContext, shardingRule, tableNames)) {
             return new ShardingStandardRoutingEngine(tableNames.iterator().next(), shardingConditions, props);
         }
         if (isShardingFederatedQuery(sqlStatementContext, tableNames, shardingRule)) {
@@ -179,15 +179,20 @@ public final class ShardingRouteEngineFactory {
         return new ShardingComplexRoutingEngine(tableNames, shardingConditions, props);
     }
     
+    private static boolean isShardingStandardQuery(final SQLStatementContext<?> sqlStatementContext, final ShardingRule shardingRule, final Collection<String> tableNames) {
+        boolean containsHaving = sqlStatementContext instanceof SelectStatementContext && ((SelectStatementContext) sqlStatementContext).isContainsHaving(); 
+        return (shardingRule.isAllBindingTables(tableNames) || shardingRule.isAllShardingTables(tableNames) && 1 == tableNames.size()) && !containsHaving;
+    }
+    
     private static boolean isShardingFederatedQuery(final SQLStatementContext<?> sqlStatementContext, final Collection<String> tableNames, final ShardingRule shardingRule) {
         if (!(sqlStatementContext instanceof SelectStatementContext)) {
             return false;
         }
         SelectStatementContext select = (SelectStatementContext) sqlStatementContext;
-        if (!select.isContainsJoinQuery() && !select.isContainsSubquery()) {
+        if (!select.isContainsJoinQuery() && !select.isContainsSubquery() && !select.isContainsHaving()) {
             return false;
         }
-        if (shardingRule.isAllTablesInSameDataSource(tableNames)) {
+        if (shardingRule.isAllTablesInSameDataSource(tableNames) && !select.isContainsHaving()) {
             return false;
         }
         return shardingRule.isAllShardingTables(tableNames) || (shardingRule.tableRuleExists(tableNames) && shardingRule.singleTableRuleExists(tableNames));
diff --git a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/having/HavingColumn.java b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/having/HavingColumn.java
deleted file mode 100644
index 3a56958..0000000
--- a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/having/HavingColumn.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.binder.segment.select.having;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-
-/**
- * Having column.
- */
-@RequiredArgsConstructor
-@Getter
-@Setter
-public final class HavingColumn {
-    
-    private final ColumnSegment segment;
-    
-    private int index;
-}
diff --git a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/having/HavingContext.java b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/having/HavingContext.java
deleted file mode 100644
index c5fcb57..0000000
--- a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/having/HavingContext.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.binder.segment.select.having;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-import java.util.Collection;
-
-/**
- * Having context.
- */
-@RequiredArgsConstructor
-@Getter
-public final class HavingContext {
-    
-    private final String havingExpression;
-    
-    private final boolean hasHaving;
-    
-    private final Collection<HavingColumn> columns;
-}
diff --git a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/having/engine/HavingContextEngine.java b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/having/engine/HavingContextEngine.java
deleted file mode 100644
index 5be02e4..0000000
--- a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/having/engine/HavingContextEngine.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.binder.segment.select.having.engine;
-
-import org.apache.shardingsphere.infra.binder.segment.select.having.HavingColumn;
-import org.apache.shardingsphere.infra.binder.segment.select.having.HavingContext;
-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.item.AggregationProjectionSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.HavingSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
-import org.apache.shardingsphere.sql.parser.sql.common.util.SQLUtil;
-import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
-
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.Optional;
-
-/**
- * Having context engine.
- */
-public final class HavingContextEngine {
-    
-    /**
-     * Create having context.
-     *
-     * @param selectStatement select statement
-     * @return having context
-     */
-    public HavingContext createHavingContext(final SelectStatement selectStatement) {
-        Optional<HavingSegment> havingSegment = selectStatement.getHaving();
-        if (!havingSegment.isPresent()) {
-            return new HavingContext(null, false, new LinkedList<>());
-        }
-        Collection<HavingColumn> columns = new LinkedList<>();
-        ExpressionSegment segment = havingSegment.get().getExpr();
-        extractHavingColumn(segment, columns);
-        String havingExpression = segment instanceof BinaryOperationExpression ? ((BinaryOperationExpression) segment).getText() : "";
-        return new HavingContext(havingExpression, !columns.isEmpty(), columns);
-    }
-    
-    private void extractHavingColumn(final ExpressionSegment expression, final Collection<HavingColumn> columns) {
-        if (expression instanceof BinaryOperationExpression) {
-            extractHavingColumnFromBinaryOperationExpression(((BinaryOperationExpression) expression).getLeft(), columns);
-            extractHavingColumnFromBinaryOperationExpression(((BinaryOperationExpression) expression).getRight(), columns);
-        }
-    }
-    
-    private void extractHavingColumnFromBinaryOperationExpression(final ExpressionSegment expression, final Collection<HavingColumn> columns) {
-        if (expression instanceof BinaryOperationExpression) {
-            extractHavingColumn(expression, columns);
-        }
-        if (expression instanceof AggregationProjectionSegment) {
-            extractHavingColumnFromAggregationProjectionSegment((AggregationProjectionSegment) expression, columns);
-        }
-        if (expression instanceof ExpressionProjectionSegment) {
-            extractHavingColumnFromExpressionProjectionSegment((ExpressionProjectionSegment) expression, columns);
-        }
-        if (expression instanceof ColumnSegment) {
-            extractHavingColumnFromColumnSegment((ColumnSegment) expression, columns);
-        }
-    }
-    
-    private void extractHavingColumnFromColumnSegment(final ColumnSegment segment, final Collection<HavingColumn> columns) {
-        columns.add(new HavingColumn(segment));
-    }
-    
-    private void extractHavingColumnFromExpressionProjectionSegment(final ExpressionProjectionSegment segment, final Collection<HavingColumn> columns) {
-        columns.add(new HavingColumn(new ColumnSegment(segment.getStartIndex(), segment.getStopIndex(), new IdentifierValue(segment.getText()))));
-    }
-    
-    private void extractHavingColumnFromAggregationProjectionSegment(final AggregationProjectionSegment segment, final Collection<HavingColumn> columns) {
-        String columnLabel = SQLUtil.getExactlyValue(segment.getType().name() + segment.getInnerExpression());
-        columns.add(new HavingColumn(new ColumnSegment(segment.getStartIndex(), segment.getStopIndex(), new IdentifierValue(columnLabel))));
-    }
-}
diff --git a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/SelectStatementContext.java b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/SelectStatementContext.java
index 55b02f4..c4ba413 100644
--- a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/SelectStatementContext.java
+++ b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/SelectStatementContext.java
@@ -21,9 +21,6 @@ import com.google.common.base.Preconditions;
 import lombok.Getter;
 import org.apache.shardingsphere.infra.binder.segment.select.groupby.GroupByContext;
 import org.apache.shardingsphere.infra.binder.segment.select.groupby.engine.GroupByContextEngine;
-import org.apache.shardingsphere.infra.binder.segment.select.having.HavingColumn;
-import org.apache.shardingsphere.infra.binder.segment.select.having.HavingContext;
-import org.apache.shardingsphere.infra.binder.segment.select.having.engine.HavingContextEngine;
 import org.apache.shardingsphere.infra.binder.segment.select.orderby.OrderByContext;
 import org.apache.shardingsphere.infra.binder.segment.select.orderby.OrderByItem;
 import org.apache.shardingsphere.infra.binder.segment.select.orderby.engine.OrderByContextEngine;
@@ -73,8 +70,6 @@ public final class SelectStatementContext extends CommonSQLStatementContext<Sele
     
     private final GroupByContext groupByContext;
     
-    private final HavingContext havingContext;
-    
     private final OrderByContext orderByContext;
     
     private final PaginationContext paginationContext;
@@ -82,6 +77,8 @@ public final class SelectStatementContext extends CommonSQLStatementContext<Sele
     private final boolean containsSubquery;
     
     private final int generateOrderByStartIndex;
+    
+    private final boolean containsHaving;
 
     // TODO to be remove, for test case only
     public SelectStatementContext(final SelectStatement sqlStatement, final GroupByContext groupByContext,
@@ -89,24 +86,24 @@ public final class SelectStatementContext extends CommonSQLStatementContext<Sele
         super(sqlStatement);
         tablesContext = new TablesContext(getAllSimpleTableSegments());
         this.groupByContext = groupByContext;
-        this.havingContext = new HavingContextEngine().createHavingContext(sqlStatement);
         this.orderByContext = orderByContext;
         this.projectionsContext = projectionsContext;
         this.paginationContext = paginationContext;
         containsSubquery = containsSubquery();
         generateOrderByStartIndex = generateOrderByStartIndex();
+        containsHaving = sqlStatement.getHaving().isPresent();
     }
     
     public SelectStatementContext(final ShardingSphereSchema schema, final List<Object> parameters, final SelectStatement sqlStatement) {
         super(sqlStatement);
         tablesContext = new TablesContext(getAllSimpleTableSegments());
         groupByContext = new GroupByContextEngine().createGroupByContext(sqlStatement);
-        havingContext = new HavingContextEngine().createHavingContext(sqlStatement);
         orderByContext = new OrderByContextEngine().createOrderBy(schema, sqlStatement, groupByContext);
         projectionsContext = new ProjectionsContextEngine(schema).createProjectionsContext(getFromSimpleTableSegments(), getSqlStatement().getProjections(), groupByContext, orderByContext);
         paginationContext = new PaginationContextEngine().createPaginationContext(sqlStatement, projectionsContext, parameters);
         containsSubquery = containsSubquery();
         generateOrderByStartIndex = generateOrderByStartIndex();
+        containsHaving = sqlStatement.getHaving().isPresent();
     }
     
     private boolean containsSubquery() {
@@ -148,15 +145,6 @@ public final class SelectStatementContext extends CommonSQLStatementContext<Sele
         setIndexForAggregationProjection(columnLabelIndexMap);
         setIndexForOrderItem(columnLabelIndexMap, orderByContext.getItems());
         setIndexForOrderItem(columnLabelIndexMap, groupByContext.getItems());
-        setIndexForHaving(columnLabelIndexMap);
-    }
-    
-    private void setIndexForHaving(final Map<String, Integer> columnLabelIndexMap) {
-        for (HavingColumn each : havingContext.getColumns()) {
-            String columnLabel = each.getSegment().getIdentifier().getValue();
-            Preconditions.checkState(columnLabelIndexMap.containsKey(columnLabel), "Can't find index: %s.", each);
-            each.setIndex(columnLabelIndexMap.get(columnLabel));
-        }
     }
     
     private void setIndexForAggregationProjection(final Map<String, Integer> columnLabelIndexMap) {
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/row/FederateRowEnumerator.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/row/FederateRowEnumerator.java
index 3168738..20ef504 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/row/FederateRowEnumerator.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/row/FederateRowEnumerator.java
@@ -70,11 +70,7 @@ public final class FederateRowEnumerator implements Enumerator<Object[]> {
             return false;
         }
         currentResultSet = iterator.next();
-        if (currentResultSet.next()) {
-            setCurrentRow();
-            return true;
-        }
-        return false;
+        return moveNext0();
     }
     
     private void setCurrentRow() throws SQLException {
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/row/FederateRowExecutor.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/row/FederateRowExecutor.java
index 81f3942..1761a82 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/row/FederateRowExecutor.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/row/FederateRowExecutor.java
@@ -33,6 +33,7 @@ import org.apache.shardingsphere.infra.executor.sql.federate.schema.table.genera
 import org.apache.shardingsphere.infra.executor.sql.federate.schema.table.generator.FederateExecutionSQLGenerator;
 import org.apache.shardingsphere.infra.executor.sql.prepare.driver.DriverExecutionPrepareEngine;
 import org.apache.shardingsphere.infra.executor.sql.process.ExecuteProcessEngine;
+import org.apache.shardingsphere.infra.optimize.core.metadata.FederateTableMetadata;
 
 import java.sql.Connection;
 import java.sql.SQLException;
@@ -59,14 +60,15 @@ public final class FederateRowExecutor {
     /**
      * Execute.
      *
-     * @param logicTable logic table
+     * @param metadata metadata
      * @param root root
      * @param filters filter
      * @param projects projects
      * @return a query result list
      */
-    public Collection<QueryResult> execute(final String logicTable, final DataContext root, final List<RexNode> filters, final int[] projects) {
-        FederateExecutionContextGenerator generator = new FederateExecutionContextGenerator(logicTable, routeExecutionContext, new FederateExecutionSQLGenerator(root, filters, projects));
+    public Collection<QueryResult> execute(final FederateTableMetadata metadata, final DataContext root, final List<RexNode> filters, final int[] projects) {
+        FederateExecutionContextGenerator generator = new FederateExecutionContextGenerator(metadata.getName(), routeExecutionContext, 
+                new FederateExecutionSQLGenerator(root, filters, projects, metadata.getColumnNames()));
         return execute(generator.generate());
     }
     
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/table/FederateFilterableTable.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/table/FederateFilterableTable.java
index 4ef40e6..f00e207 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/table/FederateFilterableTable.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/table/FederateFilterableTable.java
@@ -42,10 +42,9 @@ public final class FederateFilterableTable extends AbstractFederateTable impleme
     @Override
     public Enumerable<Object[]> scan(final DataContext root, final List<RexNode> filters, final int[] projects) {
         return new AbstractEnumerable<Object[]>() {
-
             @Override
             public Enumerator<Object[]> enumerator() {
-                return new FederateRowEnumerator(getExecutor().execute(getMetadata().getName(), root, filters, projects));
+                return new FederateRowEnumerator(getExecutor().execute(getMetadata(), root, filters, projects));
             }
         };
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/table/generator/FederateExecutionSQLGenerator.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/table/generator/FederateExecutionSQLGenerator.java
index 2df025b..9364dcc 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/table/generator/FederateExecutionSQLGenerator.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/federate/schema/table/generator/FederateExecutionSQLGenerator.java
@@ -17,11 +17,15 @@
 
 package org.apache.shardingsphere.infra.executor.sql.federate.schema.table.generator;
 
+import com.google.common.base.Joiner;
 import lombok.RequiredArgsConstructor;
 import org.apache.calcite.DataContext;
 import org.apache.calcite.rex.RexNode;
 
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * Federate execution sql generator.
@@ -35,6 +39,8 @@ public final class FederateExecutionSQLGenerator {
     
     private final int[] projects;
     
+    private final List<String> columnNames;
+    
     /**
      * Generate sql.
      *
@@ -42,7 +48,8 @@ public final class FederateExecutionSQLGenerator {
      * @return sql
      */
     public String generate(final String table) {
-        // TODO
-        return String.format("SELECT * FROM %s", table);
+        // TODO generate sql with filters
+        Collection<String> actualColumnNames = null == projects ? columnNames : Arrays.stream(projects).mapToObj(columnNames::get).collect(Collectors.toList());
+        return String.format("SELECT %s FROM %s", Joiner.on(", ").join(actualColumnNames), table);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryMergedResult.java b/shardingsphere-infra/shardingsphere-infra-merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryMergedResult.java
index 77f2b16..ad78abd 100644
--- a/shardingsphere-infra/shardingsphere-infra-merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryMergedResult.java
+++ b/shardingsphere-infra/shardingsphere-infra-merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryMergedResult.java
@@ -47,24 +47,15 @@ public abstract class MemoryMergedResult<T extends ShardingSphereRule> implement
     
     private boolean wasNull;
     
-    protected MemoryMergedResult(final SQLStatementContext sqlStatementContext, final MergedResult mergedResult) throws SQLException {
-        List<MemoryQueryResultRow> memoryQueryResultRowList = init(null, null, sqlStatementContext, null, mergedResult);
-        memoryResultSetRows = memoryQueryResultRowList.iterator();
-        if (!memoryQueryResultRowList.isEmpty()) {
-            currentResultSetRow = memoryQueryResultRowList.get(0);
-        }
-    }
-    
     protected MemoryMergedResult(final T rule, final ShardingSphereSchema schema, final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults) throws SQLException {
-        List<MemoryQueryResultRow> memoryQueryResultRowList = init(rule, schema, sqlStatementContext, queryResults, null);
+        List<MemoryQueryResultRow> memoryQueryResultRowList = init(rule, schema, sqlStatementContext, queryResults);
         memoryResultSetRows = memoryQueryResultRowList.iterator();
         if (!memoryQueryResultRowList.isEmpty()) {
             currentResultSetRow = memoryQueryResultRowList.get(0);
         }
     }
     
-    protected abstract List<MemoryQueryResultRow> init(T rule, ShardingSphereSchema schema, SQLStatementContext sqlStatementContext, 
-                                                       List<QueryResult> queryResults, MergedResult mergedResult) throws SQLException;
+    protected abstract List<MemoryQueryResultRow> init(T rule, ShardingSphereSchema schema, SQLStatementContext sqlStatementContext, List<QueryResult> queryResults) throws SQLException;
     
     @Override
     public final boolean next() {
diff --git a/shardingsphere-infra/shardingsphere-infra-merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryQueryResultRow.java b/shardingsphere-infra/shardingsphere-infra-merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryQueryResultRow.java
index 7f2d785..75032bd 100644
--- a/shardingsphere-infra/shardingsphere-infra-merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryQueryResultRow.java
+++ b/shardingsphere-infra/shardingsphere-infra-merge/src/main/java/org/apache/shardingsphere/infra/merge/result/impl/memory/MemoryQueryResultRow.java
@@ -20,7 +20,6 @@ package org.apache.shardingsphere.infra.merge.result.impl.memory;
 import com.google.common.base.Preconditions;
 import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
-import org.apache.shardingsphere.infra.merge.result.MergedResult;
 
 import java.sql.SQLException;
 
@@ -36,10 +35,6 @@ public final class MemoryQueryResultRow {
         data = load(queryResult);
     }
     
-    public MemoryQueryResultRow(final MergedResult mergedResult, final int columnCount) throws SQLException {
-        data = load(mergedResult, columnCount);
-    }
-    
     private Object[] load(final QueryResult queryResult) throws SQLException {
         int columnCount = queryResult.getMetaData().getColumnCount();
         Object[] result = new Object[columnCount];
@@ -49,14 +44,6 @@ public final class MemoryQueryResultRow {
         return result;
     }
     
-    private Object[] load(final MergedResult mergedResult, final int columnCount) throws SQLException {
-        Object[] result = new Object[columnCount];
-        for (int i = 0; i < columnCount; i++) {
-            result[i] = mergedResult.getValue(i + 1, Object.class);
-        }
-        return result;
-    }
-    
     /**
      * Get data from cell.
      * 
diff --git a/shardingsphere-infra/shardingsphere-infra-merge/src/test/java/org/apache/shardingsphere/infra/merge/result/impl/memory/fixture/TestMemoryMergedResult.java b/shardingsphere-infra/shardingsphere-infra-merge/src/test/java/org/apache/shardingsphere/infra/merge/result/impl/memory/fixture/TestMemoryMergedResult.java
index 9cf252a..ebc3a1a 100644
--- a/shardingsphere-infra/shardingsphere-infra-merge/src/test/java/org/apache/shardingsphere/infra/merge/result/impl/memory/fixture/TestMemoryMergedResult.java
+++ b/shardingsphere-infra/shardingsphere-infra-merge/src/test/java/org/apache/shardingsphere/infra/merge/result/impl/memory/fixture/TestMemoryMergedResult.java
@@ -18,13 +18,12 @@
 package org.apache.shardingsphere.infra.merge.result.impl.memory.fixture;
 
 import lombok.Getter;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
 import org.apache.shardingsphere.infra.merge.fixture.rule.IndependentRuleFixture;
-import org.apache.shardingsphere.infra.merge.result.MergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryMergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryQueryResultRow;
 import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
-import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 
 import java.sql.SQLException;
 import java.util.Collections;
@@ -43,7 +42,7 @@ public final class TestMemoryMergedResult extends MemoryMergedResult<Independent
     
     @Override
     protected List<MemoryQueryResultRow> init(final IndependentRuleFixture rule, final ShardingSphereSchema schema, 
-                                              final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults, final MergedResult mergedResult) {
+                                              final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults) {
         memoryQueryResultRow = mock(MemoryQueryResultRow.class);
         return Collections.singletonList(memoryQueryResultRow);
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/metadata/FederateTableMetadata.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/metadata/FederateTableMetadata.java
index 4452ac6..229f1f6 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/metadata/FederateTableMetadata.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/core/metadata/FederateTableMetadata.java
@@ -32,7 +32,9 @@ import org.apache.shardingsphere.infra.metadata.schema.model.TableMetaData;
 
 import javax.sql.DataSource;
 import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 
@@ -42,13 +44,18 @@ import java.util.Optional;
 @Getter
 public final class FederateTableMetadata {
     
+    private static final RelDataTypeFactory TYPE_FACTORY = new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+    
     private final String name;
     
     private final RelProtoDataType relProtoDataType;
     
+    private final List<String> columnNames = new ArrayList<>();
+    
     public FederateTableMetadata(final String name, final TableMetaData tableMetaData) {
         this.name = name;
         relProtoDataType = createRelDataType(tableMetaData);
+        columnNames.addAll(tableMetaData.getColumns().keySet());
     }
     
     /**
@@ -59,7 +66,9 @@ public final class FederateTableMetadata {
     public FederateTableMetadata(final String name, final Map<String, DataSource> dataSources, final Map<String, Collection<String>> dataSourceRules,
                                  final Collection<DataNode> tableDataNodes, final DatabaseType databaseType) throws SQLException {
         this.name = name;
-        relProtoDataType = createRelDataType(createTableMetaData(dataSources, dataSourceRules, tableDataNodes, databaseType));
+        TableMetaData tableMetaData = createTableMetaData(dataSources, dataSourceRules, tableDataNodes, databaseType);
+        relProtoDataType = createRelDataType(tableMetaData);
+        columnNames.addAll(tableMetaData.getColumns().keySet());
     }
     
     private TableMetaData createTableMetaData(final Map<String, DataSource> dataSources, final Map<String, Collection<String>> dataSourceRules,
@@ -71,11 +80,10 @@ public final class FederateTableMetadata {
     }
     
     private RelProtoDataType createRelDataType(final TableMetaData tableMetaData) {
-        RelDataTypeFactory typeFactory = new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
-        RelDataTypeFactory.Builder fieldInfo = typeFactory.builder();
+        RelDataTypeFactory.Builder fieldInfo = TYPE_FACTORY.builder();
         for (Map.Entry<String, ColumnMetaData> entry : tableMetaData.getColumns().entrySet()) {
             SqlTypeName sqlTypeName = SqlTypeName.getNameForJdbcType(entry.getValue().getDataType());
-            fieldInfo.add(entry.getKey(), null == sqlTypeName ? typeFactory.createUnknownType() : typeFactory.createTypeWithNullability(typeFactory.createSqlType(sqlTypeName), true));
+            fieldInfo.add(entry.getKey(), null == sqlTypeName ? TYPE_FACTORY.createUnknownType() : TYPE_FACTORY.createTypeWithNullability(TYPE_FACTORY.createSqlType(sqlTypeName), true));
         }
         return RelDataTypeImpl.proto(fieldInfo.build());
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-rewrite/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/token/generator/generic/RemoveTokenGenerator.java b/shardingsphere-infra/shardingsphere-infra-rewrite/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/token/generator/generic/RemoveTokenGenerator.java
index db8cb4c..bf889a1 100644
--- a/shardingsphere-infra/shardingsphere-infra-rewrite/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/token/generator/generic/RemoveTokenGenerator.java
+++ b/shardingsphere-infra/shardingsphere-infra-rewrite/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/token/generator/generic/RemoveTokenGenerator.java
@@ -18,11 +18,10 @@
 package org.apache.shardingsphere.infra.rewrite.sql.token.generator.generic;
 
 import com.google.common.base.Preconditions;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.rewrite.sql.token.generator.CollectionSQLTokenGenerator;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.generic.RemoveToken;
-import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.RemoveAvailable;
-import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLShowColumnsStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLShowTableStatusStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLShowTablesStatement;
@@ -46,9 +45,6 @@ public final class RemoveTokenGenerator implements CollectionSQLTokenGenerator<S
         if (sqlStatementContext.getSqlStatement() instanceof MySQLShowColumnsStatement) {
             return ((MySQLShowColumnsStatement) sqlStatementContext.getSqlStatement()).getFromSchema().isPresent();
         }
-        if (sqlStatementContext.getSqlStatement() instanceof SelectStatement) {
-            return ((SelectStatement) sqlStatementContext.getSqlStatement()).getHaving().isPresent();
-        }
         return false;
     }
     
@@ -69,11 +65,6 @@ public final class RemoveTokenGenerator implements CollectionSQLTokenGenerator<S
             RemoveAvailable removeAvailable = ((MySQLShowColumnsStatement) sqlStatementContext.getSqlStatement()).getFromSchema().get();
             return Collections.singletonList(new RemoveToken(removeAvailable.getStartIndex(), removeAvailable.getStopIndex()));
         }
-        if (sqlStatementContext.getSqlStatement() instanceof SelectStatement) {
-            Preconditions.checkState(((SelectStatement) sqlStatementContext.getSqlStatement()).getHaving().isPresent());
-            RemoveAvailable removeAvailable = ((SelectStatement) sqlStatementContext.getSqlStatement()).getHaving().get();
-            return Collections.singletonList(new RemoveToken(removeAvailable.getStartIndex(), removeAvailable.getStopIndex()));
-        }
         return Collections.emptyList();
     }
 }
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/DatabaseCommunicationEngineTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/DatabaseCommunicationEngineTest.java
index f90b1b3..5677758 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/DatabaseCommunicationEngineTest.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/DatabaseCommunicationEngineTest.java
@@ -26,7 +26,6 @@ import org.apache.shardingsphere.infra.database.type.dialect.H2DatabaseType;
 import org.apache.shardingsphere.infra.executor.kernel.ExecutorEngine;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResultMetaData;
-import org.apache.shardingsphere.infra.merge.result.MergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryMergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryQueryResultRow;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
@@ -97,7 +96,7 @@ public final class DatabaseCommunicationEngineTest {
             
             @Override
             protected List<MemoryQueryResultRow> init(final ShardingSphereRule rule, final ShardingSphereSchema schema, 
-                                                      final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults, final MergedResult mergedResult) {
+                                                      final SQLStatementContext sqlStatementContext, final List<QueryResult> queryResults) {
                 memoryQueryResultRow = mock(MemoryQueryResultRow.class);
                 return Collections.singletonList(memoryQueryResultRow);
             }
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/predicate/HavingSegment.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/predicate/HavingSegment.java
index d946a74..0f8cb4b 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/predicate/HavingSegment.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/predicate/HavingSegment.java
@@ -20,8 +20,8 @@ package org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.RemoveAvailable;
 
 /**
  * Having segment.
@@ -29,7 +29,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.RemoveAva
 @RequiredArgsConstructor
 @Getter
 @Setter
-public final class HavingSegment implements RemoveAvailable {
+public final class HavingSegment implements SQLSegment {
     
     private final int startIndex;
     
diff --git a/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/sharding/case/select.xml b/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/sharding/case/select.xml
index c1daf0a..324e5a7 100644
--- a/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/sharding/case/select.xml
+++ b/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/sharding/case/select.xml
@@ -45,20 +45,17 @@
 
     <rewrite-assertion id="select_with_having">
         <input sql="SELECT COUNT(account_id) as count_alias FROM t_account GROUP BY amount HAVING count_alias > ?" parameters="1"/>
-        <output sql="SELECT COUNT(account_id) as count_alias , amount AS GROUP_BY_DERIVED_0 FROM t_account_0 GROUP BY amount  ORDER BY amount ASC " parameters="1"/>
-        <output sql="SELECT COUNT(account_id) as count_alias , amount AS GROUP_BY_DERIVED_0 FROM t_account_1 GROUP BY amount  ORDER BY amount ASC " parameters="1"/>
+        <output sql="SELECT COUNT(account_id) as count_alias FROM t_account GROUP BY amount HAVING count_alias > ?" parameters="1"/>
     </rewrite-assertion>
 
     <rewrite-assertion id="select_with_having_and_window_for_mysql" db-type="MySQL">
         <input sql="SELECT COUNT(account_id) as count_alias FROM t_account GROUP BY amount HAVING count_alias > ? WINDOW w AS (PARTITION BY account_id)" parameters="1"/>
-        <output sql="SELECT COUNT(account_id) as count_alias , amount AS GROUP_BY_DERIVED_0 FROM t_account_0 GROUP BY amount  WINDOW w AS (PARTITION BY account_id) ORDER BY amount ASC " parameters="1"/>
-        <output sql="SELECT COUNT(account_id) as count_alias , amount AS GROUP_BY_DERIVED_0 FROM t_account_1 GROUP BY amount  WINDOW w AS (PARTITION BY account_id) ORDER BY amount ASC " parameters="1"/>
+        <output sql="SELECT COUNT(account_id) as count_alias FROM t_account GROUP BY amount HAVING count_alias > ? WINDOW w AS (PARTITION BY account_id)" parameters="1"/>
     </rewrite-assertion>
 
     <rewrite-assertion id="select_with_having_and_window_for_postgresql" db-type="PostgreSQL">
         <input sql="SELECT COUNT(account_id) as count_alias FROM t_account GROUP BY amount HAVING count_alias > ? WINDOW w AS (PARTITION BY account_id)" parameters="1"/>
-        <output sql="SELECT COUNT(account_id) as count_alias , amount AS GROUP_BY_DERIVED_0 FROM t_account_0 GROUP BY amount  WINDOW w AS (PARTITION BY account_id) ORDER BY amount ASC " parameters="1"/>
-        <output sql="SELECT COUNT(account_id) as count_alias , amount AS GROUP_BY_DERIVED_0 FROM t_account_1 GROUP BY amount  WINDOW w AS (PARTITION BY account_id) ORDER BY amount ASC " parameters="1"/>
+        <output sql="SELECT COUNT(account_id) as count_alias FROM t_account GROUP BY amount HAVING count_alias > ? WINDOW w AS (PARTITION BY account_id)" parameters="1"/>
     </rewrite-assertion>
 
     <rewrite-assertion id="select_with_schema">