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

zhaojinchao 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 30054d77e95 distinguish table subquery and join subquery to fix 
rewriting wrong result when join segment contains subquery table (#28040)
30054d77e95 is described below

commit 30054d77e95bd10a5d5b418cce0fd03386ce3408
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Fri Aug 11 15:22:42 2023 +0800

    distinguish table subquery and join subquery to fix rewriting wrong result 
when join segment contains subquery table (#28040)
    
    * distinguish table subquery and join subquery to fix rewriting wrong 
result when join segment contains subquery table
    
    * revert it-env.properties
---
 .../generator/EncryptProjectionTokenGenerator.java | 88 ++++++++++------------
 .../EncryptProjectionTokenGeneratorTest.java       |  5 +-
 .../statement/dml/SelectStatementContext.java      |  9 +++
 .../statement/dml/SelectStatementContextTest.java  | 21 ++++++
 .../sql/parser/sql/common/enums/SubqueryType.java  |  2 +-
 .../sql/common/util/SubqueryExtractUtils.java      | 27 +++++--
 .../dml/select/select-subquery.xml                 | 10 +--
 .../dml/select/select-subquery.xml                 |  8 +-
 8 files changed, 100 insertions(+), 70 deletions(-)

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 09359858d5b..1891e99fb3e 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
@@ -33,6 +33,7 @@ import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
 import 
org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
 import 
org.apache.shardingsphere.infra.database.core.metadata.database.DialectDatabaseMetaData;
+import 
org.apache.shardingsphere.infra.database.core.metadata.database.enums.QuoteCharacter;
 import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
 import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
 import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
@@ -46,9 +47,6 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnPr
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
 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;
@@ -94,11 +92,11 @@ public final class EncryptProjectionTokenGenerator 
implements CollectionSQLToken
                 ColumnProjection columnProjection = 
buildColumnProjection(columnSegment);
                 String originalColumnName = 
columnProjection.getOriginalColumn().getValue();
                 Optional<EncryptTable> encryptTable = 
encryptRule.findEncryptTable(columnProjection.getOriginalTable().getValue());
-                if (encryptTable.isPresent() && 
encryptTable.get().isEncryptColumn(originalColumnName) && 
!containsTableSubquery(selectStatementContext.getSqlStatement().getFrom())) {
+                if (encryptTable.isPresent() && 
encryptTable.get().isEncryptColumn(originalColumnName) && 
!selectStatementContext.containsTableSubquery()) {
                     
sqlTokens.add(generateSQLToken(encryptTable.get().getEncryptColumn(originalColumnName),
 columnSegment, columnProjection, subqueryType));
                 }
             }
-            ShardingSpherePreconditions.checkState(!(each instanceof 
ShorthandProjectionSegment) || 
!containsTableSubquery(selectStatementContext.getSqlStatement().getFrom()),
+            ShardingSpherePreconditions.checkState(!(each instanceof 
ShorthandProjectionSegment) || !selectStatementContext.containsTableSubquery(),
                     () -> new UnsupportedSQLOperationException("Can not 
support encrypt shorthand expand with subquery statement"));
             if (each instanceof ShorthandProjectionSegment) {
                 ShorthandProjectionSegment shorthandSegment = 
(ShorthandProjectionSegment) each;
@@ -110,16 +108,6 @@ public final class EncryptProjectionTokenGenerator 
implements CollectionSQLToken
         }
     }
     
-    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);
@@ -133,11 +121,11 @@ public final class EncryptProjectionTokenGenerator 
implements CollectionSQLToken
         List<Projection> projections = new LinkedList<>();
         for (Projection each : actualColumns) {
             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));
+                ColumnProjection columnProjection = (ColumnProjection) each;
+                Optional<EncryptTable> encryptTable = 
encryptRule.findEncryptTable(columnProjection.getOriginalTable().getValue());
+                if (encryptTable.isPresent() && 
encryptTable.get().isEncryptColumn(columnProjection.getOriginalColumn().getValue())
 && !selectStatementContext.containsTableSubquery()) {
+                    EncryptColumn encryptColumn = 
encryptTable.get().getEncryptColumn(columnProjection.getOriginalColumn().getValue());
+                    projections.addAll(generateProjections(encryptColumn, 
columnProjection, subqueryType, true, segment));
                     continue;
                 }
             }
@@ -158,57 +146,59 @@ public final class EncryptProjectionTokenGenerator 
implements CollectionSQLToken
         return result;
     }
     
-    private Collection<Projection> generateProjections(final EncryptColumn 
encryptColumn, final ColumnProjection column,
-                                                       final SubqueryType 
subqueryType, final boolean shorthand, final ShorthandProjectionSegment 
segment) {
+    private Collection<Projection> generateProjections(final EncryptColumn 
encryptColumn, final ColumnProjection columnProjection,
+                                                       final SubqueryType 
subqueryType, final boolean shorthandProjection, final 
ShorthandProjectionSegment segment) {
         Collection<Projection> result = new LinkedList<>();
         if (SubqueryType.PREDICATE_SUBQUERY == subqueryType) {
-            result.add(generatePredicateSubqueryProjection(encryptColumn, 
column, shorthand));
-        } else if (SubqueryType.TABLE_SUBQUERY == subqueryType) {
-            result.addAll(generateTableSubqueryProjections(encryptColumn, 
column, shorthand));
+            result.add(generatePredicateSubqueryProjection(encryptColumn, 
columnProjection, shorthandProjection));
+        } else if (SubqueryType.TABLE_SUBQUERY == subqueryType || 
SubqueryType.JOIN_SUBQUERY == subqueryType) {
+            
result.addAll(generateTableSegmentSubqueryProjections(encryptColumn, 
columnProjection, shorthandProjection, subqueryType));
         } else if (SubqueryType.EXISTS_SUBQUERY == subqueryType) {
-            result.addAll(generateExistsSubqueryProjections(encryptColumn, 
column, shorthand));
+            result.addAll(generateExistsSubqueryProjections(encryptColumn, 
columnProjection, shorthandProjection));
         } else {
-            result.add(generateCommonProjection(encryptColumn, column, 
segment, shorthand));
+            result.add(generateCommonProjection(encryptColumn, 
columnProjection, segment, shorthandProjection));
         }
         return result;
     }
     
-    private ColumnProjection generatePredicateSubqueryProjection(final 
EncryptColumn encryptColumn, final ColumnProjection column, final boolean 
shorthand) {
+    private ColumnProjection generatePredicateSubqueryProjection(final 
EncryptColumn encryptColumn, final ColumnProjection columnProjection, final 
boolean shorthandProjection) {
         Optional<AssistedQueryColumnItem> assistedQueryColumn = 
encryptColumn.getAssistedQuery();
+        IdentifierValue owner = columnProjection.getOwner().orElse(null);
         return assistedQueryColumn
-                .map(optional -> new 
ColumnProjection(column.getOwner().orElse(null), new 
IdentifierValue(optional.getName(), column.getName().getQuoteCharacter()), 
null, databaseType))
-                .orElseGet(() -> 
createCipherColumn(column.getOwner().orElse(null), 
encryptColumn.getCipher().getName(), column, shorthand));
+                .map(optional -> new ColumnProjection(owner, new 
IdentifierValue(optional.getName(), 
columnProjection.getName().getQuoteCharacter()), null, databaseType))
+                .orElseGet(() -> createCipherColumn(owner, new 
IdentifierValue(encryptColumn.getCipher().getName(), 
columnProjection.getName().getQuoteCharacter()),
+                        
columnProjection.getAlias().orElse(columnProjection.getName()), 
shorthandProjection));
     }
     
-    private Collection<ColumnProjection> 
generateTableSubqueryProjections(final EncryptColumn encryptColumn, final 
ColumnProjection cipherColumn, final boolean shorthand) {
+    private Collection<ColumnProjection> 
generateTableSegmentSubqueryProjections(final EncryptColumn encryptColumn, 
final ColumnProjection columnProjection, final boolean shorthandProjection,
+                                                                               
  final SubqueryType subqueryType) {
         Collection<ColumnProjection> result = new LinkedList<>();
-        IdentifierValue owner = cipherColumn.getOwner().orElse(null);
-        result.add(createCipherColumn(owner, 
encryptColumn.getCipher().getName(), cipherColumn, shorthand));
-        encryptColumn.getAssistedQuery()
-                .ifPresent(optional -> result.add(new ColumnProjection(owner, 
new IdentifierValue(optional.getName(), 
cipherColumn.getName().getQuoteCharacter()), null, databaseType)));
-        encryptColumn.getLikeQuery()
-                .ifPresent(optional -> result.add(new ColumnProjection(owner, 
new IdentifierValue(optional.getName(), 
cipherColumn.getName().getQuoteCharacter()), null, databaseType)));
+        IdentifierValue owner = columnProjection.getOwner().orElse(null);
+        QuoteCharacter quoteCharacter = 
columnProjection.getName().getQuoteCharacter();
+        IdentifierValue columnName = new 
IdentifierValue(encryptColumn.getCipher().getName(), quoteCharacter);
+        IdentifierValue alias = SubqueryType.JOIN_SUBQUERY == subqueryType ? 
null : columnProjection.getAlias().orElse(columnProjection.getName());
+        result.add(createCipherColumn(owner, columnName, alias, 
shorthandProjection));
+        encryptColumn.getAssistedQuery().ifPresent(optional -> result.add(new 
ColumnProjection(owner, new IdentifierValue(optional.getName(), 
quoteCharacter), null, databaseType)));
+        encryptColumn.getLikeQuery().ifPresent(optional -> result.add(new 
ColumnProjection(owner, new IdentifierValue(optional.getName(), 
quoteCharacter), null, databaseType)));
         return result;
     }
     
-    private ColumnProjection createCipherColumn(final IdentifierValue owner, 
final String cipherColumn, final ColumnProjection columnProjection, final 
boolean shorthand) {
-        if (shorthand || !columnProjection.getOwner().isPresent()) {
-            return new ColumnProjection(owner, new 
IdentifierValue(cipherColumn, columnProjection.getName().getQuoteCharacter()), 
columnProjection.getAlias().orElse(columnProjection.getName()),
-                    databaseType);
-        }
-        return new ColumnProjection(null, new IdentifierValue(cipherColumn, 
columnProjection.getName().getQuoteCharacter()), 
columnProjection.getAlias().orElse(columnProjection.getName()),
-                databaseType);
+    private ColumnProjection createCipherColumn(final IdentifierValue owner, 
final IdentifierValue columnName, final IdentifierValue alias, final boolean 
shorthandProjection) {
+        return new ColumnProjection(shorthandProjection ? owner : null, 
columnName, alias, databaseType);
     }
     
-    private Collection<ColumnProjection> 
generateExistsSubqueryProjections(final EncryptColumn encryptColumn, final 
ColumnProjection column, final boolean shorthand) {
+    private Collection<ColumnProjection> 
generateExistsSubqueryProjections(final EncryptColumn encryptColumn, final 
ColumnProjection columnProjection, final boolean shorthandProjection) {
         Collection<ColumnProjection> result = new LinkedList<>();
-        result.add(createCipherColumn(column.getOwner().orElse(null), 
encryptColumn.getCipher().getName(), column, shorthand));
+        IdentifierValue columnName = new 
IdentifierValue(encryptColumn.getCipher().getName(), 
columnProjection.getName().getQuoteCharacter());
+        
result.add(createCipherColumn(columnProjection.getOwner().orElse(null), 
columnName, columnProjection.getAlias().orElse(columnProjection.getName()), 
shorthandProjection));
         return result;
     }
     
-    private ColumnProjection generateCommonProjection(final EncryptColumn 
encryptColumn, final ColumnProjection column, final ShorthandProjectionSegment 
segment, final boolean shorthand) {
-        IdentifierValue owner = (null == segment || 
!segment.getOwner().isPresent()) ? column.getOwner().orElse(null) : 
segment.getOwner().get().getIdentifier();
-        return createCipherColumn(owner, encryptColumn.getCipher().getName(), 
column, shorthand);
+    private ColumnProjection generateCommonProjection(final EncryptColumn 
encryptColumn, final ColumnProjection columnProjection, final 
ShorthandProjectionSegment segment,
+                                                      final boolean 
shorthandProjection) {
+        IdentifierValue owner = (null == segment || 
!segment.getOwner().isPresent()) ? columnProjection.getOwner().orElse(null) : 
segment.getOwner().get().getIdentifier();
+        IdentifierValue columnName = new 
IdentifierValue(encryptColumn.getCipher().getName(), 
columnProjection.getName().getQuoteCharacter());
+        return createCipherColumn(owner, columnName, 
columnProjection.getAlias().orElse(columnProjection.getName()), 
shorthandProjection);
     }
     
     private ShorthandProjection getShorthandProjection(final 
ShorthandProjectionSegment segment, final ProjectionsContext 
projectionsContext) {
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 d30545ceab7..22d927bf71d 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
@@ -28,16 +28,13 @@ import 
org.apache.shardingsphere.infra.exception.core.external.sql.type.generic.
 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;
-import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 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.generic.AliasSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -143,7 +140,7 @@ class EncryptProjectionTokenGeneratorTest {
     @Test
     void assertGenerateSQLTokensWhenShorthandExpandContainsSubqueryTable() {
         SelectStatementContext sqlStatementContext = 
mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
-        when(sqlStatementContext.getSqlStatement().getFrom()).thenReturn(new 
SubqueryTableSegment(new SubquerySegment(0, 0, mock(SelectStatement.class))));
+        when(sqlStatementContext.containsTableSubquery()).thenReturn(true);
         
when(sqlStatementContext.getSqlStatement().getProjections().getProjections()).thenReturn(Collections.singleton(new
 ShorthandProjectionSegment(0, 0)));
         assertThrows(UnsupportedSQLOperationException.class, () -> 
generator.generateSQLTokens(sqlStatementContext));
     }
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/dml/SelectStatementContext.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/dml/SelectStatementContext.java
index f634f5e4c47..96c19fbc7be 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/dml/SelectStatementContext.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/dml/SelectStatementContext.java
@@ -374,6 +374,15 @@ public final class SelectStatementContext extends 
CommonSQLStatementContext impl
         return result;
     }
     
+    /**
+     * Judge whether sql statement contains table subquery segment or not.
+     *
+     * @return whether sql statement contains table subquery segment or not
+     */
+    public boolean containsTableSubquery() {
+        return getSqlStatement().getFrom() instanceof SubqueryTableSegment;
+    }
+    
     @Override
     public void setUpParameters(final List<Object> params) {
         paginationContext = new 
PaginationContextEngine().createPaginationContext(getSqlStatement(), 
projectionsContext, params, whereSegments);
diff --git 
a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/statement/dml/SelectStatementContextTest.java
 
b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/statement/dml/SelectStatementContextTest.java
index ae2e8cb3ff1..051f9c819f2 100644
--- 
a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/statement/dml/SelectStatementContextTest.java
+++ 
b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/statement/dml/SelectStatementContextTest.java
@@ -51,6 +51,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegm
 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.SimpleTableSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
@@ -626,4 +627,24 @@ class SelectStatementContextTest {
         SelectStatementContext actual = new SelectStatementContext(metaData, 
Collections.emptyList(), selectStatement, DefaultDatabase.LOGIC_NAME);
         assertTrue(actual.isContainsEnhancedTable());
     }
+    
+    @Test
+    void assertContainsEnhancedTable() {
+        SelectStatement selectStatement = new MySQLSelectStatement();
+        selectStatement.setProjections(new ProjectionsSegment(0, 0));
+        selectStatement.setFrom(new SubqueryTableSegment(new 
SubquerySegment(0, 0, createSubSelectStatement())));
+        ShardingSphereMetaData metaData = new 
ShardingSphereMetaData(Collections.singletonMap(DefaultDatabase.LOGIC_NAME, 
mockDatabase()), mock(ResourceMetaData.class),
+                mock(RuleMetaData.class), mock(ConfigurationProperties.class));
+        SelectStatementContext actual = new SelectStatementContext(metaData, 
Collections.emptyList(), selectStatement, DefaultDatabase.LOGIC_NAME);
+        assertTrue(actual.containsTableSubquery());
+    }
+    
+    private SelectStatement createSubSelectStatement() {
+        ProjectionsSegment projectionsSegment = new ProjectionsSegment(0, 0);
+        projectionsSegment.getProjections().add(new 
ColumnProjectionSegment(new ColumnSegment(0, 0, new 
IdentifierValue("order_id"))));
+        SelectStatement result = new MySQLSelectStatement();
+        result.setProjections(projectionsSegment);
+        result.setFrom(new SimpleTableSegment(new TableNameSegment(0, 0, new 
IdentifierValue("t_order"))));
+        return result;
+    }
 }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/SubqueryType.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/SubqueryType.java
index 00a07321f49..383c9ede9d4 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/SubqueryType.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/enums/SubqueryType.java
@@ -22,5 +22,5 @@ package org.apache.shardingsphere.sql.parser.sql.common.enums;
  */
 public enum SubqueryType {
     
-    PROJECTION_SUBQUERY, TABLE_SUBQUERY, PREDICATE_SUBQUERY, 
INSERT_SELECT_SUBQUERY, EXISTS_SUBQUERY
+    PROJECTION_SUBQUERY, TABLE_SUBQUERY, JOIN_SUBQUERY, PREDICATE_SUBQUERY, 
INSERT_SELECT_SUBQUERY, EXISTS_SUBQUERY
 }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SubqueryExtractUtils.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SubqueryExtractUtils.java
index 522e5c55676..22e360b253f 100644
--- 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SubqueryExtractUtils.java
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SubqueryExtractUtils.java
@@ -88,19 +88,32 @@ public final class SubqueryExtractUtils {
     }
     
     private static void extractSubquerySegmentsFromTableSegment(final 
List<SubquerySegment> result, final TableSegment tableSegment) {
-        if (null == tableSegment) {
-            return;
+        if (tableSegment instanceof SubqueryTableSegment) {
+            extractSubquerySegmentsFromSubqueryTableSegment(result, 
(SubqueryTableSegment) tableSegment);
         }
+        if (tableSegment instanceof JoinTableSegment) {
+            extractSubquerySegmentsFromJoinTableSegment(result, 
((JoinTableSegment) tableSegment).getLeft());
+            extractSubquerySegmentsFromJoinTableSegment(result, 
((JoinTableSegment) tableSegment).getRight());
+        }
+    }
+    
+    private static void extractSubquerySegmentsFromJoinTableSegment(final 
List<SubquerySegment> result, final TableSegment tableSegment) {
         if (tableSegment instanceof SubqueryTableSegment) {
             SubquerySegment subquery = ((SubqueryTableSegment) 
tableSegment).getSubquery();
-            subquery.setSubqueryType(SubqueryType.TABLE_SUBQUERY);
+            subquery.setSubqueryType(SubqueryType.JOIN_SUBQUERY);
             result.add(subquery);
             extractSubquerySegments(result, subquery.getSelect());
+        } else if (tableSegment instanceof JoinTableSegment) {
+            extractSubquerySegmentsFromJoinTableSegment(result, 
((JoinTableSegment) tableSegment).getLeft());
+            extractSubquerySegmentsFromJoinTableSegment(result, 
((JoinTableSegment) tableSegment).getRight());
         }
-        if (tableSegment instanceof JoinTableSegment) {
-            extractSubquerySegmentsFromTableSegment(result, 
((JoinTableSegment) tableSegment).getLeft());
-            extractSubquerySegmentsFromTableSegment(result, 
((JoinTableSegment) tableSegment).getRight());
-        }
+    }
+    
+    private static void extractSubquerySegmentsFromSubqueryTableSegment(final 
List<SubquerySegment> result, final SubqueryTableSegment subqueryTableSegment) {
+        SubquerySegment subquery = subqueryTableSegment.getSubquery();
+        subquery.setSubqueryType(SubqueryType.TABLE_SUBQUERY);
+        result.add(subquery);
+        extractSubquerySegments(result, subquery.getSelect());
     }
     
     private static void extractSubquerySegmentsFromExpression(final 
List<SubquerySegment> result, final ExpressionSegment expressionSegment) {
diff --git 
a/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/select/select-subquery.xml
 
b/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/select/select-subquery.xml
index b5ffed1df65..69216088fc1 100644
--- 
a/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/select/select-subquery.xml
+++ 
b/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/select/select-subquery.xml
@@ -24,12 +24,12 @@
 
     <rewrite-assertion id="select_not_nested_subquery_in_table_segment" 
db-types="MySQL">
         <input sql="SELECT u.amount, u.password, o.certificate_number FROM 
(SELECT certificate_number FROM t_account) o, t_account u WHERE 
o.certificate_number=u.certificate_number AND u.password=?" parameters="1" />
-        <output sql="SELECT u.amount, u.password, o.certificate_number FROM 
(SELECT cipher_certificate_number AS certificate_number, 
assisted_query_certificate_number, like_query_certificate_number FROM 
t_account) o, t_account u WHERE 
o.assisted_query_certificate_number=u.assisted_query_certificate_number AND 
u.assisted_query_password=?" parameters="assisted_query_1" />
+        <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS 
password, o.cipher_certificate_number AS certificate_number FROM (SELECT 
cipher_certificate_number, assisted_query_certificate_number, 
like_query_certificate_number FROM t_account) o, t_account u WHERE 
o.assisted_query_certificate_number=u.assisted_query_certificate_number AND 
u.assisted_query_password=?" parameters="assisted_query_1" />
     </rewrite-assertion>
 
     <rewrite-assertion id="select_not_nested_subquery_in_table_segment_refed" 
db-types="MySQL">
         <input sql="SELECT u.amount, u.password, o.certificate_number FROM 
(SELECT certificate_number FROM t_account_bak) o, t_account u WHERE 
o.certificate_number=u.certificate_number AND u.password=?" parameters="1" />
-        <output sql="SELECT u.amount, u.password, o.certificate_number FROM 
(SELECT cipher_certificate_number AS certificate_number, 
assisted_query_certificate_number, like_query_certificate_number FROM 
t_account_bak) o, t_account u WHERE 
o.assisted_query_certificate_number=u.assisted_query_certificate_number AND 
u.assisted_query_password=?" parameters="assisted_query_1" />
+        <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS 
password, o.cipher_certificate_number AS certificate_number FROM (SELECT 
cipher_certificate_number, assisted_query_certificate_number, 
like_query_certificate_number FROM t_account_bak) o, t_account u WHERE 
o.assisted_query_certificate_number=u.assisted_query_certificate_number AND 
u.assisted_query_password=?" parameters="assisted_query_1" />
     </rewrite-assertion>
 
     <rewrite-assertion id="select_not_nested_subquery_in_table_segment_alias" 
db-types="MySQL">
@@ -39,17 +39,17 @@
 
     <rewrite-assertion 
id="select_not_nested_subquery_in_table_segment_with_shorthand_project_alias" 
db-types="MySQL">
         <input sql="SELECT u.amount, u.password, o.certificate_number FROM 
(SELECT a.* FROM t_account a) o, t_account u WHERE 
o.certificate_number=u.certificate_number AND u.password=?" parameters="1" />
-        <output sql="SELECT u.amount, u.password, o.certificate_number FROM 
(SELECT a.`account_id`, a.`cipher_certificate_number` AS `certificate_number`, 
a.`assisted_query_certificate_number`, a.`like_query_certificate_number`, 
a.`cipher_password` AS `password`, a.`assisted_query_password`, 
a.`like_query_password`, a.`cipher_amount` AS `amount` FROM t_account a) o, 
t_account u WHERE 
o.assisted_query_certificate_number=u.assisted_query_certificate_number AND 
u.assisted_query_password=?"  [...]
+        <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS 
password, o.cipher_certificate_number AS certificate_number FROM (SELECT 
a.`account_id`, a.`cipher_certificate_number`, 
a.`assisted_query_certificate_number`, a.`like_query_certificate_number`, 
a.`cipher_password`, a.`assisted_query_password`, a.`like_query_password`, 
a.`cipher_amount` FROM t_account a) o, t_account u WHERE 
o.assisted_query_certificate_number=u.assisted_query_certificate_number AND 
u.assisted_que [...]
     </rewrite-assertion>
 
     <rewrite-assertion 
id="select_not_nested_subquery_in_table_segment_with_shorthand_project_alias_quote"
 db-types="MySQL">
         <input sql="SELECT u.amount, u.password, o.certificate_number FROM 
(SELECT a.* FROM t_account `a`) o, t_account u WHERE 
o.certificate_number=u.certificate_number AND u.password=?" parameters="1" />
-        <output sql="SELECT u.amount, u.password, o.certificate_number FROM 
(SELECT `a`.`account_id`, `a`.`cipher_certificate_number` AS 
`certificate_number`, `a`.`assisted_query_certificate_number`, 
`a`.`like_query_certificate_number`, `a`.`cipher_password` AS `password`, 
`a`.`assisted_query_password`, `a`.`like_query_password`, `a`.`cipher_amount` 
AS `amount` FROM t_account `a`) o, t_account u WHERE 
o.assisted_query_certificate_number=u.assisted_query_certificate_number AND 
u.assisted_ [...]
+        <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS 
password, o.cipher_certificate_number AS certificate_number FROM (SELECT 
`a`.`account_id`, `a`.`cipher_certificate_number`, 
`a`.`assisted_query_certificate_number`, `a`.`like_query_certificate_number`, 
`a`.`cipher_password`, `a`.`assisted_query_password`, 
`a`.`like_query_password`, `a`.`cipher_amount` FROM t_account `a`) o, t_account 
u WHERE o.assisted_query_certificate_number=u.assisted_query_certificate_number 
 [...]
     </rewrite-assertion>
 
     <rewrite-assertion 
id="select_not_nested_subquery_in_table_segment_with_shorthand_project" 
db-types="MySQL">
         <input sql="SELECT u.amount, u.password, o.certificate_number FROM 
(SELECT * FROM t_account) o, t_account u WHERE 
o.certificate_number=u.certificate_number AND u.password=?" parameters="1" />
-        <output sql="SELECT u.amount, u.password, o.certificate_number FROM 
(SELECT t_account.`account_id`, t_account.`cipher_certificate_number` AS 
`certificate_number`, t_account.`assisted_query_certificate_number`, 
t_account.`like_query_certificate_number`, t_account.`cipher_password` AS 
`password`, t_account.`assisted_query_password`, 
t_account.`like_query_password`, t_account.`cipher_amount` AS `amount` FROM 
t_account) o, t_account u WHERE o.assisted_query_certificate_number=u.assis 
[...]
+        <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS 
password, o.cipher_certificate_number AS certificate_number FROM (SELECT 
t_account.`account_id`, t_account.`cipher_certificate_number`, 
t_account.`assisted_query_certificate_number`, 
t_account.`like_query_certificate_number`, t_account.`cipher_password`, 
t_account.`assisted_query_password`, t_account.`like_query_password`, 
t_account.`cipher_amount` FROM t_account) o, t_account u WHERE 
o.assisted_query_certificate [...]
     </rewrite-assertion>
 
     <rewrite-assertion 
id="select_not_nested_subquery_in_predicate_right_equal_condition" 
db-types="MySQL">
diff --git 
a/test/it/rewriter/src/test/resources/scenario/mix/case/query-with-cipher/dml/select/select-subquery.xml
 
b/test/it/rewriter/src/test/resources/scenario/mix/case/query-with-cipher/dml/select/select-subquery.xml
index e0ccbe45cde..90828aac50a 100644
--- 
a/test/it/rewriter/src/test/resources/scenario/mix/case/query-with-cipher/dml/select/select-subquery.xml
+++ 
b/test/it/rewriter/src/test/resources/scenario/mix/case/query-with-cipher/dml/select/select-subquery.xml
@@ -25,14 +25,14 @@
     
     <rewrite-assertion 
id="select_not_nested_subquery_in_table_segment_with_shorthand_project_alias" 
db-types="MySQL">
         <input sql="SELECT u.amount, u.password FROM (SELECT a.* FROM 
t_account a) o, t_account u WHERE u.password=?" parameters="1" />
-        <output sql="SELECT u.amount, u.password FROM (SELECT a.`account_id`, 
a.`cipher_password` AS `password`, a.`assisted_query_password`, 
a.`cipher_amount` AS `amount` FROM t_account_0 a) o, t_account_0 u WHERE 
u.assisted_query_password=?" parameters="assisted_query_1" />
-        <output sql="SELECT u.amount, u.password FROM (SELECT a.`account_id`, 
a.`cipher_password` AS `password`, a.`assisted_query_password`, 
a.`cipher_amount` AS `amount` FROM t_account_1 a) o, t_account_1 u WHERE 
u.assisted_query_password=?" parameters="assisted_query_1" />
+        <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS 
password FROM (SELECT a.`account_id`, a.`cipher_password`, 
a.`assisted_query_password`, a.`cipher_amount` FROM t_account_0 a) o, 
t_account_0 u WHERE u.assisted_query_password=?" parameters="assisted_query_1" 
/>
+        <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS 
password FROM (SELECT a.`account_id`, a.`cipher_password`, 
a.`assisted_query_password`, a.`cipher_amount` FROM t_account_1 a) o, 
t_account_1 u WHERE u.assisted_query_password=?" parameters="assisted_query_1" 
/>
     </rewrite-assertion>
 
     <rewrite-assertion 
id="select_not_nested_subquery_in_table_segment_with_shorthand_project_alias_quote"
 db-types="MySQL">
         <input sql="SELECT u.amount, u.password FROM (SELECT `a`.* FROM 
t_account `a`) o, t_account u WHERE u.password=?" parameters="1" />
-        <output sql="SELECT u.amount, u.password FROM (SELECT 
`a`.`account_id`, `a`.`cipher_password` AS `password`, 
`a`.`assisted_query_password`, `a`.`cipher_amount` AS `amount` FROM t_account_0 
`a`) o, t_account_0 u WHERE u.assisted_query_password=?" 
parameters="assisted_query_1" />
-        <output sql="SELECT u.amount, u.password FROM (SELECT 
`a`.`account_id`, `a`.`cipher_password` AS `password`, 
`a`.`assisted_query_password`, `a`.`cipher_amount` AS `amount` FROM t_account_1 
`a`) o, t_account_1 u WHERE u.assisted_query_password=?" 
parameters="assisted_query_1" />
+        <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS 
password FROM (SELECT `a`.`account_id`, `a`.`cipher_password`, 
`a`.`assisted_query_password`, `a`.`cipher_amount` FROM t_account_0 `a`) o, 
t_account_0 u WHERE u.assisted_query_password=?" parameters="assisted_query_1" 
/>
+        <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS 
password FROM (SELECT `a`.`account_id`, `a`.`cipher_password`, 
`a`.`assisted_query_password`, `a`.`cipher_amount` FROM t_account_1 `a`) o, 
t_account_1 u WHERE u.assisted_query_password=?" parameters="assisted_query_1" 
/>
     </rewrite-assertion>
     
     <rewrite-assertion id="select_not_nested_subquery_in_table_segment_alias" 
db-types="MySQL">


Reply via email to