You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2023/08/11 07:22:49 UTC
[shardingsphere] branch master updated: distinguish table subquery and join subquery to fix rewriting wrong result when join segment contains subquery table (#28040)
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 <du...@apache.org>
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">