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

[shardingsphere] branch master updated: Rewrite derived projection from orderby (#7476)

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

zhangliang 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 2c98ce4  Rewrite derived projection from orderby (#7476)
2c98ce4 is described below

commit 2c98ce46a7f4a57a1b5eede378310a708939d53f
Author: JingShang Lu <lu...@apache.org>
AuthorDate: Mon Sep 21 19:15:01 2020 +0800

    Rewrite derived projection from orderby (#7476)
    
    * fix rewrite for derived orderBy projection
    * change package of TableExtractor
---
 .../generator/impl/ProjectionsTokenGenerator.java  | 81 +++++++++++++++++++---
 .../rewrite/token/pojo/ProjectionsToken.java       | 13 ++--
 .../src/test/resources/sharding/select.xml         | 18 ++---
 .../select/projection/engine/ProjectionEngine.java |  4 +-
 .../engine/ProjectionsContextEngine.java           |  2 +-
 .../select/projection/impl/DerivedProjection.java  |  3 +
 .../statement/dml/DeleteStatementContext.java      | 14 ++--
 .../statement/dml/InsertStatementContext.java      |  8 +--
 .../statement/dml/SelectStatementContext.java      | 14 ++--
 .../statement/dml/UpdateStatementContext.java      | 14 ++--
 .../select/projection/ProjectionsContextTest.java  |  2 +-
 .../TableExtractor.java}                           | 17 +++--
 12 files changed, 131 insertions(+), 59 deletions(-)

diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/main/java/org/apache/shardingsphere/sharding/rewrite/token/generator/impl/ProjectionsTokenGenerator.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/main/java/org/apache/shardingsphere/sharding/rewrite/token/generator/impl/ProjectionsTokenGenerator.java
index 9ad8cd5..e635d26 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/main/java/org/apache/shardingsphere/sharding/rewrite/token/generator/impl/ProjectionsTokenGenerator.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/main/java/org/apache/shardingsphere/sharding/rewrite/token/generator/impl/ProjectionsTokenGenerator.java
@@ -18,6 +18,12 @@
 package org.apache.shardingsphere.sharding.rewrite.token.generator.impl;
 
 import com.google.common.base.Preconditions;
+import lombok.Setter;
+import org.apache.shardingsphere.infra.rewrite.sql.token.generator.OptionalSQLTokenGenerator;
+import org.apache.shardingsphere.infra.rewrite.sql.token.generator.aware.RouteContextAware;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.infra.route.context.RouteMapper;
+import org.apache.shardingsphere.infra.route.context.RouteUnit;
 import org.apache.shardingsphere.sharding.rewrite.token.generator.IgnoreForSingleRoute;
 import org.apache.shardingsphere.sharding.rewrite.token.pojo.ProjectionsToken;
 import org.apache.shardingsphere.sql.parser.binder.segment.select.projection.Projection;
@@ -26,16 +32,26 @@ import org.apache.shardingsphere.sql.parser.binder.segment.select.projection.imp
 import org.apache.shardingsphere.sql.parser.binder.segment.select.projection.impl.DerivedProjection;
 import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.sql.parser.binder.statement.dml.SelectStatementContext;
-import org.apache.shardingsphere.infra.rewrite.sql.token.generator.OptionalSQLTokenGenerator;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.extractor.TableExtractor;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
  * Projections token generator.
  */
-public final class ProjectionsTokenGenerator implements OptionalSQLTokenGenerator<SelectStatementContext>, IgnoreForSingleRoute {
+@Setter
+public final class ProjectionsTokenGenerator implements OptionalSQLTokenGenerator<SelectStatementContext>, IgnoreForSingleRoute, RouteContextAware {
+    
+    private RouteContext routeContext;
     
     @Override
     public boolean isGenerateSQLToken(final SQLStatementContext sqlStatementContext) {
@@ -44,17 +60,24 @@ public final class ProjectionsTokenGenerator implements OptionalSQLTokenGenerato
     
     @Override
     public ProjectionsToken generateSQLToken(final SelectStatementContext selectStatementContext) {
-        Collection<String> derivedProjectionTexts = getDerivedProjectionTexts(selectStatementContext);
+        Map<RouteUnit, Collection<String>> derivedProjectionTexts = getDerivedProjectionTexts(selectStatementContext);
         return new ProjectionsToken(selectStatementContext.getProjectionsContext().getStopIndex() + 1 + " ".length(), derivedProjectionTexts);
     }
     
-    private Collection<String> getDerivedProjectionTexts(final SelectStatementContext selectStatementContext) {
-        Collection<String> result = new LinkedList<>();
-        for (Projection each : selectStatementContext.getProjectionsContext().getProjections()) {
-            if (each instanceof AggregationProjection && !((AggregationProjection) each).getDerivedAggregationProjections().isEmpty()) {
-                result.addAll(((AggregationProjection) each).getDerivedAggregationProjections().stream().map(this::getDerivedProjectionText).collect(Collectors.toList()));
-            } else if (each instanceof DerivedProjection) {
-                result.add(getDerivedProjectionText(each));
+    private Map<RouteUnit, Collection<String>> getDerivedProjectionTexts(final SelectStatementContext selectStatementContext) {
+        Map<RouteUnit, Collection<String>> result = new HashMap<>();
+        for (RouteUnit routeUnit : routeContext.getRouteResult().getRouteUnits()) {
+            result.put(routeUnit, new LinkedList<>());
+            for (Projection each : selectStatementContext.getProjectionsContext().getProjections()) {
+                if (each instanceof AggregationProjection && !((AggregationProjection) each).getDerivedAggregationProjections().isEmpty()) {
+                    result.get(routeUnit).addAll(((AggregationProjection) each).getDerivedAggregationProjections().stream().map(this::getDerivedProjectionText).collect(Collectors.toList()));
+                } else if (each instanceof DerivedProjection && ((DerivedProjection) each).getDerivedProjection() instanceof ColumnOrderByItemSegment) {
+                    TableExtractor tableExtractor = new TableExtractor();
+                    tableExtractor.extractTablesFromSelect(selectStatementContext.getSqlStatement());
+                    result.get(routeUnit).add(getDerivedProjectionTextFromColumnOrderByItemSegment((DerivedProjection) each, tableExtractor, routeUnit));
+                } else if (each instanceof DerivedProjection) {
+                    result.get(routeUnit).add(getDerivedProjectionText(each));
+                }
             }
         }
         return result;
@@ -67,4 +90,42 @@ public final class ProjectionsTokenGenerator implements OptionalSQLTokenGenerato
         }
         return projection.getExpression() + " AS " + projection.getAlias().get() + " ";
     }
+    
+    private String getDerivedProjectionTextFromColumnOrderByItemSegment(final DerivedProjection projection, final TableExtractor tableExtractor, final RouteUnit routeUnit) {
+        Preconditions.checkState(projection.getAlias().isPresent());
+        Preconditions.checkState(projection.getDerivedProjection() instanceof ColumnOrderByItemSegment);
+        ColumnOrderByItemSegment columnOrderByItemSegment = (ColumnOrderByItemSegment) projection.getDerivedProjection();
+        ColumnOrderByItemSegment newColumnOrderByItem = generateNewColumnOrderByItem(columnOrderByItemSegment, routeUnit, tableExtractor);
+        String result = new StringBuilder().append(newColumnOrderByItem.getText()).append(" AS ").append(projection.getAlias().get()).append(" ").toString();
+        return result;
+    }
+    
+    private Optional<String> getActualTables(final RouteUnit routeUnit, final String logicalTableName) {
+        for (RouteMapper each : routeUnit.getTableMappers()) {
+            if (each.getLogicName().equalsIgnoreCase(logicalTableName)) {
+                return Optional.of(each.getActualName());
+            }
+        }
+        return Optional.empty();
+    }
+
+    private ColumnOrderByItemSegment generateNewColumnOrderByItem(final ColumnOrderByItemSegment old, final RouteUnit routeUnit, final TableExtractor tableExtractor) {
+        Optional<OwnerSegment> ownerSegment = old.getColumn().getOwner();
+        if (!ownerSegment.isPresent()) {
+            return old;
+        }
+        if (!tableExtractor.needRewrite(ownerSegment.get())) {
+            return old;
+        }
+        Optional<String> actualTableName = getActualTables(routeUnit, ownerSegment.get().getIdentifier().getValue());
+        Preconditions.checkState(actualTableName.isPresent());
+        ColumnSegment newColumnSegment = new ColumnSegment(0, 0, old.getColumn().getIdentifier());
+        String newOwnerString = String.format("%s%s%s", ownerSegment.get().getIdentifier().getQuoteCharacter().getStartDelimiter(), actualTableName.get(),
+                ownerSegment.get().getIdentifier().getQuoteCharacter().getEndDelimiter());
+        IdentifierValue newOwnerIdentifier = new IdentifierValue(newOwnerString);
+        OwnerSegment newOwner = new OwnerSegment(0, 0, newOwnerIdentifier);
+        newColumnSegment.setOwner(newOwner);
+        ColumnOrderByItemSegment result = new ColumnOrderByItemSegment(newColumnSegment, old.getOrderDirection());
+        return result;
+    }
 }
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/main/java/org/apache/shardingsphere/sharding/rewrite/token/pojo/ProjectionsToken.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/main/java/org/apache/shardingsphere/sharding/rewrite/token/pojo/ProjectionsToken.java
index 8f95537..c6947c7 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/main/java/org/apache/shardingsphere/sharding/rewrite/token/pojo/ProjectionsToken.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/main/java/org/apache/shardingsphere/sharding/rewrite/token/pojo/ProjectionsToken.java
@@ -18,26 +18,29 @@
 package org.apache.shardingsphere.sharding.rewrite.token.pojo;
 
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.Attachable;
+import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.RouteUnitAware;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.SQLToken;
+import org.apache.shardingsphere.infra.route.context.RouteUnit;
 
 import java.util.Collection;
+import java.util.Map;
 
 /**
  * Projections token.
  */
-public final class ProjectionsToken extends SQLToken implements Attachable {
+public final class ProjectionsToken extends SQLToken implements Attachable, RouteUnitAware {
     
-    private final Collection<String> projections;
+    private final Map<RouteUnit, Collection<String>> projections;
     
-    public ProjectionsToken(final int startIndex, final Collection<String> projections) {
+    public ProjectionsToken(final int startIndex, final Map<RouteUnit, Collection<String>> projections) {
         super(startIndex);
         this.projections = projections;
     }
     
     @Override
-    public String toString() {
+    public String toString(final RouteUnit routeUnit) {
         StringBuilder result = new StringBuilder();
-        for (String each : projections) {
+        for (String each : projections.get(routeUnit)) {
             result.append(", ");
             result.append(each);
         }
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/resources/sharding/select.xml b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/resources/sharding/select.xml
index acdb3f9..b617724 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/resources/sharding/select.xml
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/resources/sharding/select.xml
@@ -92,18 +92,18 @@
         <output sql="SELECT distinct a.account_id FROM t_account_1 as a ORDER BY a.account_id ASC " />
     </rewrite-assertion>
 
-    <rewrite-assertion id="select_for_literals_with_table_prefix" db-type="MySQL">
-        <input sql="SELECT `t_account`.`account_id` FROM `t_account` order by `t_account`.`account_id` ASC" />
-        <output sql="SELECT `t_account_0`.`account_id` FROM `t_account_0` order by `t_account_0`.`account_id` ASC" />
-        <output sql="SELECT `t_account_1`.`account_id` FROM `t_account_1` order by `t_account_1`.`account_id` ASC" />
+    <rewrite-assertion id="select_for_literals_with_order_by_with_table_prefix" db-type="MySQL">
+        <input sql="SELECT `t_account`.`amount` FROM `t_account` order by `t_account`.`account_id` ASC" />
+        <output sql="SELECT `t_account_0`.`amount` , `t_account_0`.`account_id` AS ORDER_BY_DERIVED_0 FROM `t_account_0` order by `t_account_0`.`account_id` ASC" />
+        <output sql="SELECT `t_account_1`.`amount` , `t_account_1`.`account_id` AS ORDER_BY_DERIVED_0 FROM `t_account_1` order by `t_account_1`.`account_id` ASC" />
     </rewrite-assertion>
 
-    <rewrite-assertion id="select_for_literals_no_quote_with_table_prefix" db-type="MySQL">
-        <input sql="SELECT t_account.account_id FROM t_account order by t_account.account_id ASC" />
-        <output sql="SELECT t_account_0.account_id FROM t_account_0 order by t_account_0.account_id ASC" />
-        <output sql="SELECT t_account_1.account_id FROM t_account_1 order by t_account_1.account_id ASC" />
+    <rewrite-assertion id="select_for_literals_with_order_by_no_quote_with_table_prefix" db-type="MySQL">
+        <input sql="SELECT t_account.amount FROM t_account order by t_account.account_id ASC" />
+        <output sql="SELECT t_account_0.amount , t_account_0.account_id AS ORDER_BY_DERIVED_0 FROM t_account_0 order by t_account_0.account_id ASC" />
+        <output sql="SELECT t_account_1.amount , t_account_1.account_id AS ORDER_BY_DERIVED_0 FROM t_account_1 order by t_account_1.account_id ASC" />
     </rewrite-assertion>
-    
+
     <rewrite-assertion id="select_binding_table_with_sharding_value_for_parameters">
         <input sql="SELECT * FROM t_account o, t_account_detail i WHERE o.account_id=i.account_id AND o.account_id = ?" parameters="100" />
         <output sql="SELECT * FROM t_account_0 o, t_account_detail_0 i WHERE o.account_id=i.account_id AND o.account_id = ?" parameters="100" />
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/engine/ProjectionEngine.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/engine/ProjectionEngine.java
index 02b929c..5b4211c 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/engine/ProjectionEngine.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/engine/ProjectionEngine.java
@@ -87,8 +87,8 @@ public final class ProjectionEngine {
     }
     
     private ColumnProjection createProjection(final ColumnProjectionSegment projectionSegment) {
-        String owner = projectionSegment.getColumn().getOwner().isPresent() ? projectionSegment.getColumn().getOwner().get().getIdentifier().getValueWithQuoteCharacters() : null;
-        return new ColumnProjection(owner, projectionSegment.getColumn().getIdentifier().getValueWithQuoteCharacters(), projectionSegment.getAlias().orElse(null));
+        String owner = projectionSegment.getColumn().getOwner().isPresent() ? projectionSegment.getColumn().getOwner().get().getIdentifier().getValue() : null;
+        return new ColumnProjection(owner, projectionSegment.getColumn().getIdentifier().getValue(), projectionSegment.getAlias().orElse(null));
     }
     
     private ExpressionProjection createProjection(final ExpressionProjectionSegment projectionSegment) {
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/engine/ProjectionsContextEngine.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/engine/ProjectionsContextEngine.java
index b282f2e..1d23154 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/engine/ProjectionsContextEngine.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/engine/ProjectionsContextEngine.java
@@ -94,7 +94,7 @@ public final class ProjectionsContextEngine {
         int derivedColumnOffset = 0;
         for (OrderByItem each : orderItems) {
             if (!containsProjection(projections, each.getSegment(), tables)) {
-                result.add(new DerivedProjection(((TextOrderByItemSegment) each.getSegment()).getText(), derivedColumn.getDerivedColumnAlias(derivedColumnOffset++)));
+                result.add(new DerivedProjection(((TextOrderByItemSegment) each.getSegment()).getText(), derivedColumn.getDerivedColumnAlias(derivedColumnOffset++), each.getSegment()));
             }
         }
         return result;
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/impl/DerivedProjection.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/impl/DerivedProjection.java
index 31c5c17..e1cf11a 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/impl/DerivedProjection.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/impl/DerivedProjection.java
@@ -22,6 +22,7 @@ import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
 import org.apache.shardingsphere.sql.parser.binder.segment.select.projection.Projection;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
 
 import java.util.Optional;
 
@@ -38,6 +39,8 @@ public final class DerivedProjection implements Projection {
     
     private final String alias;
     
+    private final SQLSegment derivedProjection;
+    
     @Override
     public Optional<String> getAlias() {
         return Optional.ofNullable(alias);
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/DeleteStatementContext.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/DeleteStatementContext.java
index 92963ac..e18c288 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/DeleteStatementContext.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/DeleteStatementContext.java
@@ -26,7 +26,7 @@ import org.apache.shardingsphere.sql.parser.binder.type.WhereAvailable;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
-import org.apache.shardingsphere.sql.parser.sql.common.util.TableExtractUtils;
+import org.apache.shardingsphere.sql.parser.sql.common.extractor.TableExtractor;
 
 import java.util.Collection;
 import java.util.Optional;
@@ -42,16 +42,16 @@ public final class DeleteStatementContext extends CommonSQLStatementContext<Dele
     
     public DeleteStatementContext(final DeleteStatement sqlStatement) {
         super(sqlStatement);
-        TableExtractUtils utils = new TableExtractUtils();
-        utils.extractTablesFromDelete(sqlStatement);
-        tablesContext = new TablesContext(utils.getRewriteTables());
+        TableExtractor tableExtractor = new TableExtractor();
+        tableExtractor.extractTablesFromDelete(sqlStatement);
+        tablesContext = new TablesContext(tableExtractor.getRewriteTables());
     }
     
     @Override
     public Collection<SimpleTableSegment> getAllTables() {
-        TableExtractUtils utils = new TableExtractUtils();
-        utils.extractTablesFromDelete(getSqlStatement());
-        return utils.getRewriteTables();
+        TableExtractor tableExtractor = new TableExtractor();
+        tableExtractor.extractTablesFromDelete(getSqlStatement());
+        return tableExtractor.getRewriteTables();
     }
     
     @Override
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/InsertStatementContext.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/InsertStatementContext.java
index 8c83b21..6c1ed83 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/InsertStatementContext.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/InsertStatementContext.java
@@ -34,8 +34,8 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.Expressi
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.extractor.TableExtractor;
 import org.apache.shardingsphere.sql.parser.sql.common.util.SQLStatementUtils;
-import org.apache.shardingsphere.sql.parser.sql.common.util.TableExtractUtils;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -164,8 +164,8 @@ public final class InsertStatementContext extends CommonSQLStatementContext<Inse
     
     @Override
     public Collection<SimpleTableSegment> getAllTables() {
-        TableExtractUtils utils = new TableExtractUtils();
-        utils.extractTablesFromInsert(getSqlStatement());
-        return utils.getRewriteTables();
+        TableExtractor tableExtractor = new TableExtractor();
+        tableExtractor.extractTablesFromInsert(getSqlStatement());
+        return tableExtractor.getRewriteTables();
     }
 }
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/SelectStatementContext.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/SelectStatementContext.java
index c1d1880..157509a 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/SelectStatementContext.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/SelectStatementContext.java
@@ -44,7 +44,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.Whe
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 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.util.TableExtractUtils;
+import org.apache.shardingsphere.sql.parser.sql.common.extractor.TableExtractor;
 import org.apache.shardingsphere.sql.parser.sql.common.util.WhereSegmentExtractUtils;
 
 import java.util.Collection;
@@ -178,9 +178,9 @@ public final class SelectStatementContext extends CommonSQLStatementContext<Sele
     
     @Override
     public Collection<SimpleTableSegment> getAllTables() {
-        TableExtractUtils utils = new TableExtractUtils();
-        utils.extractTablesFromSelect(getSqlStatement());
-        return utils.getRewriteTables();
+        TableExtractor tableExtractor = new TableExtractor();
+        tableExtractor.extractTablesFromSelect(getSqlStatement());
+        return tableExtractor.getRewriteTables();
     }
     
     @Override
@@ -193,8 +193,8 @@ public final class SelectStatementContext extends CommonSQLStatementContext<Sele
      * @return tables.
      */
     public Collection<SimpleTableSegment> getSimpleTableSegments() {
-        TableExtractUtils utils = new TableExtractUtils();
-        utils.extractTablesFromSelect(getSqlStatement());
-        return utils.getRewriteTables();
+        TableExtractor tableExtractor = new TableExtractor();
+        tableExtractor.extractTablesFromSelect(getSqlStatement());
+        return tableExtractor.getRewriteTables();
     }
 }
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContext.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContext.java
index f56fbe2..980cc6c 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContext.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/dml/UpdateStatementContext.java
@@ -26,7 +26,7 @@ import org.apache.shardingsphere.sql.parser.binder.type.WhereAvailable;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
-import org.apache.shardingsphere.sql.parser.sql.common.util.TableExtractUtils;
+import org.apache.shardingsphere.sql.parser.sql.common.extractor.TableExtractor;
 
 import java.util.Collection;
 import java.util.Optional;
@@ -42,16 +42,16 @@ public final class UpdateStatementContext extends CommonSQLStatementContext<Upda
     
     public UpdateStatementContext(final UpdateStatement sqlStatement) {
         super(sqlStatement);
-        TableExtractUtils utils = new TableExtractUtils();
-        utils.extractTablesFromUpdate(sqlStatement);
-        tablesContext = new TablesContext(utils.getRewriteTables());
+        TableExtractor tableExtractor = new TableExtractor();
+        tableExtractor.extractTablesFromUpdate(sqlStatement);
+        tablesContext = new TablesContext(tableExtractor.getRewriteTables());
     }
     
     @Override
     public Collection<SimpleTableSegment> getAllTables() {
-        TableExtractUtils utils = new TableExtractUtils();
-        utils.extractTablesFromUpdate(getSqlStatement());
-        return utils.getRewriteTables();
+        TableExtractor tableExtractor = new TableExtractor();
+        tableExtractor.extractTablesFromUpdate(getSqlStatement());
+        return tableExtractor.getRewriteTables();
     }
     
     @Override
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/ProjectionsContextTest.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/ProjectionsContextTest.java
index 4096835..277298b 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/ProjectionsContextTest.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/test/java/org/apache/shardingsphere/sql/parser/binder/segment/select/projection/ProjectionsContextTest.java
@@ -133,7 +133,7 @@ public final class ProjectionsContextTest {
         ColumnProjection columnProjection1 = new ColumnProjection(null, "col1", null);
         ColumnProjection columnProjection2 = new ColumnProjection(null, "col2", null);
         ColumnProjection columnProjection3 = new ColumnProjection(null, "col3", null);
-        DerivedProjection derivedProjection = new DerivedProjection("col3", "a3");
+        DerivedProjection derivedProjection = new DerivedProjection("col3", "a3", null);
         ShorthandProjection shorthandProjection = new ShorthandProjection(null, Arrays.asList(columnProjection2, columnProjection3));
         ProjectionsContext actual = new ProjectionsContext(0, 0, false, Arrays.asList(columnProjection1, shorthandProjection, derivedProjection));
         assertThat(actual.getExpandProjections().size(), is(3));
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/extractor/TableExtractor.java
similarity index 95%
rename from shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
rename to shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/extractor/TableExtractor.java
index 0dcd492..638106f 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/TableExtractUtils.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/extractor/TableExtractor.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sql.parser.sql.common.util;
+package org.apache.shardingsphere.sql.parser.sql.common.extractor;
 
 import lombok.Getter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
@@ -46,7 +46,7 @@ import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
 
-public final class TableExtractUtils {
+public final class TableExtractor {
     
     @Getter
     private Collection<SimpleTableSegment> rewriteTables = new LinkedList<>();
@@ -84,9 +84,9 @@ public final class TableExtractUtils {
         }
         if (tableSegment instanceof SubqueryTableSegment) {
             tableContext.add(tableSegment);
-            TableExtractUtils utils = new TableExtractUtils();
-            utils.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
-            rewriteTables.addAll(utils.getRewriteTables());
+            TableExtractor tableExtractor = new TableExtractor();
+            tableExtractor.extractTablesFromSelect(((SubqueryTableSegment) tableSegment).getSubquery().getSelect());
+            rewriteTables.addAll(tableExtractor.getRewriteTables());
         }
         if (tableSegment instanceof JoinTableSegment) {
             extractTablesFromTableSegment(((JoinTableSegment) tableSegment).getLeft());
@@ -198,7 +198,12 @@ public final class TableExtractUtils {
         }
     }
     
-    private boolean needRewrite(final OwnerSegment owner) {
+    /**
+     * Check if the table needs to be overwritten.
+     * @param owner OwnerSegment.
+     * @return boolean.
+     */
+    public boolean needRewrite(final OwnerSegment owner) {
         for (TableSegment each : tableContext) {
             if (owner.getIdentifier().getValue().equals(each.getAlias().orElse(null))) {
                 return false;