This is an automated email from the ASF dual-hosted git repository.
sunnianjun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 9592b850627 Refactor EncryptProjectionTokenGenerator for projection
subquery and predicate subquery (#28043)
9592b850627 is described below
commit 9592b8506279791e0deaedc35fde556fc5d77b81
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Fri Aug 11 19:10:38 2023 +0800
Refactor EncryptProjectionTokenGenerator for projection subquery and
predicate subquery (#28043)
---
.../generator/EncryptProjectionTokenGenerator.java | 91 +++++++++-------------
.../EncryptProjectionTokenGeneratorTest.java | 3 +
.../sql/parser/sql/common/enums/SubqueryType.java | 2 +-
.../sql/common/util/SubqueryExtractUtils.java | 30 +++----
.../dml/select/select-subquery.xml | 4 +-
5 files changed, 59 insertions(+), 71 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 1891e99fb3e..a9498f4c1fe 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
@@ -24,7 +24,6 @@ import
org.apache.shardingsphere.encrypt.rewrite.aware.EncryptRuleAware;
import org.apache.shardingsphere.encrypt.rule.EncryptRule;
import org.apache.shardingsphere.encrypt.rule.EncryptTable;
import org.apache.shardingsphere.encrypt.rule.column.EncryptColumn;
-import
org.apache.shardingsphere.encrypt.rule.column.item.AssistedQueryColumnItem;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.DerivedColumn;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.ProjectionsContext;
@@ -50,6 +49,7 @@ import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegm
import
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
import java.util.Collection;
+import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -108,12 +108,19 @@ public final class EncryptProjectionTokenGenerator
implements CollectionSQLToken
}
}
+ private ColumnProjection buildColumnProjection(final
ColumnProjectionSegment segment) {
+ IdentifierValue owner =
segment.getColumn().getOwner().map(OwnerSegment::getIdentifier).orElse(null);
+ ColumnProjection result = new ColumnProjection(owner,
segment.getColumn().getIdentifier(), segment.getAliasName().isPresent() ?
segment.getAlias().orElse(null) : null, databaseType);
+ result.setOriginalColumn(segment.getColumn().getOriginalColumn());
+ result.setOriginalTable(segment.getColumn().getOriginalTable());
+ return result;
+ }
+
private SubstitutableColumnNameToken generateSQLToken(final EncryptColumn
encryptColumn, final ColumnProjectionSegment columnSegment,
final
ColumnProjection columnProjection, final SubqueryType subqueryType) {
- Collection<Projection> projections =
generateProjections(encryptColumn, columnProjection, subqueryType, false, null);
+ Collection<Projection> projections =
generateProjections(encryptColumn, columnProjection, subqueryType, false);
int startIndex = columnSegment.getColumn().getOwner().isPresent() ?
columnSegment.getColumn().getOwner().get().getStopIndex() + 2 :
columnSegment.getColumn().getStartIndex();
- int stopIndex = columnSegment.getStopIndex();
- return new SubstitutableColumnNameToken(startIndex, stopIndex,
projections);
+ return new SubstitutableColumnNameToken(startIndex,
columnSegment.getStopIndex(), projections);
}
private SubstitutableColumnNameToken generateSQLToken(final
ShorthandProjectionSegment segment, final Collection<Projection> actualColumns,
@@ -125,7 +132,7 @@ public final class EncryptProjectionTokenGenerator
implements CollectionSQLToken
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));
+ projections.addAll(generateProjections(encryptColumn,
columnProjection, subqueryType, true));
continue;
}
}
@@ -138,67 +145,45 @@ public final class EncryptProjectionTokenGenerator
implements CollectionSQLToken
return new SubstitutableColumnNameToken(startIndex,
segment.getStopIndex(), projections,
dialectDatabaseMetaData.getQuoteCharacter());
}
- private ColumnProjection buildColumnProjection(final
ColumnProjectionSegment segment) {
- IdentifierValue owner =
segment.getColumn().getOwner().map(OwnerSegment::getIdentifier).orElse(null);
- ColumnProjection result = new ColumnProjection(owner,
segment.getColumn().getIdentifier(), segment.getAliasName().isPresent() ?
segment.getAlias().orElse(null) : null, databaseType);
- result.setOriginalColumn(segment.getColumn().getOriginalColumn());
- result.setOriginalTable(segment.getColumn().getOriginalTable());
- return result;
- }
-
private Collection<Projection> generateProjections(final EncryptColumn
encryptColumn, final ColumnProjection columnProjection,
- final SubqueryType
subqueryType, final boolean shorthandProjection, final
ShorthandProjectionSegment segment) {
- Collection<Projection> result = new LinkedList<>();
- if (SubqueryType.PREDICATE_SUBQUERY == subqueryType) {
- result.add(generatePredicateSubqueryProjection(encryptColumn,
columnProjection, shorthandProjection));
+ final SubqueryType
subqueryType, final boolean shorthandProjection) {
+ if (null == subqueryType || SubqueryType.PROJECTION_SUBQUERY ==
subqueryType) {
+ return Collections.singleton(generateProjection(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,
columnProjection, shorthandProjection));
- } else {
- result.add(generateCommonProjection(encryptColumn,
columnProjection, segment, shorthandProjection));
+ return generateProjectionsInTableSegmentSubquery(encryptColumn,
columnProjection, shorthandProjection, subqueryType);
+ } else if (SubqueryType.PREDICATE_SUBQUERY == subqueryType) {
+ return
Collections.singleton(generateProjectionInPredicateSubquery(encryptColumn,
columnProjection, shorthandProjection));
}
- return result;
+ throw new UnsupportedSQLOperationException("Projections not in simple
select, table subquery, join subquery and predicate subquery are not supported
in encrypt feature.");
}
- 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(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 ColumnProjection generateProjection(final EncryptColumn
encryptColumn, final ColumnProjection columnProjection, final boolean
shorthandProjection) {
+ IdentifierValue encryptColumnOwner = shorthandProjection ?
columnProjection.getOwner().orElse(null) : null;
+ String encryptColumnName = encryptColumn.getCipher().getName();
+ return new ColumnProjection(encryptColumnOwner, new
IdentifierValue(encryptColumnName,
columnProjection.getName().getQuoteCharacter()),
+
columnProjection.getAlias().orElse(columnProjection.getName()), databaseType);
}
- private Collection<ColumnProjection>
generateTableSegmentSubqueryProjections(final EncryptColumn encryptColumn,
final ColumnProjection columnProjection, final boolean shorthandProjection,
-
final SubqueryType subqueryType) {
- Collection<ColumnProjection> result = new LinkedList<>();
- IdentifierValue owner = columnProjection.getOwner().orElse(null);
+ private Collection<Projection>
generateProjectionsInTableSegmentSubquery(final EncryptColumn encryptColumn,
final ColumnProjection columnProjection,
+
final boolean shorthandProjection, final SubqueryType subqueryType) {
+ Collection<Projection> result = new LinkedList<>();
+ IdentifierValue encryptColumnOwner = shorthandProjection ?
columnProjection.getOwner().orElse(null) : 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)));
+ result.add(new ColumnProjection(encryptColumnOwner, columnName, alias,
databaseType));
+ IdentifierValue assistedColumOwner =
columnProjection.getOwner().orElse(null);
+ encryptColumn.getAssistedQuery().ifPresent(optional -> result.add(new
ColumnProjection(assistedColumOwner, new IdentifierValue(optional.getName(),
quoteCharacter), null, databaseType)));
+ encryptColumn.getLikeQuery().ifPresent(optional -> result.add(new
ColumnProjection(assistedColumOwner, new IdentifierValue(optional.getName(),
quoteCharacter), null, databaseType)));
return result;
}
- 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 columnProjection, final boolean shorthandProjection) {
- Collection<ColumnProjection> result = new LinkedList<>();
- 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 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 ColumnProjection generateProjectionInPredicateSubquery(final
EncryptColumn encryptColumn, final ColumnProjection columnProjection, final
boolean shorthandProjection) {
+ IdentifierValue owner = shorthandProjection ?
columnProjection.getOwner().orElse(null) : null;
+ QuoteCharacter quoteCharacter =
columnProjection.getName().getQuoteCharacter();
+ return encryptColumn.getAssistedQuery().map(optional -> new
ColumnProjection(owner, new IdentifierValue(optional.getName(),
quoteCharacter), null, databaseType))
+ .orElseGet(() -> new ColumnProjection(owner, new
IdentifierValue(encryptColumn.getCipher().getName(), quoteCharacter),
columnProjection.getAlias().orElse(columnProjection.getName()),
+ databaseType));
}
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 22d927bf71d..b1f0893683e 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
@@ -88,6 +88,7 @@ class EncryptProjectionTokenGeneratorTest {
ProjectionsSegment projections = mock(ProjectionsSegment.class);
when(projections.getProjections()).thenReturn(Collections.singletonList(new
ColumnProjectionSegment(column)));
SelectStatementContext sqlStatementContext =
mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
+ when(sqlStatementContext.getSubqueryType()).thenReturn(null);
when(sqlStatementContext.getDatabaseType()).thenReturn(databaseType);
when(sqlStatementContext.getSqlStatement().getProjections()).thenReturn(projections);
when(sqlStatementContext.getSubqueryContexts().values()).thenReturn(Collections.emptyList());
@@ -109,6 +110,7 @@ class EncryptProjectionTokenGeneratorTest {
ProjectionsSegment projections = mock(ProjectionsSegment.class);
when(projections.getProjections()).thenReturn(Collections.singletonList(new
ColumnProjectionSegment(column)));
SelectStatementContext sqlStatementContext =
mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
+ when(sqlStatementContext.getSubqueryType()).thenReturn(null);
when(sqlStatementContext.getDatabaseType()).thenReturn(databaseType);
when(sqlStatementContext.getSqlStatement().getProjections()).thenReturn(projections);
when(sqlStatementContext.getSubqueryContexts().values()).thenReturn(Collections.emptyList());
@@ -126,6 +128,7 @@ class EncryptProjectionTokenGeneratorTest {
ProjectionsSegment projections = mock(ProjectionsSegment.class);
when(projections.getProjections()).thenReturn(Collections.singletonList(new
ColumnProjectionSegment(column)));
SelectStatementContext sqlStatementContext =
mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
+ when(sqlStatementContext.getSubqueryType()).thenReturn(null);
when(sqlStatementContext.getDatabaseType()).thenReturn(databaseType);
when(sqlStatementContext.getSqlStatement().getProjections()).thenReturn(projections);
when(sqlStatementContext.getSubqueryContexts().values()).thenReturn(Collections.emptyList());
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 383c9ede9d4..e2b752cb1bc 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, JOIN_SUBQUERY, PREDICATE_SUBQUERY,
INSERT_SELECT_SUBQUERY, EXISTS_SUBQUERY
+ PROJECTION_SUBQUERY, TABLE_SUBQUERY, JOIN_SUBQUERY, PREDICATE_SUBQUERY,
INSERT_SELECT_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 22e360b253f..2759801fa8d 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
@@ -63,7 +63,7 @@ public final class SubqueryExtractUtils {
extractSubquerySegmentsFromProjections(result,
selectStatement.getProjections());
extractSubquerySegmentsFromTableSegment(result,
selectStatement.getFrom());
if (selectStatement.getWhere().isPresent()) {
- extractSubquerySegmentsFromExpression(result,
selectStatement.getWhere().get().getExpr());
+ extractSubquerySegmentsFromWhere(result,
selectStatement.getWhere().get().getExpr());
}
if (selectStatement.getCombine().isPresent()) {
CombineSegment combineSegment = selectStatement.getCombine().get();
@@ -116,35 +116,35 @@ public final class SubqueryExtractUtils {
extractSubquerySegments(result, subquery.getSelect());
}
- private static void extractSubquerySegmentsFromExpression(final
List<SubquerySegment> result, final ExpressionSegment expressionSegment) {
+ private static void extractSubquerySegmentsFromWhere(final
List<SubquerySegment> result, final ExpressionSegment expressionSegment) {
if (expressionSegment instanceof SubqueryExpressionSegment) {
SubquerySegment subquery = ((SubqueryExpressionSegment)
expressionSegment).getSubquery();
subquery.setSubqueryType(SubqueryType.PREDICATE_SUBQUERY);
result.add(subquery);
extractSubquerySegments(result, subquery.getSelect());
}
+ if (expressionSegment instanceof ExistsSubqueryExpression) {
+ SubquerySegment subquery = ((ExistsSubqueryExpression)
expressionSegment).getSubquery();
+ subquery.setSubqueryType(SubqueryType.PREDICATE_SUBQUERY);
+ result.add(subquery);
+ extractSubquerySegments(result, subquery.getSelect());
+ }
if (expressionSegment instanceof ListExpression) {
for (ExpressionSegment each : ((ListExpression)
expressionSegment).getItems()) {
- extractSubquerySegmentsFromExpression(result, each);
+ extractSubquerySegmentsFromWhere(result, each);
}
}
if (expressionSegment instanceof BinaryOperationExpression) {
- extractSubquerySegmentsFromExpression(result,
((BinaryOperationExpression) expressionSegment).getLeft());
- extractSubquerySegmentsFromExpression(result,
((BinaryOperationExpression) expressionSegment).getRight());
+ extractSubquerySegmentsFromWhere(result,
((BinaryOperationExpression) expressionSegment).getLeft());
+ extractSubquerySegmentsFromWhere(result,
((BinaryOperationExpression) expressionSegment).getRight());
}
if (expressionSegment instanceof InExpression) {
- extractSubquerySegmentsFromExpression(result, ((InExpression)
expressionSegment).getLeft());
- extractSubquerySegmentsFromExpression(result, ((InExpression)
expressionSegment).getRight());
+ extractSubquerySegmentsFromWhere(result, ((InExpression)
expressionSegment).getLeft());
+ extractSubquerySegmentsFromWhere(result, ((InExpression)
expressionSegment).getRight());
}
if (expressionSegment instanceof BetweenExpression) {
- extractSubquerySegmentsFromExpression(result, ((BetweenExpression)
expressionSegment).getBetweenExpr());
- extractSubquerySegmentsFromExpression(result, ((BetweenExpression)
expressionSegment).getAndExpr());
- }
- if (expressionSegment instanceof ExistsSubqueryExpression) {
- SubquerySegment subquery = ((ExistsSubqueryExpression)
expressionSegment).getSubquery();
- subquery.setSubqueryType(SubqueryType.EXISTS_SUBQUERY);
- result.add(subquery);
- extractSubquerySegments(result, subquery.getSelect());
+ extractSubquerySegmentsFromWhere(result, ((BetweenExpression)
expressionSegment).getBetweenExpr());
+ extractSubquerySegmentsFromWhere(result, ((BetweenExpression)
expressionSegment).getAndExpr());
}
}
}
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 69216088fc1..45dd5f6b56a 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
@@ -74,12 +74,12 @@
<rewrite-assertion id="select_not_nested_subquery_in_predicate_exists"
db-types="MySQL">
<input sql="SELECT u.amount, u.password, u.certificate_number FROM
t_account_bak u WHERE EXISTS(SELECT b.certificate_number from t_account b where
b.certificate_number=u.certificate_number)" />
- <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS
password, u.cipher_certificate_number AS certificate_number FROM t_account_bak
u WHERE EXISTS(SELECT b.cipher_certificate_number AS certificate_number from
t_account b where
b.assisted_query_certificate_number=u.assisted_query_certificate_number)" />
+ <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS
password, u.cipher_certificate_number AS certificate_number FROM t_account_bak
u WHERE EXISTS(SELECT b.assisted_query_certificate_number from t_account b
where b.assisted_query_certificate_number=u.assisted_query_certificate_number)"
/>
</rewrite-assertion>
<rewrite-assertion id="select_not_nested_subquery_in_predicate_not_exists"
db-types="MySQL">
<input sql="SELECT u.amount, u.password, u.certificate_number FROM
t_account_bak u WHERE NOT EXISTS(SELECT b.certificate_number from t_account b
where b.certificate_number=u.certificate_number)" />
- <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS
password, u.cipher_certificate_number AS certificate_number FROM t_account_bak
u WHERE NOT EXISTS(SELECT b.cipher_certificate_number AS certificate_number
from t_account b where
b.assisted_query_certificate_number=u.assisted_query_certificate_number)" />
+ <output sql="SELECT u.cipher_amount AS amount, u.cipher_password AS
password, u.cipher_certificate_number AS certificate_number FROM t_account_bak
u WHERE NOT EXISTS(SELECT b.assisted_query_certificate_number from t_account b
where b.assisted_query_certificate_number=u.assisted_query_certificate_number)"
/>
</rewrite-assertion>
<rewrite-assertion
id="select_not_nested_subquery_in_predicate_in_condition" db-types="MySQL">