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">