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 17dbb3fe233 Remove useless findTableNamesByColumnProjection and 
simplify code (#27963)
17dbb3fe233 is described below

commit 17dbb3fe2332c74ab9d937e2daf9d7896bfd0d96
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Tue Aug 8 08:26:18 2023 +0800

    Remove useless findTableNamesByColumnProjection and simplify code (#27963)
---
 .../encrypt/merge/dql/EncryptMergedResult.java     | 34 ++--------
 .../generator/EncryptProjectionTokenGenerator.java | 79 ++++++++--------------
 .../EncryptProjectionTokenGeneratorTest.java       |  7 +-
 .../mask/merge/dql/MaskAlgorithmMetaData.java      | 23 +------
 .../mask/merge/dql/MaskAlgorithmMetaDataTest.java  |  6 +-
 .../engine/type/standard/SubqueryRouteTest.java    |  2 +-
 .../standard/assertion/ShardingRouteAssert.java    |  3 +-
 .../context/segment/table/TablesContext.java       | 69 -------------------
 .../expression/ExpressionSegmentBinder.java        | 63 +++++++++++++++++
 .../BinaryOperationExpressionBinder.java}          | 27 ++++----
 .../expression/{ => impl}/ColumnSegmentBinder.java |  2 +-
 .../ExistsSubqueryExpressionBinder.java}           | 23 +++----
 .../InExpressionBinder.java}                       | 27 ++++----
 .../SubqueryExpressionSegmentBinder.java}          | 23 +++----
 .../{ => impl}/SubquerySegmentBinder.java          |  2 +-
 .../projection/ProjectionsSegmentBinder.java       | 19 ++++--
 .../impl/ColumnProjectionSegmentBinder.java        |  2 +-
 ...r.java => SubqueryProjectionSegmentBinder.java} | 30 ++++----
 .../WhereSegmentBinder.java}                       | 26 +++----
 .../statement/dml/InsertStatementBinder.java       |  2 +-
 .../statement/dml/SelectStatementBinder.java       |  5 +-
 .../context/segment/table/TablesContextTest.java   | 59 ----------------
 .../resultset/SQLFederationResultSetMetaData.java  |  5 +-
 .../dml/item/SubqueryProjectionSegment.java        |  9 +++
 .../prepare/MySQLComStmtPrepareExecutor.java       |  9 +--
 25 files changed, 220 insertions(+), 336 deletions(-)

diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/merge/dql/EncryptMergedResult.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/merge/dql/EncryptMergedResult.java
index 6432674c11a..32724b912c6 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/merge/dql/EncryptMergedResult.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/merge/dql/EncryptMergedResult.java
@@ -21,7 +21,6 @@ import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.encrypt.rule.EncryptRule;
 import org.apache.shardingsphere.encrypt.rule.column.EncryptColumn;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ColumnProjection;
-import 
org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
 import 
org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
 import org.apache.shardingsphere.infra.merge.result.MergedResult;
@@ -31,8 +30,6 @@ import java.io.InputStream;
 import java.io.Reader;
 import java.sql.SQLException;
 import java.util.Calendar;
-import java.util.Collections;
-import java.util.Map;
 import java.util.Optional;
 
 /**
@@ -60,33 +57,16 @@ public final class EncryptMergedResult implements 
MergedResult {
         if (!columnProjection.isPresent()) {
             return mergedResult.getValue(columnIndex, type);
         }
-        TablesContext tablesContext = 
selectStatementContext.getTablesContext();
-        String schemaName = tablesContext.getSchemaName().orElseGet(() -> new 
DatabaseTypeRegistry(selectStatementContext.getDatabaseType()).getDefaultSchemaName(database.getName()));
-        ColumnProjection originalColumn = new 
ColumnProjection(columnProjection.get().getOriginalTable(), 
columnProjection.get().getOriginalColumn(), null, 
selectStatementContext.getDatabaseType());
-        Map<String, String> expressionTableNames = 
tablesContext.findTableNamesByColumnProjection(Collections.singletonList(originalColumn),
 database.getSchema(schemaName));
-        Optional<String> tableName = findTableName(originalColumn, 
expressionTableNames);
-        if (!tableName.isPresent()) {
-            return mergedResult.getValue(columnIndex, type);
-        }
-        if (!encryptRule.findEncryptTable(tableName.get()).map(optional -> 
optional.isEncryptColumn(originalColumn.getName().getValue())).orElse(false)) {
+        String originalTableName = 
columnProjection.get().getOriginalTable().getValue();
+        String originalColumnName = 
columnProjection.get().getOriginalColumn().getValue();
+        if (!encryptRule.findEncryptTable(originalTableName).map(optional -> 
optional.isEncryptColumn(originalColumnName)).orElse(false)) {
             return mergedResult.getValue(columnIndex, type);
         }
         Object cipherValue = mergedResult.getValue(columnIndex, Object.class);
-        EncryptColumn encryptColumn = 
encryptRule.getEncryptTable(tableName.get()).getEncryptColumn(originalColumn.getName().getValue());
-        return encryptColumn.getCipher().decrypt(database.getName(), 
schemaName, tableName.get(), originalColumn.getName().getValue(), cipherValue);
-    }
-    
-    private Optional<String> findTableName(final ColumnProjection 
columnProjection, final Map<String, String> columnTableNames) {
-        String tableName = 
columnTableNames.get(columnProjection.getExpression());
-        if (null != tableName) {
-            return Optional.of(tableName);
-        }
-        for (String each : 
selectStatementContext.getTablesContext().getTableNames()) {
-            if (encryptRule.findEncryptTable(each).map(optional -> 
optional.isEncryptColumn(columnProjection.getName().getValue())).orElse(false)) 
{
-                return Optional.of(each);
-            }
-        }
-        return Optional.empty();
+        EncryptColumn encryptColumn = 
encryptRule.getEncryptTable(originalTableName).getEncryptColumn(originalColumnName);
+        String schemaName =
+                
selectStatementContext.getTablesContext().getSchemaName().orElseGet(() -> new 
DatabaseTypeRegistry(selectStatementContext.getDatabaseType()).getDefaultSchemaName(database.getName()));
+        return encryptColumn.getCipher().decrypt(database.getName(), 
schemaName, originalTableName, originalColumnName, cipherValue);
     }
     
     @Override
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
index 9bfdd0879b5..99bfe795eb5 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
@@ -35,10 +35,8 @@ import 
org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatem
 import 
org.apache.shardingsphere.infra.database.core.metadata.database.DialectDatabaseMetaData;
 import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
 import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
-import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import 
org.apache.shardingsphere.infra.rewrite.sql.token.generator.CollectionSQLTokenGenerator;
 import 
org.apache.shardingsphere.infra.rewrite.sql.token.generator.aware.PreviousSQLTokensAware;
-import 
org.apache.shardingsphere.infra.rewrite.sql.token.generator.aware.SchemaMetaDataAware;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.SQLToken;
 import 
org.apache.shardingsphere.infra.rewrite.sql.token.pojo.generic.SubstitutableColumnNameToken;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.SubqueryType;
@@ -48,29 +46,25 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.Shorthan
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 
 /**
  * Projection token generator for encrypt.
  */
 @Setter
-public final class EncryptProjectionTokenGenerator implements 
CollectionSQLTokenGenerator<SQLStatementContext>, PreviousSQLTokensAware, 
SchemaMetaDataAware, EncryptRuleAware, DatabaseTypeAware {
+public final class EncryptProjectionTokenGenerator implements 
CollectionSQLTokenGenerator<SQLStatementContext>, PreviousSQLTokensAware, 
EncryptRuleAware, DatabaseTypeAware {
     
     private List<SQLToken> previousSQLTokens;
     
     private EncryptRule encryptRule;
     
-    private String databaseName;
-    
-    private Map<String, ShardingSphereSchema> schemas;
-    
     private DatabaseType databaseType;
     
     @Override
@@ -91,31 +85,37 @@ public final class EncryptProjectionTokenGenerator 
implements CollectionSQLToken
     }
     
     private void addGenerateSQLTokens(final Collection<SQLToken> sqlTokens, 
final SelectStatementContext selectStatementContext) {
-        Map<String, String> columnTableNames = 
getColumnTableNames(selectStatementContext);
         for (ProjectionSegment each : 
selectStatementContext.getSqlStatement().getProjections().getProjections()) {
             SubqueryType subqueryType = 
selectStatementContext.getSubqueryType();
             if (each instanceof ColumnProjectionSegment) {
                 ColumnProjectionSegment columnSegment = 
(ColumnProjectionSegment) each;
                 ColumnProjection columnProjection = 
buildColumnProjection(columnSegment);
-                String tableName = 
columnTableNames.get(columnProjection.getExpression());
-                if (null == tableName) {
-                    continue;
-                }
-                Optional<EncryptTable> encryptTable = 
encryptRule.findEncryptTable(tableName);
-                if (encryptTable.isPresent() && 
encryptTable.get().isEncryptColumn(columnProjection.getName().getValue()) && 
!containsTableSubquery(selectStatementContext)) {
-                    
sqlTokens.add(generateSQLToken(encryptTable.get().getEncryptColumn(columnProjection.getName().getValue()),
 columnSegment, columnProjection, subqueryType));
+                String originalColumnName = 
columnProjection.getOriginalColumn().getValue();
+                Optional<EncryptTable> encryptTable = 
encryptRule.findEncryptTable(columnProjection.getOriginalTable().getValue());
+                if (encryptTable.isPresent() && 
encryptTable.get().isEncryptColumn(originalColumnName) && 
!containsTableSubquery(selectStatementContext.getSqlStatement().getFrom())) {
+                    
sqlTokens.add(generateSQLToken(encryptTable.get().getEncryptColumn(originalColumnName),
 columnSegment, columnProjection, subqueryType));
                 }
             }
             if (each instanceof ShorthandProjectionSegment) {
                 ShorthandProjectionSegment shorthandSegment = 
(ShorthandProjectionSegment) each;
                 Collection<Projection> actualColumns = 
getShorthandProjection(shorthandSegment, 
selectStatementContext.getProjectionsContext()).getActualColumns();
                 if (!actualColumns.isEmpty()) {
-                    sqlTokens.add(generateSQLToken(shorthandSegment, 
actualColumns, selectStatementContext, subqueryType, columnTableNames));
+                    sqlTokens.add(generateSQLToken(shorthandSegment, 
actualColumns, selectStatementContext, subqueryType));
                 }
             }
         }
     }
     
+    private boolean containsTableSubquery(final TableSegment tableSegment) {
+        if (tableSegment instanceof SubqueryTableSegment) {
+            return true;
+        } else if (tableSegment instanceof JoinTableSegment) {
+            JoinTableSegment joinTableSegment = (JoinTableSegment) 
tableSegment;
+            return containsTableSubquery(joinTableSegment.getLeft()) || 
containsTableSubquery(joinTableSegment.getRight());
+        }
+        return false;
+    }
+    
     private SubstitutableColumnNameToken generateSQLToken(final EncryptColumn 
encryptColumn, final ColumnProjectionSegment columnSegment,
                                                           final 
ColumnProjection columnProjection, final SubqueryType subqueryType) {
         Collection<Projection> projections = 
generateProjections(encryptColumn, columnProjection, subqueryType, false, null);
@@ -125,16 +125,19 @@ public final class EncryptProjectionTokenGenerator 
implements CollectionSQLToken
     }
     
     private SubstitutableColumnNameToken generateSQLToken(final 
ShorthandProjectionSegment segment, final Collection<Projection> actualColumns,
-                                                          final 
SelectStatementContext selectStatementContext, final SubqueryType subqueryType, 
final Map<String, String> columnTableNames) {
+                                                          final 
SelectStatementContext selectStatementContext, final SubqueryType subqueryType) 
{
         List<Projection> projections = new LinkedList<>();
         for (Projection each : actualColumns) {
-            String tableName = columnTableNames.get(each.getExpression());
-            Optional<EncryptTable> encryptTable = null == tableName ? 
Optional.empty() : encryptRule.findEncryptTable(tableName);
-            if (!encryptTable.isPresent() || 
!encryptTable.get().isEncryptColumn(each.getColumnLabel()) || 
containsTableSubquery(selectStatementContext)) {
+            if (each instanceof ColumnProjection) {
+                Optional<EncryptTable> encryptTable = 
encryptRule.findEncryptTable(((ColumnProjection) 
each).getOriginalTable().getValue());
+                if (encryptTable.isPresent() && 
encryptTable.get().isEncryptColumn(((ColumnProjection) 
each).getOriginalColumn().getValue())
+                        && 
!containsTableSubquery(selectStatementContext.getSqlStatement().getFrom())) {
+                    EncryptColumn encryptColumn = 
encryptTable.get().getEncryptColumn(((ColumnProjection) 
each).getName().getValue());
+                    projections.addAll(generateProjections(encryptColumn, 
(ColumnProjection) each, subqueryType, true, segment));
+                    continue;
+                }
                 projections.add(each.getAlias().filter(alias -> 
!DerivedColumn.isDerivedColumnName(alias.getValue()))
                         .map(optional -> (Projection) new 
ColumnProjection(null, optional, null, databaseType)).orElse(each));
-            } else if (each instanceof ColumnProjection) {
-                
projections.addAll(generateProjections(encryptTable.get().getEncryptColumn(((ColumnProjection)
 each).getName().getValue()), (ColumnProjection) each, subqueryType, true, 
segment));
             }
         }
         int startIndex = segment.getOwner().isPresent() ? 
segment.getOwner().get().getStartIndex() : segment.getStartIndex();
@@ -143,34 +146,12 @@ public final class EncryptProjectionTokenGenerator 
implements CollectionSQLToken
         return new SubstitutableColumnNameToken(startIndex, 
segment.getStopIndex(), projections, 
dialectDatabaseMetaData.getQuoteCharacter());
     }
     
-    private boolean containsTableSubquery(final SelectStatementContext 
selectStatementContext) {
-        if (selectStatementContext.getSqlStatement().getFrom() instanceof 
SubqueryTableSegment) {
-            return true;
-        } else if (selectStatementContext.getSqlStatement().getFrom() 
instanceof JoinTableSegment) {
-            JoinTableSegment joinTableSegment = (JoinTableSegment) 
selectStatementContext.getSqlStatement().getFrom();
-            return joinTableSegment.getLeft() instanceof SubqueryTableSegment 
|| joinTableSegment.getRight() instanceof SubqueryTableSegment;
-        }
-        return false;
-    }
-    
     private ColumnProjection buildColumnProjection(final 
ColumnProjectionSegment segment) {
         IdentifierValue owner = 
segment.getColumn().getOwner().map(OwnerSegment::getIdentifier).orElse(null);
-        return new ColumnProjection(owner, 
segment.getColumn().getIdentifier(), segment.getAliasName().isPresent() ? 
segment.getAlias().orElse(null) : null, databaseType);
-    }
-    
-    private Map<String, String> getColumnTableNames(final 
SelectStatementContext selectStatementContext) {
-        Collection<ColumnProjection> columns = new LinkedList<>();
-        for (Projection projection : 
selectStatementContext.getProjectionsContext().getProjections()) {
-            if (projection instanceof ColumnProjection) {
-                columns.add((ColumnProjection) projection);
-            }
-            if (projection instanceof ShorthandProjection) {
-                columns.addAll(((ShorthandProjection) 
projection).getColumnProjections());
-            }
-        }
-        String defaultSchema = new 
DatabaseTypeRegistry(selectStatementContext.getDatabaseType()).getDefaultSchemaName(databaseName);
-        ShardingSphereSchema schema = 
selectStatementContext.getTablesContext().getSchemaName().map(schemas::get).orElseGet(()
 -> schemas.get(defaultSchema));
-        return 
selectStatementContext.getTablesContext().findTableNamesByColumnProjection(columns,
 schema);
+        ColumnProjection result = new ColumnProjection(owner, 
segment.getColumn().getIdentifier(), segment.getAliasName().isPresent() ? 
segment.getAlias().orElse(null) : null, databaseType);
+        result.setOriginalColumn(segment.getColumn().getOriginalColumn());
+        result.setOriginalTable(segment.getColumn().getOriginalTable());
+        return result;
     }
     
     private Collection<Projection> generateProjections(final EncryptColumn 
encryptColumn, final ColumnProjection column,
diff --git 
a/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGeneratorTest.java
 
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGeneratorTest.java
index 1180ccb294f..fe4e21962d3 100644
--- 
a/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGeneratorTest.java
+++ 
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGeneratorTest.java
@@ -24,7 +24,6 @@ import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.
 import 
org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
 import 
org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
-import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.SQLToken;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
@@ -58,8 +57,6 @@ class EncryptProjectionTokenGeneratorTest {
     @BeforeEach
     void setup() {
         generator.setEncryptRule(mockEncryptRule());
-        generator.setDatabaseName("db_schema");
-        generator.setSchemas(Collections.singletonMap("test", 
mock(ShardingSphereSchema.class)));
     }
     
     private EncryptRule mockEncryptRule() {
@@ -82,6 +79,8 @@ class EncryptProjectionTokenGeneratorTest {
         SimpleTableSegment doctorTable = new SimpleTableSegment(new 
TableNameSegment(0, 0, new IdentifierValue("doctor")));
         doctorTable.setAlias(new AliasSegment(0, 0, new IdentifierValue("a")));
         ColumnSegment column = new ColumnSegment(0, 0, new 
IdentifierValue("mobile"));
+        column.setOriginalColumn(new IdentifierValue("mobile"));
+        column.setOriginalTable(new IdentifierValue("doctor"));
         column.setOwner(new OwnerSegment(0, 0, new IdentifierValue("a")));
         ProjectionsSegment projections = mock(ProjectionsSegment.class);
         
when(projections.getProjections()).thenReturn(Collections.singletonList(new 
ColumnProjectionSegment(column)));
@@ -101,6 +100,8 @@ class EncryptProjectionTokenGeneratorTest {
         SimpleTableSegment doctorTable = new SimpleTableSegment(new 
TableNameSegment(0, 0, new IdentifierValue("doctor")));
         doctorTable.setAlias(new AliasSegment(0, 0, new IdentifierValue("a")));
         ColumnSegment column = new ColumnSegment(0, 0, new 
IdentifierValue("mobile"));
+        column.setOriginalColumn(new IdentifierValue("mobile"));
+        column.setOriginalTable(new IdentifierValue("doctor"));
         column.setOwner(new OwnerSegment(0, 0, new IdentifierValue("a")));
         ProjectionsSegment projections = mock(ProjectionsSegment.class);
         
when(projections.getProjections()).thenReturn(Collections.singletonList(new 
ColumnProjectionSegment(column)));
diff --git 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/merge/dql/MaskAlgorithmMetaData.java
 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/merge/dql/MaskAlgorithmMetaData.java
index 0a4da833854..70b85687899 100644
--- 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/merge/dql/MaskAlgorithmMetaData.java
+++ 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/merge/dql/MaskAlgorithmMetaData.java
@@ -20,16 +20,12 @@ package org.apache.shardingsphere.mask.merge.dql;
 import lombok.RequiredArgsConstructor;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ColumnProjection;
-import 
org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
 import 
org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
-import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.mask.rule.MaskRule;
 import org.apache.shardingsphere.mask.spi.MaskAlgorithm;
 
-import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 
 /**
@@ -56,11 +52,7 @@ public final class MaskAlgorithmMetaData {
         if (!columnProjection.isPresent()) {
             return Optional.empty();
         }
-        TablesContext tablesContext = 
selectStatementContext.getTablesContext();
-        String schemaName = tablesContext.getSchemaName().orElseGet(() -> new 
DatabaseTypeRegistry(selectStatementContext.getDatabaseType()).getDefaultSchemaName(database.getName()));
-        Map<String, String> expressionTableNames = 
tablesContext.findTableNamesByColumnProjection(
-                Collections.singletonList(columnProjection.get()), 
database.getSchema(schemaName));
-        return findTableName(columnProjection.get(), 
expressionTableNames).flatMap(optional -> maskRule.findMaskAlgorithm(optional, 
columnProjection.get().getName().getValue()));
+        return 
maskRule.findMaskAlgorithm(columnProjection.get().getOriginalTable().getValue(),
 columnProjection.get().getName().getValue());
     }
     
     private Optional<ColumnProjection> findColumnProjection(final int 
columnIndex) {
@@ -71,17 +63,4 @@ public final class MaskAlgorithmMetaData {
         Projection projection = expandProjections.get(columnIndex - 1);
         return projection instanceof ColumnProjection ? 
Optional.of((ColumnProjection) projection) : Optional.empty();
     }
-    
-    private Optional<String> findTableName(final ColumnProjection 
columnProjection, final Map<String, String> columnTableNames) {
-        String tableName = 
columnTableNames.get(columnProjection.getExpression());
-        if (null != tableName) {
-            return Optional.of(tableName);
-        }
-        for (String each : 
selectStatementContext.getTablesContext().getTableNames()) {
-            if (maskRule.findMaskAlgorithm(each, 
columnProjection.getName().getValue()).isPresent()) {
-                return Optional.of(each);
-            }
-        }
-        return Optional.empty();
-    }
 }
diff --git 
a/features/mask/core/src/test/java/org/apache/shardingsphere/mask/merge/dql/MaskAlgorithmMetaDataTest.java
 
b/features/mask/core/src/test/java/org/apache/shardingsphere/mask/merge/dql/MaskAlgorithmMetaDataTest.java
index 9de8619e000..eae75d2a29c 100644
--- 
a/features/mask/core/src/test/java/org/apache/shardingsphere/mask/merge/dql/MaskAlgorithmMetaDataTest.java
+++ 
b/features/mask/core/src/test/java/org/apache/shardingsphere/mask/merge/dql/MaskAlgorithmMetaDataTest.java
@@ -24,6 +24,7 @@ import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.mask.rule.MaskRule;
 import org.apache.shardingsphere.mask.spi.MaskAlgorithm;
+import 
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Answers;
@@ -55,7 +56,10 @@ class MaskAlgorithmMetaDataTest {
     @Test
     void assertFindMaskAlgorithmByColumnIndex() {
         when(maskRule.findMaskAlgorithm("t_order", 
"order_id")).thenReturn(Optional.of(TypedSPILoader.getService(MaskAlgorithm.class,
 "MD5")));
-        
when(selectStatementContext.getProjectionsContext().getExpandProjections()).thenReturn(Collections.singletonList(new
 ColumnProjection(null, "order_id", null, mock(DatabaseType.class))));
+        ColumnProjection columnProjection = new ColumnProjection(null, 
"order_id", null, mock(DatabaseType.class));
+        columnProjection.setOriginalColumn(new IdentifierValue("order_id"));
+        columnProjection.setOriginalTable(new IdentifierValue("t_order"));
+        
when(selectStatementContext.getProjectionsContext().getExpandProjections()).thenReturn(Collections.singletonList(columnProjection));
         
when(selectStatementContext.getTablesContext().getTableNames()).thenReturn(Collections.singletonList("t_order"));
         Optional<MaskAlgorithm> actual = new MaskAlgorithmMetaData(database, 
maskRule, selectStatementContext).findMaskAlgorithmByColumnIndex(1);
         assertTrue(actual.isPresent());
diff --git 
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SubqueryRouteTest.java
 
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SubqueryRouteTest.java
index 95d9e28a684..2622fe3b6d5 100644
--- 
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SubqueryRouteTest.java
+++ 
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SubqueryRouteTest.java
@@ -45,7 +45,7 @@ class SubqueryRouteTest {
         HintManager hintManager = HintManager.getInstance();
         hintManager.addDatabaseShardingValue("t_hint_test", 1);
         hintManager.addTableShardingValue("t_hint_test", 1);
-        String sql = "select count(*) from t_hint_test where user_id = (select 
t_hint_test from t_hint_test where user_id in (?,?,?)) ";
+        String sql = "select count(*) from t_hint_test where user_id = (select 
user_id from t_hint_test where user_id in (?,?,?)) ";
         ShardingRouteAssert.assertRoute(sql, Arrays.asList(1, 3, 5));
         hintManager.close();
     }
diff --git 
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/assertion/ShardingRouteAssert.java
 
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/assertion/ShardingRouteAssert.java
index a8caa0b5cde..06b396c70d3 100644
--- 
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/assertion/ShardingRouteAssert.java
+++ 
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/assertion/ShardingRouteAssert.java
@@ -108,7 +108,8 @@ public final class ShardingRouteAssert {
         tables.put("t_category", new ShardingSphereTable("t_category", 
Collections.emptyList(), Collections.emptyList(), Collections.emptyList()));
         tables.put("t_product", new ShardingSphereTable("t_product", 
Collections.emptyList(), Collections.emptyList(), Collections.emptyList()));
         tables.put("t_user", new ShardingSphereTable("t_user", 
Collections.emptyList(), Collections.emptyList(), Collections.emptyList()));
-        tables.put("t_hint_test", new ShardingSphereTable("t_hint_test", 
Collections.emptyList(), Collections.emptyList(), Collections.emptyList()));
+        tables.put("t_hint_test", new ShardingSphereTable("t_hint_test", 
Collections.singleton(new ShardingSphereColumn("user_id", Types.INTEGER, true, 
false, false, true, false, false)),
+                Collections.emptyList(), Collections.emptyList()));
         return Collections.singletonMap(DefaultDatabase.LOGIC_NAME, new 
ShardingSphereSchema(tables, Collections.emptyMap()));
     }
 }
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/table/TablesContext.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/table/TablesContext.java
index c899a39a9f2..d47750d7fdb 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/table/TablesContext.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/table/TablesContext.java
@@ -20,7 +20,6 @@ package 
org.apache.shardingsphere.infra.binder.context.segment.table;
 import com.google.common.base.Preconditions;
 import lombok.Getter;
 import lombok.ToString;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ColumnProjection;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.subquery.SubqueryTableContext;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.subquery.engine.SubqueryTableContextEngine;
 import 
org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
@@ -138,26 +137,6 @@ public final class TablesContext {
         return result;
     }
     
-    /**
-     * Find expression table name map by column projection.
-     *
-     * @param columns column segment collection
-     * @param schema schema meta data
-     * @return expression table name map
-     */
-    public Map<String, String> findTableNamesByColumnProjection(final 
Collection<ColumnProjection> columns, final ShardingSphereSchema schema) {
-        if (1 == simpleTableSegments.size()) {
-            return findTableNameFromSingleTableByColumnProjection(columns);
-        }
-        Map<String, String> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-        Map<String, Collection<String>> ownerColumnNames = 
getOwnerColumnNamesByColumnProjection(columns);
-        result.putAll(findTableNameFromSQL(ownerColumnNames));
-        Collection<String> noOwnerColumnNames = 
getNoOwnerColumnNamesByColumnProjection(columns);
-        result.putAll(findTableNameFromMetaData(noOwnerColumnNames, schema));
-        result.putAll(findTableNameFromSubqueryByColumnProjection(columns, 
result));
-        return result;
-    }
-    
     private Map<String, String> findTableNameFromSubqueryByColumnSegment(final 
Collection<ColumnSegment> columns, final Map<String, String> ownerTableNames) {
         if (ownerTableNames.size() == columns.size() || 
subqueryTables.isEmpty()) {
             return Collections.emptyMap();
@@ -178,25 +157,6 @@ public final class TablesContext {
         return result;
     }
     
-    private Map<String, String> 
findTableNameFromSubqueryByColumnProjection(final Collection<ColumnProjection> 
columns, final Map<String, String> ownerTableNames) {
-        if (ownerTableNames.size() == columns.size() || 
subqueryTables.isEmpty()) {
-            return Collections.emptyMap();
-        }
-        Map<String, String> result = new LinkedHashMap<>(columns.size(), 1F);
-        for (ColumnProjection each : columns) {
-            if (ownerTableNames.containsKey(each.getExpression())) {
-                continue;
-            }
-            Collection<SubqueryTableContext> subqueryTableContexts = 
each.getOwner().map(optional -> 
subqueryTables.get(each.getOwner().get().getValue())).orElseGet(Collections::emptyList);
-            for (SubqueryTableContext subqueryTableContext : 
subqueryTableContexts) {
-                if 
(subqueryTableContext.getColumnNames().contains(each.getName().getValue())) {
-                    result.put(each.getExpression(), 
subqueryTableContext.getTableName());
-                }
-            }
-        }
-        return result;
-    }
-    
     private Map<String, String> 
findTableNameFromSingleTableByColumnSegment(final Collection<ColumnSegment> 
columns) {
         String tableName = 
simpleTableSegments.iterator().next().getTableName().getIdentifier().getValue();
         Map<String, String> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
@@ -206,15 +166,6 @@ public final class TablesContext {
         return result;
     }
     
-    private Map<String, String> 
findTableNameFromSingleTableByColumnProjection(final 
Collection<ColumnProjection> columns) {
-        String tableName = 
simpleTableSegments.iterator().next().getTableName().getIdentifier().getValue();
-        Map<String, String> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-        for (ColumnProjection each : columns) {
-            result.putIfAbsent(each.getExpression(), tableName);
-        }
-        return result;
-    }
-    
     private Map<String, Collection<String>> 
getOwnerColumnNamesByColumnSegment(final Collection<ColumnSegment> columns) {
         Map<String, Collection<String>> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
         for (ColumnSegment each : columns) {
@@ -226,16 +177,6 @@ public final class TablesContext {
         return result;
     }
     
-    private Map<String, Collection<String>> 
getOwnerColumnNamesByColumnProjection(final Collection<ColumnProjection> 
columns) {
-        Map<String, Collection<String>> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-        for (ColumnProjection each : columns) {
-            if (each.getOwner().isPresent()) {
-                result.computeIfAbsent(each.getOwner().get().getValue(), 
unused -> new LinkedList<>()).add(each.getExpression());
-            }
-        }
-        return result;
-    }
-    
     private Map<String, String> findTableNameFromSQL(final Map<String, 
Collection<String>> ownerColumnNames) {
         if (ownerColumnNames.isEmpty()) {
             return Collections.emptyMap();
@@ -280,16 +221,6 @@ public final class TablesContext {
         return result;
     }
     
-    private Collection<String> getNoOwnerColumnNamesByColumnProjection(final 
Collection<ColumnProjection> columns) {
-        Collection<String> result = new 
TreeSet<>(String.CASE_INSENSITIVE_ORDER);
-        for (ColumnProjection each : columns) {
-            if (!each.getOwner().isPresent()) {
-                result.add(each.getName().getValue());
-            }
-        }
-        return result;
-    }
-    
     /**
      * Get database name.
      *
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/ExpressionSegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/ExpressionSegmentBinder.java
new file mode 100644
index 00000000000..b342ac81d2e
--- /dev/null
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/ExpressionSegmentBinder.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.infra.binder.segment.expression;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import 
org.apache.shardingsphere.infra.binder.segment.expression.impl.BinaryOperationExpressionBinder;
+import 
org.apache.shardingsphere.infra.binder.segment.expression.impl.ExistsSubqueryExpressionBinder;
+import 
org.apache.shardingsphere.infra.binder.segment.expression.impl.InExpressionBinder;
+import 
org.apache.shardingsphere.infra.binder.segment.expression.impl.SubqueryExpressionSegmentBinder;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
+
+/**
+ * Expression segment binder.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ExpressionSegmentBinder {
+    
+    /**
+     * Bind expression segment with metadata.
+     *
+     * @param segment expression segment
+     * @param metaData metaData
+     * @param defaultDatabaseName default database name
+     * @return bounded expression segment
+     */
+    public static ExpressionSegment bind(final ExpressionSegment segment, 
final ShardingSphereMetaData metaData, final String defaultDatabaseName) {
+        if (segment instanceof BinaryOperationExpression) {
+            return 
BinaryOperationExpressionBinder.bind((BinaryOperationExpression) segment, 
metaData, defaultDatabaseName);
+        }
+        if (segment instanceof ExistsSubqueryExpression) {
+            return 
ExistsSubqueryExpressionBinder.bind((ExistsSubqueryExpression) segment, 
metaData, defaultDatabaseName);
+        }
+        if (segment instanceof SubqueryExpressionSegment) {
+            return 
SubqueryExpressionSegmentBinder.bind((SubqueryExpressionSegment) segment, 
metaData, defaultDatabaseName);
+        }
+        if (segment instanceof InExpression) {
+            return InExpressionBinder.bind((InExpression) segment, metaData, 
defaultDatabaseName);
+        }
+        // TODO support more ExpressionSegment bind
+        return segment;
+    }
+}
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/BinaryOperationExpressionBinder.java
similarity index 54%
copy from 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
copy to 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/BinaryOperationExpressionBinder.java
index 7fde0c58618..913aabbcafc 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/BinaryOperationExpressionBinder.java
@@ -15,33 +15,32 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.binder.segment.expression;
+package org.apache.shardingsphere.infra.binder.segment.expression.impl;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import 
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementBinder;
+import 
org.apache.shardingsphere.infra.binder.segment.expression.ExpressionSegmentBinder;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
-import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
-import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 
 /**
- * Subquery segment binder.
+ * Binary operation expression binder.
  */
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class SubquerySegmentBinder {
+public final class BinaryOperationExpressionBinder {
     
     /**
-     * Bind subquery segment with metadata.
+     * Bind binary operation expression with metadata.
      *
-     * @param segment subquery segment
+     * @param segment binary operation expression segment
      * @param metaData metaData
      * @param defaultDatabaseName default database name
-     * @return bounded subquery segment
+     * @return bounded binary operation expression segment
      */
-    public static SubquerySegment bind(final SubquerySegment segment, final 
ShardingSphereMetaData metaData, final String defaultDatabaseName) {
-        SelectStatement boundedSelectStatement = new 
SelectStatementBinder().bind(segment.getSelect(), metaData, 
defaultDatabaseName);
-        SubquerySegment result = new SubquerySegment(segment.getStartIndex(), 
segment.getStopIndex(), boundedSelectStatement);
-        result.setSubqueryType(segment.getSubqueryType());
-        return result;
+    public static BinaryOperationExpression bind(final 
BinaryOperationExpression segment, final ShardingSphereMetaData metaData, final 
String defaultDatabaseName) {
+        ExpressionSegment boundedLeft = 
ExpressionSegmentBinder.bind(segment.getLeft(), metaData, defaultDatabaseName);
+        ExpressionSegment boundedRight = 
ExpressionSegmentBinder.bind(segment.getRight(), metaData, defaultDatabaseName);
+        return new BinaryOperationExpression(segment.getStartIndex(), 
segment.getStopIndex(), boundedLeft, boundedRight, segment.getOperator(), 
segment.getText());
     }
 }
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/ColumnSegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
similarity index 99%
rename from 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/ColumnSegmentBinder.java
rename to 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
index cc8a09ac2bd..bead7512381 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/ColumnSegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.binder.segment.expression;
+package org.apache.shardingsphere.infra.binder.segment.expression.impl;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ExistsSubqueryExpressionBinder.java
similarity index 61%
copy from 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
copy to 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ExistsSubqueryExpressionBinder.java
index 7fde0c58618..dac518c89dd 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ExistsSubqueryExpressionBinder.java
@@ -15,33 +15,32 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.binder.segment.expression;
+package org.apache.shardingsphere.infra.binder.segment.expression.impl;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import 
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementBinder;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
-import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 
 /**
- * Subquery segment binder.
+ * Exists subquery expression binder.
  */
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class SubquerySegmentBinder {
+public final class ExistsSubqueryExpressionBinder {
     
     /**
-     * Bind subquery segment with metadata.
+     * Bind exists subquery expression with metadata.
      *
-     * @param segment subquery segment
+     * @param segment exists subquery expression segment
      * @param metaData metaData
      * @param defaultDatabaseName default database name
-     * @return bounded subquery segment
+     * @return bounded exists subquery expression segment
      */
-    public static SubquerySegment bind(final SubquerySegment segment, final 
ShardingSphereMetaData metaData, final String defaultDatabaseName) {
-        SelectStatement boundedSelectStatement = new 
SelectStatementBinder().bind(segment.getSelect(), metaData, 
defaultDatabaseName);
-        SubquerySegment result = new SubquerySegment(segment.getStartIndex(), 
segment.getStopIndex(), boundedSelectStatement);
-        result.setSubqueryType(segment.getSubqueryType());
+    public static ExistsSubqueryExpression bind(final ExistsSubqueryExpression 
segment, final ShardingSphereMetaData metaData, final String 
defaultDatabaseName) {
+        SubquerySegment boundedSubquery = 
SubquerySegmentBinder.bind(segment.getSubquery(), metaData, 
defaultDatabaseName);
+        ExistsSubqueryExpression result = new 
ExistsSubqueryExpression(segment.getStartIndex(), segment.getStopIndex(), 
boundedSubquery);
+        result.setNot(segment.isNot());
         return result;
     }
 }
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/InExpressionBinder.java
similarity index 57%
copy from 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
copy to 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/InExpressionBinder.java
index 7fde0c58618..3f3f1ba13fe 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/InExpressionBinder.java
@@ -15,33 +15,32 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.binder.segment.expression;
+package org.apache.shardingsphere.infra.binder.segment.expression.impl;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import 
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementBinder;
+import 
org.apache.shardingsphere.infra.binder.segment.expression.ExpressionSegmentBinder;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
-import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
-import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
 
 /**
- * Subquery segment binder.
+ * In expression binder.
  */
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class SubquerySegmentBinder {
+public final class InExpressionBinder {
     
     /**
-     * Bind subquery segment with metadata.
+     * Bind in expression segment with metadata.
      *
-     * @param segment subquery segment
+     * @param segment in expression
      * @param metaData metaData
      * @param defaultDatabaseName default database name
-     * @return bounded subquery segment
+     * @return bounded in expression
      */
-    public static SubquerySegment bind(final SubquerySegment segment, final 
ShardingSphereMetaData metaData, final String defaultDatabaseName) {
-        SelectStatement boundedSelectStatement = new 
SelectStatementBinder().bind(segment.getSelect(), metaData, 
defaultDatabaseName);
-        SubquerySegment result = new SubquerySegment(segment.getStartIndex(), 
segment.getStopIndex(), boundedSelectStatement);
-        result.setSubqueryType(segment.getSubqueryType());
-        return result;
+    public static InExpression bind(final InExpression segment, final 
ShardingSphereMetaData metaData, final String defaultDatabaseName) {
+        ExpressionSegment boundedLeft = 
ExpressionSegmentBinder.bind(segment.getLeft(), metaData, defaultDatabaseName);
+        ExpressionSegment boundedRight = 
ExpressionSegmentBinder.bind(segment.getRight(), metaData, defaultDatabaseName);
+        return new InExpression(segment.getStartIndex(), 
segment.getStopIndex(), boundedLeft, boundedRight, segment.isNot());
     }
 }
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/SubqueryExpressionSegmentBinder.java
similarity index 59%
copy from 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
copy to 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/SubqueryExpressionSegmentBinder.java
index 7fde0c58618..ac16a62dbaa 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/SubqueryExpressionSegmentBinder.java
@@ -15,33 +15,30 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.binder.segment.expression;
+package org.apache.shardingsphere.infra.binder.segment.expression.impl;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import 
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementBinder;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
-import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 
 /**
- * Subquery segment binder.
+ * Subquery expression segment binder.
  */
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class SubquerySegmentBinder {
+public final class SubqueryExpressionSegmentBinder {
     
     /**
-     * Bind subquery segment with metadata.
+     * Bind subquery expression segment with metadata.
      *
-     * @param segment subquery segment
+     * @param segment subquery expression segment
      * @param metaData metaData
      * @param defaultDatabaseName default database name
-     * @return bounded subquery segment
+     * @return bounded subquery expression segment
      */
-    public static SubquerySegment bind(final SubquerySegment segment, final 
ShardingSphereMetaData metaData, final String defaultDatabaseName) {
-        SelectStatement boundedSelectStatement = new 
SelectStatementBinder().bind(segment.getSelect(), metaData, 
defaultDatabaseName);
-        SubquerySegment result = new SubquerySegment(segment.getStartIndex(), 
segment.getStopIndex(), boundedSelectStatement);
-        result.setSubqueryType(segment.getSubqueryType());
-        return result;
+    public static SubqueryExpressionSegment bind(final 
SubqueryExpressionSegment segment, final ShardingSphereMetaData metaData, final 
String defaultDatabaseName) {
+        SubquerySegment boundedSubquery = 
SubquerySegmentBinder.bind(segment.getSubquery(), metaData, 
defaultDatabaseName);
+        return new SubqueryExpressionSegment(boundedSubquery);
     }
 }
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/SubquerySegmentBinder.java
similarity index 99%
copy from 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
copy to 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/SubquerySegmentBinder.java
index 7fde0c58618..e3b8b42a7f4 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/SubquerySegmentBinder.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.binder.segment.expression;
+package org.apache.shardingsphere.infra.binder.segment.expression.impl;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/ProjectionsSegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/ProjectionsSegmentBinder.java
index 2efa2510ff8..1db1dcf1155 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/ProjectionsSegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/ProjectionsSegmentBinder.java
@@ -17,18 +17,22 @@
 
 package org.apache.shardingsphere.infra.binder.segment.projection;
 
-import java.util.Map;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import 
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
 import 
org.apache.shardingsphere.infra.binder.segment.projection.impl.ColumnProjectionSegmentBinder;
 import 
org.apache.shardingsphere.infra.binder.segment.projection.impl.ShorthandProjectionSegmentBinder;
+import 
org.apache.shardingsphere.infra.binder.segment.projection.impl.SubqueryProjectionSegmentBinder;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
 
+import java.util.Map;
+
 /**
  * Projections segment binder.
  */
@@ -39,24 +43,31 @@ public final class ProjectionsSegmentBinder {
      * Bind projections segment with metadata.
      *
      * @param segment table segment
+     * @param metaData meta data
+     * @param defaultDatabaseName default database name
      * @param boundedTableSegment bounded table segment
      * @param tableBinderContexts table binder contexts
      * @return bounded projections segment
      */
-    public static ProjectionsSegment bind(final ProjectionsSegment segment, 
final TableSegment boundedTableSegment, final Map<String, 
TableSegmentBinderContext> tableBinderContexts) {
+    public static ProjectionsSegment bind(final ProjectionsSegment segment, 
final ShardingSphereMetaData metaData, final String defaultDatabaseName, final 
TableSegment boundedTableSegment,
+                                          final Map<String, 
TableSegmentBinderContext> tableBinderContexts) {
         ProjectionsSegment result = new 
ProjectionsSegment(segment.getStartIndex(), segment.getStopIndex());
         result.setDistinctRow(segment.isDistinctRow());
-        segment.getProjections().forEach(each -> 
result.getProjections().add(bind(each, boundedTableSegment, 
tableBinderContexts)));
+        segment.getProjections().forEach(each -> 
result.getProjections().add(bind(each, metaData, defaultDatabaseName, 
boundedTableSegment, tableBinderContexts)));
         return result;
     }
     
-    private static ProjectionSegment bind(final ProjectionSegment 
projectionSegment, final TableSegment boundedTableSegment, final Map<String, 
TableSegmentBinderContext> tableBinderContexts) {
+    private static ProjectionSegment bind(final ProjectionSegment 
projectionSegment, final ShardingSphereMetaData metaData, final String 
defaultDatabaseName, final TableSegment boundedTableSegment,
+                                          final Map<String, 
TableSegmentBinderContext> tableBinderContexts) {
         if (projectionSegment instanceof ColumnProjectionSegment) {
             return 
ColumnProjectionSegmentBinder.bind((ColumnProjectionSegment) projectionSegment, 
tableBinderContexts);
         }
         if (projectionSegment instanceof ShorthandProjectionSegment) {
             return 
ShorthandProjectionSegmentBinder.bind((ShorthandProjectionSegment) 
projectionSegment, boundedTableSegment, tableBinderContexts);
         }
+        if (projectionSegment instanceof SubqueryProjectionSegment) {
+            return 
SubqueryProjectionSegmentBinder.bind((SubqueryProjectionSegment) 
projectionSegment, metaData, defaultDatabaseName);
+        }
         // TODO support more ProjectionSegment bind
         return projectionSegment;
     }
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
index 60b2796b98c..d131993c87b 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
@@ -19,7 +19,7 @@ package 
org.apache.shardingsphere.infra.binder.segment.projection.impl;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import 
org.apache.shardingsphere.infra.binder.segment.expression.ColumnSegmentBinder;
+import 
org.apache.shardingsphere.infra.binder.segment.expression.impl.ColumnSegmentBinder;
 import 
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/SubqueryProjectionSegmentBinder.java
similarity index 58%
copy from 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
copy to 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/SubqueryProjectionSegmentBinder.java
index 60b2796b98c..47a9431a574 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/SubqueryProjectionSegmentBinder.java
@@ -19,31 +19,29 @@ package 
org.apache.shardingsphere.infra.binder.segment.projection.impl;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import 
org.apache.shardingsphere.infra.binder.segment.expression.ColumnSegmentBinder;
-import 
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
-import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
-
-import java.util.Map;
+import 
org.apache.shardingsphere.infra.binder.segment.expression.impl.SubquerySegmentBinder;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
 
 /**
- * Column projection segment binder.
+ * Subquery projection segment binder.
  */
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class ColumnProjectionSegmentBinder {
+public final class SubqueryProjectionSegmentBinder {
     
     /**
-     * Bind column projection segment with metadata.
+     * Bind subquery projection segment with metadata.
      *
-     * @param segment table segment
-     * @param tableBinderContexts table binder contexts
-     * @return bounded column projection segment
+     * @param segment subquery projection segment
+     * @param metaData meta data
+     * @param defaultDatabaseName default database name
+     * @return bounded subquery projection segment
      */
-    public static ColumnProjectionSegment bind(final ColumnProjectionSegment 
segment, final Map<String, TableSegmentBinderContext> tableBinderContexts) {
-        ColumnSegment boundedColumn = 
ColumnSegmentBinder.bind(segment.getColumn(), tableBinderContexts);
-        ColumnProjectionSegment result = new 
ColumnProjectionSegment(boundedColumn);
+    public static SubqueryProjectionSegment bind(final 
SubqueryProjectionSegment segment, final ShardingSphereMetaData metaData, final 
String defaultDatabaseName) {
+        SubquerySegment boundedSubquerySegment = 
SubquerySegmentBinder.bind(segment.getSubquery(), metaData, 
defaultDatabaseName);
+        SubqueryProjectionSegment result = new 
SubqueryProjectionSegment(boundedSubquerySegment, segment.getText());
         segment.getAliasSegment().ifPresent(result::setAlias);
-        result.setVisible(segment.isVisible());
         return result;
     }
 }
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/where/WhereSegmentBinder.java
similarity index 53%
rename from 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
rename to 
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/where/WhereSegmentBinder.java
index 7fde0c58618..1fd7f2fdb48 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/SubquerySegmentBinder.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/where/WhereSegmentBinder.java
@@ -15,33 +15,29 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.binder.segment.expression;
+package org.apache.shardingsphere.infra.binder.segment.where;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import 
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementBinder;
+import 
org.apache.shardingsphere.infra.binder.segment.expression.ExpressionSegmentBinder;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
-import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
-import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
 
 /**
- * Subquery segment binder.
+ * Where segment binder.
  */
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class SubquerySegmentBinder {
+public final class WhereSegmentBinder {
     
     /**
-     * Bind subquery segment with metadata.
+     * Bind where segment with metadata.
      *
-     * @param segment subquery segment
-     * @param metaData metaData
+     * @param segment where segment
+     * @param metaData meta data
      * @param defaultDatabaseName default database name
-     * @return bounded subquery segment
+     * @return bounded where segment
      */
-    public static SubquerySegment bind(final SubquerySegment segment, final 
ShardingSphereMetaData metaData, final String defaultDatabaseName) {
-        SelectStatement boundedSelectStatement = new 
SelectStatementBinder().bind(segment.getSelect(), metaData, 
defaultDatabaseName);
-        SubquerySegment result = new SubquerySegment(segment.getStartIndex(), 
segment.getStopIndex(), boundedSelectStatement);
-        result.setSubqueryType(segment.getSubqueryType());
-        return result;
+    public static WhereSegment bind(final WhereSegment segment, final 
ShardingSphereMetaData metaData, final String defaultDatabaseName) {
+        return new WhereSegment(segment.getStartIndex(), 
segment.getStopIndex(), ExpressionSegmentBinder.bind(segment.getExpr(), 
metaData, defaultDatabaseName));
     }
 }
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 4e40205ac23..754ad565052 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
@@ -18,7 +18,7 @@
 package org.apache.shardingsphere.infra.binder.statement.dml;
 
 import lombok.SneakyThrows;
-import 
org.apache.shardingsphere.infra.binder.segment.expression.SubquerySegmentBinder;
+import 
org.apache.shardingsphere.infra.binder.segment.expression.impl.SubquerySegmentBinder;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinder;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
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 7380470fb55..1b506c11948 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
@@ -23,6 +23,7 @@ import 
org.apache.shardingsphere.infra.binder.segment.combine.CombineSegmentBind
 import org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinder;
 import 
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
 import 
org.apache.shardingsphere.infra.binder.segment.projection.ProjectionsSegmentBinder;
+import org.apache.shardingsphere.infra.binder.segment.where.WhereSegmentBinder;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinder;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
@@ -43,9 +44,9 @@ public final class SelectStatementBinder implements 
SQLStatementBinder<SelectSta
         Map<String, TableSegmentBinderContext> tableBinderContexts = new 
CaseInsensitiveMap<>();
         TableSegment boundedTableSegment = 
TableSegmentBinder.bind(sqlStatement.getFrom(), metaData, defaultDatabaseName, 
sqlStatement.getDatabaseType(), tableBinderContexts);
         result.setFrom(boundedTableSegment);
-        
result.setProjections(ProjectionsSegmentBinder.bind(sqlStatement.getProjections(),
 boundedTableSegment, tableBinderContexts));
+        
result.setProjections(ProjectionsSegmentBinder.bind(sqlStatement.getProjections(),
 metaData, defaultDatabaseName, boundedTableSegment, tableBinderContexts));
         // TODO support other segment bind in select statement
-        sqlStatement.getWhere().ifPresent(result::setWhere);
+        sqlStatement.getWhere().ifPresent(optional -> 
result.setWhere(WhereSegmentBinder.bind(optional, metaData, 
defaultDatabaseName)));
         sqlStatement.getGroupBy().ifPresent(result::setGroupBy);
         sqlStatement.getHaving().ifPresent(result::setHaving);
         sqlStatement.getOrderBy().ifPresent(result::setOrderBy);
diff --git 
a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/table/TablesContextTest.java
 
b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/table/TablesContextTest.java
index 0057549a06c..7669110ca53 100644
--- 
a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/table/TablesContextTest.java
+++ 
b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/table/TablesContextTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.shardingsphere.infra.binder.context.segment.table;
 
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ColumnProjection;
 import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
@@ -125,64 +124,6 @@ class TablesContextTest {
         assertThat(actual.get("col"), is("TABLE_1"));
     }
     
-    @Test
-    void assertFindTableNameWhenColumnProjectionWhenSingleTable() {
-        SimpleTableSegment tableSegment = createTableSegment("table_1", 
"tbl_1");
-        ColumnProjection columnProjection = new ColumnProjection(null, "col", 
"cl", mock(DatabaseType.class));
-        Map<String, String> actual = new 
TablesContext(Collections.singletonList(tableSegment), 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE"))
-                
.findTableNamesByColumnProjection(Collections.singletonList(columnProjection), 
mock(ShardingSphereSchema.class));
-        assertFalse(actual.isEmpty());
-        assertThat(actual.get("col"), is("table_1"));
-    }
-    
-    @Test
-    void assertFindTableNameWhenColumnProjectionOwnerPresent() {
-        SimpleTableSegment tableSegment1 = createTableSegment("table_1", 
"tbl_1");
-        SimpleTableSegment tableSegment2 = createTableSegment("table_2", 
"tbl_2");
-        ColumnProjection columnProjection = new ColumnProjection("table_1", 
"col", "cl", mock(DatabaseType.class));
-        Map<String, String> actual = new 
TablesContext(Arrays.asList(tableSegment1, tableSegment2), 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE"))
-                
.findTableNamesByColumnProjection(Collections.singletonList(columnProjection), 
mock(ShardingSphereSchema.class));
-        assertFalse(actual.isEmpty());
-        assertThat(actual.get("table_1.col"), is("table_1"));
-    }
-    
-    @Test
-    void assertFindTableNameWhenColumnProjectionOwnerAbsent() {
-        SimpleTableSegment tableSegment1 = createTableSegment("table_1", 
"tbl_1");
-        SimpleTableSegment tableSegment2 = createTableSegment("table_2", 
"tbl_2");
-        ColumnProjection columnProjection = new ColumnProjection(null, "col", 
"cl", mock(DatabaseType.class));
-        Map<String, String> actual = new 
TablesContext(Arrays.asList(tableSegment1, tableSegment2), 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE"))
-                
.findTableNamesByColumnProjection(Collections.singletonList(columnProjection), 
mock(ShardingSphereSchema.class));
-        assertTrue(actual.isEmpty());
-    }
-    
-    @Test
-    void 
assertFindTableNameWhenColumnProjectionOwnerAbsentAndSchemaMetaDataContainsColumn()
 {
-        SimpleTableSegment tableSegment1 = createTableSegment("table_1", 
"tbl_1");
-        SimpleTableSegment tableSegment2 = createTableSegment("table_2", 
"tbl_2");
-        ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
-        
when(schema.getAllColumnNames("table_1")).thenReturn(Collections.singletonList("col"));
-        ColumnProjection columnProjection = new ColumnProjection(null, "col", 
"cl", mock(DatabaseType.class));
-        Map<String, String> actual = new 
TablesContext(Arrays.asList(tableSegment1, tableSegment2), 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE"))
-                
.findTableNamesByColumnProjection(Collections.singletonList(columnProjection), 
schema);
-        assertFalse(actual.isEmpty());
-        assertThat(actual.get("col"), is("table_1"));
-    }
-    
-    @Test
-    void 
assertFindTableNameWhenColumnProjectionOwnerAbsentAndSchemaMetaDataContainsColumnInUpperCase()
 {
-        SimpleTableSegment tableSegment1 = createTableSegment("TABLE_1", 
"TBL_1");
-        SimpleTableSegment tableSegment2 = createTableSegment("TABLE_2", 
"TBL_2");
-        ShardingSphereTable table = new ShardingSphereTable("TABLE_1", 
Collections.singletonList(
-                new ShardingSphereColumn("COL", 0, false, false, true, true, 
false, false)), Collections.emptyList(), Collections.emptyList());
-        ShardingSphereSchema schema = new 
ShardingSphereSchema(Stream.of(table).collect(Collectors.toMap(ShardingSphereTable::getName,
 value -> value)), Collections.emptyMap());
-        ColumnProjection columnProjection = new ColumnProjection(null, "COL", 
"CL", mock(DatabaseType.class));
-        Map<String, String> actual = new 
TablesContext(Arrays.asList(tableSegment1, tableSegment2), 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE"))
-                
.findTableNamesByColumnProjection(Collections.singletonList(columnProjection), 
schema);
-        assertFalse(actual.isEmpty());
-        assertThat(actual.get("col"), is("TABLE_1"));
-    }
-    
     private SimpleTableSegment createTableSegment(final String tableName, 
final String alias) {
         SimpleTableSegment result = new SimpleTableSegment(new 
TableNameSegment(0, 0, new IdentifierValue(tableName)));
         AliasSegment aliasSegment = new AliasSegment(0, 0, new 
IdentifierValue(alias));
diff --git 
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/SQLFederationResultSetMetaData.java
 
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/SQLFederationResultSetMetaData.java
index cdee84ceffa..9e122e7236f 100644
--- 
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/SQLFederationResultSetMetaData.java
+++ 
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/SQLFederationResultSetMetaData.java
@@ -29,7 +29,6 @@ import 
org.apache.shardingsphere.infra.database.core.DefaultDatabase;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 
 import java.sql.ResultSetMetaData;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -182,9 +181,7 @@ public final class SQLFederationResultSetMetaData extends 
WrapperAdapter impleme
                 expandProjections.size() < column ? new ColumnProjection(null, 
resultColumnType.getFieldList().get(column - 1).getName(), null, 
selectStatementContext.getDatabaseType())
                         : expandProjections.get(column - 1);
         if (projection instanceof ColumnProjection) {
-            Map<String, String> tableNamesByColumnProjection =
-                    
selectStatementContext.getTablesContext().findTableNamesByColumnProjection(Collections.singletonList((ColumnProjection)
 projection), schema);
-            return 
Optional.of(tableNamesByColumnProjection.get(projection.getExpression()));
+            return Optional.of(((ColumnProjection) 
projection).getOriginalTable().getValue());
         }
         return Optional.empty();
     }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/SubqueryProjectionSegment.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/SubqueryProjectionSegment.java
index e180b0c6eed..10d23113f02 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/SubqueryProjectionSegment.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/item/SubqueryProjectionSegment.java
@@ -56,6 +56,15 @@ public final class SubqueryProjectionSegment implements 
ProjectionSegment, Alias
         return Optional.ofNullable(alias).map(AliasSegment::getIdentifier);
     }
     
+    /**
+     * Get alias segment.
+     * 
+     * @return alias segment
+     */
+    public Optional<AliasSegment> getAliasSegment() {
+        return Optional.ofNullable(alias);
+    }
+    
     @Override
     public int getStartIndex() {
         return subquery.getStartIndex();
diff --git 
a/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLComStmtPrepareExecutor.java
 
b/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLComStmtPrepareExecutor.java
index 23e9a91eaf4..4184e3ad204 100644
--- 
a/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLComStmtPrepareExecutor.java
+++ 
b/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLComStmtPrepareExecutor.java
@@ -28,7 +28,6 @@ import 
org.apache.shardingsphere.db.protocol.mysql.packet.command.query.binary.p
 import 
org.apache.shardingsphere.db.protocol.mysql.packet.command.query.binary.prepare.MySQLComStmtPreparePacket;
 import 
org.apache.shardingsphere.db.protocol.mysql.packet.generic.MySQLEofPacket;
 import org.apache.shardingsphere.db.protocol.packet.DatabasePacket;
-import 
org.apache.shardingsphere.infra.exception.mysql.exception.UnsupportedPreparedStatementException;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ColumnProjection;
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
@@ -36,6 +35,7 @@ import 
org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatem
 import org.apache.shardingsphere.infra.binder.engine.SQLBindEngine;
 import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
 import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
+import 
org.apache.shardingsphere.infra.exception.mysql.exception.UnsupportedPreparedStatementException;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
@@ -60,7 +60,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.stream.Collectors;
 
 /**
  * COM_STMT_PREPARE command executor for MySQL.
@@ -143,13 +142,11 @@ public final class MySQLComStmtPrepareExecutor implements 
CommandExecutor {
     private Collection<MySQLPacket> 
createProjectionColumnDefinition41Packets(final SelectStatementContext 
selectStatementContext, final int characterSet) {
         Collection<Projection> projections = 
selectStatementContext.getProjectionsContext().getExpandProjections();
         ShardingSphereSchema schema = getSchema(selectStatementContext);
-        Map<String, String> columnToTableMap = 
selectStatementContext.getTablesContext()
-                
.findTableNamesByColumnProjection(projections.stream().filter(ColumnProjection.class::isInstance).map(ColumnProjection.class::cast).collect(Collectors.toList()),
 schema);
         Collection<MySQLPacket> result = new ArrayList<>(projections.size());
         for (Projection each : projections) {
             // TODO Calculate column definition flag for other projection types
-            if (each instanceof ColumnProjection && null != 
((ColumnProjection) each).getOriginalColumn()) {
-                
result.add(Optional.ofNullable(columnToTableMap.get(each.getExpression())).map(schema::getTable)
+            if (each instanceof ColumnProjection) {
+                
result.add(Optional.ofNullable(schema.getTable(((ColumnProjection) 
each).getOriginalTable().getValue()))
                         .map(table -> 
table.getColumns().get(((ColumnProjection) 
each).getOriginalColumn().getValue()))
                         .map(column -> 
createMySQLColumnDefinition41Packet(characterSet, 
calculateColumnDefinitionFlag(column), 
MySQLBinaryColumnType.valueOfJDBCType(column.getDataType())))
                         .orElseGet(() -> 
createMySQLColumnDefinition41Packet(characterSet, 0, 
MySQLBinaryColumnType.VAR_STRING)));

Reply via email to