You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by su...@apache.org on 2024/07/10 14:09:55 UTC

(shardingsphere) branch master updated: Refactor SQLStatementBinder (#32058)

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

sunnianjun 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 b4d7ff303f1 Refactor SQLStatementBinder (#32058)
b4d7ff303f1 is described below

commit b4d7ff303f1db02d085d35c08528914aa4d1fe62
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Wed Jul 10 22:09:49 2024 +0800

    Refactor SQLStatementBinder (#32058)
    
    * Refactor SQLStatementBinder
    
    * Refactor SQLStatementBinder
---
 .../segment/combine/CombineSegmentBinder.java      | 13 +++++-
 .../expression/impl/SubquerySegmentBinder.java     |  5 +-
 .../from/impl/SubqueryTableSegmentBinder.java      |  6 ++-
 .../infra/binder/statement/SQLStatementBinder.java |  6 +--
 .../statement/ddl/CursorStatementBinder.java       |  6 +--
 .../statement/dml/DeleteStatementBinder.java       | 14 ++----
 .../statement/dml/InsertStatementBinder.java       | 17 ++-----
 .../statement/dml/SelectStatementBinder.java       | 53 +++++-----------------
 .../statement/dml/UpdateStatementBinder.java       | 16 ++-----
 .../infra/binder/type/DDLStatementBindEngine.java  |  4 +-
 .../infra/binder/type/DMLStatementBindEngine.java  | 10 ++--
 .../statement/DeleteStatementBinderTest.java       |  2 +-
 .../statement/InsertStatementBinderTest.java       |  6 +--
 .../statement/SelectStatementBinderTest.java       | 14 +++---
 .../statement/UpdateStatementBinderTest.java       |  2 +-
 15 files changed, 67 insertions(+), 107 deletions(-)

diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/combine/CombineSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/combine/CombineSegmentBinder.java
index b15c09dcc00..3390eb13d86 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/combine/CombineSegmentBinder.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/combine/CombineSegmentBinder.java
@@ -46,8 +46,10 @@ public final class CombineSegmentBinder {
         ShardingSphereMetaData metaData = statementBinderContext.getMetaData();
         String currentDatabaseName = statementBinderContext.getCurrentDatabaseName();
         Map<String, TableSegmentBinderContext> externalTableBinderContexts = statementBinderContext.getExternalTableBinderContexts();
-        SelectStatement boundLeftSelect = new SelectStatementBinder().bind(segment.getLeft().getSelect(), metaData, currentDatabaseName, externalTableBinderContexts);
-        SelectStatement boundRightSelect = new SelectStatementBinder().bind(segment.getRight().getSelect(), metaData, currentDatabaseName, externalTableBinderContexts);
+        SelectStatement boundLeftSelect = new SelectStatementBinder().bind(
+                segment.getLeft().getSelect(), createBinderContext(segment.getLeft().getSelect(), metaData, currentDatabaseName, externalTableBinderContexts));
+        SelectStatement boundRightSelect = new SelectStatementBinder().bind(
+                segment.getRight().getSelect(), createBinderContext(segment.getRight().getSelect(), metaData, currentDatabaseName, externalTableBinderContexts));
         SubquerySegment boundLeft = new SubquerySegment(segment.getLeft().getStartIndex(), segment.getLeft().getStopIndex(), segment.getLeft().getText());
         boundLeft.setSelect(boundLeftSelect);
         boundLeft.setSubqueryType(segment.getLeft().getSubqueryType());
@@ -56,4 +58,11 @@ public final class CombineSegmentBinder {
         boundedRight.setSubqueryType(segment.getRight().getSubqueryType());
         return new CombineSegment(segment.getStartIndex(), segment.getStopIndex(), boundLeft, segment.getCombineType(), boundedRight);
     }
+    
+    private static SQLStatementBinderContext createBinderContext(final SelectStatement select, final ShardingSphereMetaData metaData,
+                                                                 final String currentDatabaseName, final Map<String, TableSegmentBinderContext> externalTableBinderContexts) {
+        SQLStatementBinderContext result = new SQLStatementBinderContext(select, metaData, currentDatabaseName);
+        result.getExternalTableBinderContexts().putAll(externalTableBinderContexts);
+        return result;
+    }
 }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/SubquerySegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/SubquerySegmentBinder.java
index 293d03cb85f..f695b9f9ea4 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/SubquerySegmentBinder.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/SubquerySegmentBinder.java
@@ -42,8 +42,9 @@ public final class SubquerySegmentBinder {
      * @return bounded subquery segment
      */
     public static SubquerySegment bind(final SubquerySegment segment, final SQLStatementBinderContext statementBinderContext, final Map<String, TableSegmentBinderContext> outerTableBinderContexts) {
-        SelectStatement boundedSelectStatement = new SelectStatementBinder().bindCorrelateSubquery(segment.getSelect(), statementBinderContext.getMetaData(),
-                statementBinderContext.getCurrentDatabaseName(), outerTableBinderContexts, statementBinderContext.getExternalTableBinderContexts());
+        SQLStatementBinderContext binderContext = new SQLStatementBinderContext(segment.getSelect(), statementBinderContext.getMetaData(), statementBinderContext.getCurrentDatabaseName());
+        binderContext.getExternalTableBinderContexts().putAll(statementBinderContext.getExternalTableBinderContexts());
+        SelectStatement boundedSelectStatement = new SelectStatementBinder(outerTableBinderContexts).bind(segment.getSelect(), binderContext);
         SubquerySegment result = new SubquerySegment(segment.getStartIndex(), segment.getStopIndex(), boundedSelectStatement, segment.getText());
         result.setSubqueryType(segment.getSubqueryType());
         return result;
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/from/impl/SubqueryTableSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/from/impl/SubqueryTableSegmentBinder.java
index c56cf8f0c57..b3b55f7b959 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/from/impl/SubqueryTableSegmentBinder.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/from/impl/SubqueryTableSegmentBinder.java
@@ -68,8 +68,10 @@ public final class SubqueryTableSegmentBinder {
     public static SubqueryTableSegment bind(final SubqueryTableSegment segment, final SQLStatementBinderContext statementBinderContext,
                                             final Map<String, TableSegmentBinderContext> tableBinderContexts, final Map<String, TableSegmentBinderContext> outerTableBinderContexts) {
         fillPivotColumnNamesInBinderContext(segment, statementBinderContext);
-        SelectStatement boundedSelect = new SelectStatementBinder().bindCorrelateSubquery(segment.getSubquery().getSelect(), statementBinderContext.getMetaData(),
-                statementBinderContext.getCurrentDatabaseName(), outerTableBinderContexts, statementBinderContext.getExternalTableBinderContexts());
+        SQLStatementBinderContext binderContext = new SQLStatementBinderContext(
+                segment.getSubquery().getSelect(), statementBinderContext.getMetaData(), statementBinderContext.getCurrentDatabaseName());
+        binderContext.getExternalTableBinderContexts().putAll(statementBinderContext.getExternalTableBinderContexts());
+        SelectStatement boundedSelect = new SelectStatementBinder(outerTableBinderContexts).bind(segment.getSubquery().getSelect(), binderContext);
         SubquerySegment boundedSubquerySegment = new SubquerySegment(segment.getSubquery().getStartIndex(), segment.getSubquery().getStopIndex(), boundedSelect, segment.getSubquery().getText());
         boundedSubquerySegment.setSubqueryType(segment.getSubquery().getSubqueryType());
         IdentifierValue subqueryTableName = segment.getAliasSegment().map(AliasSegment::getIdentifier).orElseGet(() -> new IdentifierValue(""));
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinder.java
index 54280df826e..a3682154128 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinder.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinder.java
@@ -17,7 +17,6 @@
 
 package org.apache.shardingsphere.infra.binder.statement;
 
-import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement;
 
 /**
@@ -31,9 +30,8 @@ public interface SQLStatementBinder<T extends SQLStatement> {
      * Bind SQL statement.
      *
      * @param sqlStatement SQL statement
-     * @param metaData meta data
-     * @param currentDatabaseName current database name
+     * @param binderContext SQL statement binder context
      * @return bound SQL statement
      */
-    T bind(T sqlStatement, ShardingSphereMetaData metaData, String currentDatabaseName);
+    T bind(T sqlStatement, SQLStatementBinderContext binderContext);
 }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/ddl/CursorStatementBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/ddl/CursorStatementBinder.java
index 80c79ca28f8..5d56b77303a 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/ddl/CursorStatementBinder.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/ddl/CursorStatementBinder.java
@@ -19,8 +19,8 @@ package org.apache.shardingsphere.infra.binder.statement.ddl;
 
 import lombok.SneakyThrows;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinder;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
 import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementBinder;
-import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CursorStatement;
 
 /**
@@ -29,9 +29,9 @@ import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CursorS
 public final class CursorStatementBinder implements SQLStatementBinder<CursorStatement> {
     
     @Override
-    public CursorStatement bind(final CursorStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName) {
+    public CursorStatement bind(final CursorStatement sqlStatement, final SQLStatementBinderContext binderContext) {
         CursorStatement result = copy(sqlStatement);
-        result.setSelect(new SelectStatementBinder().bind(sqlStatement.getSelect(), metaData, currentDatabaseName));
+        result.setSelect(new SelectStatementBinder().bind(sqlStatement.getSelect(), binderContext));
         return result;
     }
     
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/DeleteStatementBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/DeleteStatementBinder.java
index be35eae4d0b..8f651b2ec6e 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/DeleteStatementBinder.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/DeleteStatementBinder.java
@@ -23,7 +23,6 @@ import org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderCon
 import org.apache.shardingsphere.infra.binder.segment.where.WhereSegmentBinder;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinder;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
-import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.DeleteStatement;
 
 import java.util.Collections;
@@ -36,18 +35,11 @@ import java.util.Map;
 public final class DeleteStatementBinder implements SQLStatementBinder<DeleteStatement> {
     
     @Override
-    public DeleteStatement bind(final DeleteStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName) {
-        return bind(sqlStatement, metaData, currentDatabaseName, Collections.emptyMap());
-    }
-    
-    private DeleteStatement bind(final DeleteStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName,
-                                 final Map<String, TableSegmentBinderContext> externalTableBinderContexts) {
+    public DeleteStatement bind(final DeleteStatement sqlStatement, final SQLStatementBinderContext binderContext) {
         DeleteStatement result = copy(sqlStatement);
         Map<String, TableSegmentBinderContext> tableBinderContexts = new LinkedHashMap<>();
-        SQLStatementBinderContext statementBinderContext = new SQLStatementBinderContext(sqlStatement, metaData, currentDatabaseName);
-        statementBinderContext.getExternalTableBinderContexts().putAll(externalTableBinderContexts);
-        result.setTable(TableSegmentBinder.bind(sqlStatement.getTable(), statementBinderContext, tableBinderContexts, Collections.emptyMap()));
-        sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, statementBinderContext, tableBinderContexts, Collections.emptyMap())));
+        result.setTable(TableSegmentBinder.bind(sqlStatement.getTable(), binderContext, tableBinderContexts, Collections.emptyMap()));
+        sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, binderContext, tableBinderContexts, Collections.emptyMap())));
         return result;
     }
     
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/InsertStatementBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/InsertStatementBinder.java
index de385645322..c94df3c2f3e 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/InsertStatementBinder.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/InsertStatementBinder.java
@@ -24,14 +24,12 @@ import org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderCon
 import org.apache.shardingsphere.infra.binder.segment.from.impl.SimpleTableSegmentBinder;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinder;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
-import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.InsertStatement;
 
 import java.util.Collection;
-import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Optional;
@@ -43,24 +41,17 @@ import java.util.stream.Collectors;
 public final class InsertStatementBinder implements SQLStatementBinder<InsertStatement> {
     
     @Override
-    public InsertStatement bind(final InsertStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName) {
-        return bind(sqlStatement, metaData, currentDatabaseName, Collections.emptyMap());
-    }
-    
-    private InsertStatement bind(final InsertStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName,
-                                 final Map<String, TableSegmentBinderContext> externalTableBinderContexts) {
+    public InsertStatement bind(final InsertStatement sqlStatement, final SQLStatementBinderContext binderContext) {
         InsertStatement result = copy(sqlStatement);
-        SQLStatementBinderContext statementBinderContext = new SQLStatementBinderContext(sqlStatement, metaData, currentDatabaseName);
-        statementBinderContext.getExternalTableBinderContexts().putAll(externalTableBinderContexts);
         Map<String, TableSegmentBinderContext> tableBinderContexts = new LinkedHashMap<>();
-        Optional.ofNullable(sqlStatement.getTable()).ifPresent(optional -> result.setTable(SimpleTableSegmentBinder.bind(optional, statementBinderContext, tableBinderContexts)));
+        Optional.ofNullable(sqlStatement.getTable()).ifPresent(optional -> result.setTable(SimpleTableSegmentBinder.bind(optional, binderContext, tableBinderContexts)));
         if (sqlStatement.getInsertColumns().isPresent() && !sqlStatement.getInsertColumns().get().getColumns().isEmpty()) {
-            result.setInsertColumns(InsertColumnsSegmentBinder.bind(sqlStatement.getInsertColumns().get(), statementBinderContext, tableBinderContexts));
+            result.setInsertColumns(InsertColumnsSegmentBinder.bind(sqlStatement.getInsertColumns().get(), binderContext, tableBinderContexts));
         } else {
             sqlStatement.getInsertColumns().ifPresent(result::setInsertColumns);
             tableBinderContexts.values().forEach(each -> result.getDerivedInsertColumns().addAll(getVisibleColumns(each.getProjectionSegments())));
         }
-        sqlStatement.getInsertSelect().ifPresent(optional -> result.setInsertSelect(SubquerySegmentBinder.bind(optional, statementBinderContext, tableBinderContexts)));
+        sqlStatement.getInsertSelect().ifPresent(optional -> result.setInsertSelect(SubquerySegmentBinder.bind(optional, binderContext, tableBinderContexts)));
         return result;
     }
     
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/SelectStatementBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/SelectStatementBinder.java
index a4f9ce4f8ba..2568b7c9c84 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/SelectStatementBinder.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/SelectStatementBinder.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.infra.binder.statement.dml;
 
+import lombok.RequiredArgsConstructor;
 import lombok.SneakyThrows;
 import org.apache.shardingsphere.infra.binder.segment.combine.CombineSegmentBinder;
 import org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinder;
@@ -27,7 +28,6 @@ import org.apache.shardingsphere.infra.binder.segment.where.WhereSegmentBinder;
 import org.apache.shardingsphere.infra.binder.segment.with.WithSegmentBinder;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinder;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
-import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement;
 
@@ -39,56 +39,27 @@ import java.util.Optional;
 /**
  * Select statement binder.
  */
+@RequiredArgsConstructor
 public final class SelectStatementBinder implements SQLStatementBinder<SelectStatement> {
     
-    /**
-     * Bind correlate subquery select statement.
-     *
-     * @param sqlStatement subquery select statement
-     * @param metaData meta data
-     * @param currentDatabaseName current database name
-     * @param outerTableBinderContexts outer select statement table binder contexts
-     * @param externalTableBinderContexts external table binder contexts
-     * @return bounded correlate subquery select statement
-     */
-    public SelectStatement bindCorrelateSubquery(final SelectStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName,
-                                                 final Map<String, TableSegmentBinderContext> outerTableBinderContexts, final Map<String, TableSegmentBinderContext> externalTableBinderContexts) {
-        return bind(sqlStatement, metaData, currentDatabaseName, outerTableBinderContexts, externalTableBinderContexts);
-    }
+    private final Map<String, TableSegmentBinderContext> outerTableBinderContexts;
     
-    /**
-     * Bind with external table contexts.
-     *
-     * @param statement select statement
-     * @param metaData meta data
-     * @param currentDatabaseName current database name
-     * @param externalTableContexts external table contexts
-     * @return select statement
-     */
-    public SelectStatement bind(final SelectStatement statement, final ShardingSphereMetaData metaData, final String currentDatabaseName,
-                                final Map<String, TableSegmentBinderContext> externalTableContexts) {
-        return bind(statement, metaData, currentDatabaseName, Collections.emptyMap(), externalTableContexts);
+    public SelectStatementBinder() {
+        outerTableBinderContexts = Collections.emptyMap();
     }
     
     @Override
-    public SelectStatement bind(final SelectStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName) {
-        return bind(sqlStatement, metaData, currentDatabaseName, Collections.emptyMap(), Collections.emptyMap());
-    }
-    
-    private SelectStatement bind(final SelectStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName,
-                                 final Map<String, TableSegmentBinderContext> outerTableBinderContexts, final Map<String, TableSegmentBinderContext> externalTableBinderContexts) {
+    public SelectStatement bind(final SelectStatement sqlStatement, final SQLStatementBinderContext binderContext) {
         SelectStatement result = copy(sqlStatement);
         Map<String, TableSegmentBinderContext> tableBinderContexts = new LinkedHashMap<>();
-        SQLStatementBinderContext statementBinderContext = new SQLStatementBinderContext(sqlStatement, metaData, currentDatabaseName);
-        statementBinderContext.getExternalTableBinderContexts().putAll(externalTableBinderContexts);
         sqlStatement.getWithSegment()
-                .ifPresent(optional -> result.setWithSegment(WithSegmentBinder.bind(optional, statementBinderContext, tableBinderContexts, statementBinderContext.getExternalTableBinderContexts())));
-        Optional<TableSegment> boundedTableSegment = sqlStatement.getFrom().map(optional -> TableSegmentBinder.bind(optional, statementBinderContext, tableBinderContexts, outerTableBinderContexts));
+                .ifPresent(optional -> result.setWithSegment(WithSegmentBinder.bind(optional, binderContext, tableBinderContexts, binderContext.getExternalTableBinderContexts())));
+        Optional<TableSegment> boundedTableSegment = sqlStatement.getFrom().map(optional -> TableSegmentBinder.bind(optional, binderContext, tableBinderContexts, outerTableBinderContexts));
         boundedTableSegment.ifPresent(result::setFrom);
-        result.setProjections(ProjectionsSegmentBinder.bind(sqlStatement.getProjections(), statementBinderContext, boundedTableSegment.orElse(null), tableBinderContexts, outerTableBinderContexts));
-        sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, statementBinderContext, tableBinderContexts, outerTableBinderContexts)));
-        sqlStatement.getCombine().ifPresent(optional -> result.setCombine(CombineSegmentBinder.bind(optional, statementBinderContext)));
-        sqlStatement.getLock().ifPresent(optional -> result.setLock(LockSegmentBinder.bind(optional, statementBinderContext, tableBinderContexts, outerTableBinderContexts)));
+        result.setProjections(ProjectionsSegmentBinder.bind(sqlStatement.getProjections(), binderContext, boundedTableSegment.orElse(null), tableBinderContexts, outerTableBinderContexts));
+        sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, binderContext, tableBinderContexts, outerTableBinderContexts)));
+        sqlStatement.getCombine().ifPresent(optional -> result.setCombine(CombineSegmentBinder.bind(optional, binderContext)));
+        sqlStatement.getLock().ifPresent(optional -> result.setLock(LockSegmentBinder.bind(optional, binderContext, tableBinderContexts, outerTableBinderContexts)));
         // TODO support other segment bind in select statement
         return result;
     }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/UpdateStatementBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/UpdateStatementBinder.java
index 104913ec9b5..773519caa47 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/UpdateStatementBinder.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/dml/UpdateStatementBinder.java
@@ -24,7 +24,6 @@ import org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderCon
 import org.apache.shardingsphere.infra.binder.segment.where.WhereSegmentBinder;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinder;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
-import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.UpdateStatement;
 
@@ -38,20 +37,13 @@ import java.util.Map;
 public final class UpdateStatementBinder implements SQLStatementBinder<UpdateStatement> {
     
     @Override
-    public UpdateStatement bind(final UpdateStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName) {
-        return bind(sqlStatement, metaData, currentDatabaseName, Collections.emptyMap());
-    }
-    
-    private UpdateStatement bind(final UpdateStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName,
-                                 final Map<String, TableSegmentBinderContext> externalTableBinderContexts) {
+    public UpdateStatement bind(final UpdateStatement sqlStatement, final SQLStatementBinderContext binderContext) {
         UpdateStatement result = copy(sqlStatement);
         Map<String, TableSegmentBinderContext> tableBinderContexts = new LinkedHashMap<>();
-        SQLStatementBinderContext statementBinderContext = new SQLStatementBinderContext(sqlStatement, metaData, currentDatabaseName);
-        statementBinderContext.getExternalTableBinderContexts().putAll(externalTableBinderContexts);
-        TableSegment boundedTableSegment = TableSegmentBinder.bind(sqlStatement.getTable(), statementBinderContext, tableBinderContexts, Collections.emptyMap());
+        TableSegment boundedTableSegment = TableSegmentBinder.bind(sqlStatement.getTable(), binderContext, tableBinderContexts, Collections.emptyMap());
         result.setTable(boundedTableSegment);
-        sqlStatement.getAssignmentSegment().ifPresent(optional -> result.setSetAssignment(AssignmentSegmentBinder.bind(optional, statementBinderContext, tableBinderContexts, Collections.emptyMap())));
-        sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, statementBinderContext, tableBinderContexts, Collections.emptyMap())));
+        sqlStatement.getAssignmentSegment().ifPresent(optional -> result.setSetAssignment(AssignmentSegmentBinder.bind(optional, binderContext, tableBinderContexts, Collections.emptyMap())));
+        sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, binderContext, tableBinderContexts, Collections.emptyMap())));
         return result;
     }
     
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/type/DDLStatementBindEngine.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/type/DDLStatementBindEngine.java
index c1e72c42c0f..d87c6f442f0 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/type/DDLStatementBindEngine.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/type/DDLStatementBindEngine.java
@@ -18,6 +18,7 @@
 package org.apache.shardingsphere.infra.binder.type;
 
 import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
 import org.apache.shardingsphere.infra.binder.statement.ddl.CursorStatementBinder;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CursorStatement;
@@ -40,8 +41,9 @@ public final class DDLStatementBindEngine {
      * @return bound DDL statement
      */
     public DDLStatement bind(final DDLStatement statement) {
+        SQLStatementBinderContext binderContext = new SQLStatementBinderContext(statement, metaData, currentDatabaseName);
         if (statement instanceof CursorStatement) {
-            return new CursorStatementBinder().bind((CursorStatement) statement, metaData, currentDatabaseName);
+            return new CursorStatementBinder().bind((CursorStatement) statement, binderContext);
         }
         return statement;
     }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/type/DMLStatementBindEngine.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/type/DMLStatementBindEngine.java
index 72bbd3fdc65..c2c74aa6f23 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/type/DMLStatementBindEngine.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/type/DMLStatementBindEngine.java
@@ -18,6 +18,7 @@
 package org.apache.shardingsphere.infra.binder.type;
 
 import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
 import org.apache.shardingsphere.infra.binder.statement.dml.DeleteStatementBinder;
 import org.apache.shardingsphere.infra.binder.statement.dml.InsertStatementBinder;
 import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementBinder;
@@ -46,17 +47,18 @@ public final class DMLStatementBindEngine {
      * @return bound DML statement
      */
     public DMLStatement bind(final DMLStatement statement) {
+        SQLStatementBinderContext binderContext = new SQLStatementBinderContext(statement, metaData, currentDatabaseName);
         if (statement instanceof SelectStatement) {
-            return new SelectStatementBinder().bind((SelectStatement) statement, metaData, currentDatabaseName);
+            return new SelectStatementBinder().bind((SelectStatement) statement, binderContext);
         }
         if (statement instanceof InsertStatement) {
-            return new InsertStatementBinder().bind((InsertStatement) statement, metaData, currentDatabaseName);
+            return new InsertStatementBinder().bind((InsertStatement) statement, binderContext);
         }
         if (statement instanceof UpdateStatement) {
-            return new UpdateStatementBinder().bind((UpdateStatement) statement, metaData, currentDatabaseName);
+            return new UpdateStatementBinder().bind((UpdateStatement) statement, binderContext);
         }
         if (statement instanceof DeleteStatement) {
-            return new DeleteStatementBinder().bind((DeleteStatement) statement, metaData, currentDatabaseName);
+            return new DeleteStatementBinder().bind((DeleteStatement) statement, binderContext);
         }
         return statement;
     }
diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/DeleteStatementBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/DeleteStatementBinderTest.java
index efdd4c7a761..03c41344e28 100644
--- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/DeleteStatementBinderTest.java
+++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/DeleteStatementBinderTest.java
@@ -54,7 +54,7 @@ class DeleteStatementBinderTest {
         deleteStatement.setTable(simpleTableSegment);
         deleteStatement.setWhere(new WhereSegment(0, 0, new BinaryOperationExpression(0, 0, new ColumnSegment(0, 0, new IdentifierValue("status")),
                 new LiteralExpressionSegment(0, 0, 0), "=", "status = 1")));
-        DeleteStatement actual = new DeleteStatementBinder().bind(deleteStatement, createMetaData(), DefaultDatabase.LOGIC_NAME);
+        DeleteStatement actual = new DeleteStatementBinder().bind(deleteStatement, new SQLStatementBinderContext(deleteStatement, createMetaData(), DefaultDatabase.LOGIC_NAME));
         assertThat(actual, not(deleteStatement));
         assertThat(actual.getTable(), not(deleteStatement.getTable()));
         assertThat(actual.getTable(), instanceOf(SimpleTableSegment.class));
diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/InsertStatementBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/InsertStatementBinderTest.java
index ea06a6eff2c..54d65a5bcfe 100644
--- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/InsertStatementBinderTest.java
+++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/InsertStatementBinderTest.java
@@ -62,7 +62,7 @@ class InsertStatementBinderTest {
                 new ColumnSegment(0, 0, new IdentifierValue("user_id")), new ColumnSegment(0, 0, new IdentifierValue("status")))));
         insertStatement.getValues().add(new InsertValuesSegment(0, 0, Arrays.asList(new LiteralExpressionSegment(0, 0, 1),
                 new LiteralExpressionSegment(0, 0, 1), new LiteralExpressionSegment(0, 0, "OK"))));
-        InsertStatement actual = new InsertStatementBinder().bind(insertStatement, createMetaData(), DefaultDatabase.LOGIC_NAME);
+        InsertStatement actual = new InsertStatementBinder().bind(insertStatement, new SQLStatementBinderContext(insertStatement, createMetaData(), DefaultDatabase.LOGIC_NAME));
         assertThat(actual, not(insertStatement));
         assertThat(actual.getTable().getTableName(), not(insertStatement.getTable().getTableName()));
         assertTrue(actual.getInsertColumns().isPresent());
@@ -105,7 +105,7 @@ class InsertStatementBinderTest {
         insertStatement.setInsertSelect(new SubquerySegment(0, 0, subSelectStatement, ""));
         insertStatement.getValues().add(new InsertValuesSegment(0, 0, Arrays.asList(new LiteralExpressionSegment(0, 0, 1),
                 new LiteralExpressionSegment(0, 0, 1), new LiteralExpressionSegment(0, 0, "OK"))));
-        InsertStatement actual = new InsertStatementBinder().bind(insertStatement, createMetaData(), DefaultDatabase.LOGIC_NAME);
+        InsertStatement actual = new InsertStatementBinder().bind(insertStatement, new SQLStatementBinderContext(insertStatement, createMetaData(), DefaultDatabase.LOGIC_NAME));
         assertThat(actual, not(insertStatement));
         assertThat(actual.getTable().getTableName(), not(insertStatement.getTable().getTableName()));
         assertTrue(actual.getInsertColumns().isPresent());
@@ -127,7 +127,7 @@ class InsertStatementBinderTest {
         insertStatement.setInsertSelect(new SubquerySegment(0, 0, subSelectStatement, ""));
         insertStatement.getValues().add(new InsertValuesSegment(0, 0, Arrays.asList(new LiteralExpressionSegment(0, 0, 1),
                 new LiteralExpressionSegment(0, 0, 1), new LiteralExpressionSegment(0, 0, "OK"))));
-        InsertStatement actual = new InsertStatementBinder().bind(insertStatement, createMetaData(), DefaultDatabase.LOGIC_NAME);
+        InsertStatement actual = new InsertStatementBinder().bind(insertStatement, new SQLStatementBinderContext(insertStatement, createMetaData(), DefaultDatabase.LOGIC_NAME));
         assertThat(actual, not(insertStatement));
         assertThat(actual.getTable().getTableName(), not(insertStatement.getTable().getTableName()));
         assertInsertColumns(actual.getDerivedInsertColumns());
diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/SelectStatementBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/SelectStatementBinderTest.java
index 4f938fcfe93..d085f55b860 100644
--- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/SelectStatementBinderTest.java
+++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/SelectStatementBinderTest.java
@@ -81,7 +81,7 @@ class SelectStatementBinderTest {
         SimpleTableSegment simpleTableSegment = new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order")));
         selectStatement.setFrom(simpleTableSegment);
         selectStatement.setWhere(mockWhereSegment());
-        SelectStatement actual = new SelectStatementBinder().bind(selectStatement, createMetaData(), DefaultDatabase.LOGIC_NAME);
+        SelectStatement actual = new SelectStatementBinder().bind(selectStatement, new SQLStatementBinderContext(selectStatement, createMetaData(), DefaultDatabase.LOGIC_NAME));
         assertThat(actual, not(selectStatement));
         assertTrue(actual.getFrom().isPresent());
         assertThat(actual.getFrom().get(), not(simpleTableSegment));
@@ -149,11 +149,11 @@ class SelectStatementBinderTest {
         ShardingSphereMetaData metaData =
                 new ShardingSphereMetaData(Collections.singletonMap(DefaultDatabase.LOGIC_NAME, database), resourceMetaData, ruleMetaData, new ConfigurationProperties(new Properties()));
         SelectStatement selectStatement = (SelectStatement) parserEngine.parse(sql, false);
-        SelectStatement actual = new SelectStatementBinder().bind(selectStatement, metaData, DefaultDatabase.LOGIC_NAME);
+        SelectStatement actual = new SelectStatementBinder().bind(selectStatement, new SQLStatementBinderContext(selectStatement, metaData, DefaultDatabase.LOGIC_NAME));
         assertThat(actual, not(selectStatement));
         assertThat(actual, instanceOf(OracleSelectStatement.class));
-        assertTrue(((OracleSelectStatement) actual).getWithSegment().isPresent());
-        assertThat(((OracleSelectStatement) actual).getWithSegment().get().getCommonTableExpressions().size(), is(5));
+        assertTrue(actual.getWithSegment().isPresent());
+        assertThat(actual.getWithSegment().get().getCommonTableExpressions().size(), is(5));
     }
     
     @Test
@@ -179,11 +179,11 @@ class SelectStatementBinderTest {
         ShardingSphereMetaData metaData =
                 new ShardingSphereMetaData(Collections.singletonMap(DefaultDatabase.LOGIC_NAME, database), resourceMetaData, ruleMetaData, new ConfigurationProperties(new Properties()));
         SelectStatement selectStatement = (SelectStatement) parserEngine.parse(sql, false);
-        SelectStatement actual = new SelectStatementBinder().bind(selectStatement, metaData, DefaultDatabase.LOGIC_NAME);
+        SelectStatement actual = new SelectStatementBinder().bind(selectStatement, new SQLStatementBinderContext(selectStatement, metaData, DefaultDatabase.LOGIC_NAME));
         assertThat(actual, not(selectStatement));
         assertThat(actual, instanceOf(OracleSelectStatement.class));
-        assertTrue(((OracleSelectStatement) actual).getWithSegment().isPresent());
-        assertThat(((OracleSelectStatement) actual).getWithSegment().get().getCommonTableExpressions().size(), is(1));
+        assertTrue(actual.getWithSegment().isPresent());
+        assertThat(actual.getWithSegment().get().getCommonTableExpressions().size(), is(1));
     }
     
     private Map<String, ShardingSphereSchema> buildSchemas() {
diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/UpdateStatementBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/UpdateStatementBinderTest.java
index 370b1e12f5a..b982860dc8d 100644
--- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/UpdateStatementBinderTest.java
+++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/statement/UpdateStatementBinderTest.java
@@ -54,7 +54,7 @@ class UpdateStatementBinderTest {
         updateStatement.setTable(simpleTableSegment);
         updateStatement.setWhere(new WhereSegment(0, 0, new BinaryOperationExpression(0, 0, new ColumnSegment(0, 0, new IdentifierValue("status")),
                 new LiteralExpressionSegment(0, 0, 0), "=", "status = 1")));
-        UpdateStatement actual = new UpdateStatementBinder().bind(updateStatement, createMetaData(), DefaultDatabase.LOGIC_NAME);
+        UpdateStatement actual = new UpdateStatementBinder().bind(updateStatement, new SQLStatementBinderContext(updateStatement, createMetaData(), DefaultDatabase.LOGIC_NAME));
         assertThat(actual, not(updateStatement));
         assertThat(actual.getTable(), not(updateStatement.getTable()));
         assertThat(actual.getTable(), instanceOf(SimpleTableSegment.class));