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 841fda87c4f Fix wrong shorthand projection when subquery contains same column name projection and join statement (#26813) 841fda87c4f is described below commit 841fda87c4f04d724b1c7bb15552a3eca177b5f4 Author: Zhengqiang Duan <duanzhengqi...@apache.org> AuthorDate: Fri Jul 7 18:15:26 2023 +0800 Fix wrong shorthand projection when subquery contains same column name projection and join statement (#26813) * Fix wrong shorthand projection when subquery contains same column name projection and join statement * fix rewrite it * Fix wrong rewrite result when from segment contains multi subquery table join * Fix wrong rewrite result when from segment contains multi subquery table join * Fix wrong rewrite result when from segment contains multi subquery table join * fix checkstyle * fix unit test * fix unit test * fix build error * Fix unit test * Fix unit test * fix build error * remove useless file --- .../encrypt/merge/dql/EncryptMergedResult.java | 12 ++++---- .../EncryptOrderByItemTokenGenerator.java | 6 ++-- .../generator/EncryptProjectionTokenGenerator.java | 18 ++++++++++-- .../segment/select/projection/Projection.java | 8 ++++-- .../select/projection/ProjectionsContext.java | 10 +++++-- .../select/projection/engine/ProjectionEngine.java | 21 ++++++++------ .../impl/AggregationDistinctProjection.java | 9 ++++-- .../projection/impl/AggregationProjection.java | 7 +++-- .../select/projection/impl/ColumnProjection.java | 33 ++++++++++++++++++++-- .../select/projection/impl/DerivedProjection.java | 5 ++-- .../projection/impl/ExpressionProjection.java | 6 ++-- .../projection/impl/ParameterMarkerProjection.java | 6 ++-- .../projection/impl/ShorthandProjection.java | 6 ++-- .../select/projection/impl/SubqueryProjection.java | 5 ++-- .../projection/engine/ProjectionEngineTest.java | 5 ++-- .../prepare/MySQLComStmtPrepareExecutor.java | 5 ++-- .../dml/select/select-subquery.xml | 24 ++++++++-------- .../dml/select/select-subquery.xml | 16 +++++------ 18 files changed, 134 insertions(+), 68 deletions(-) diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/merge/dql/EncryptMergedResult.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/merge/dql/EncryptMergedResult.java index 038bfff8733..a700d62bdf2 100644 --- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/merge/dql/EncryptMergedResult.java +++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/merge/dql/EncryptMergedResult.java @@ -63,17 +63,19 @@ public final class EncryptMergedResult implements MergedResult { TablesContext tablesContext = selectStatementContext.getTablesContext(); String schemaName = tablesContext.getSchemaName() .orElseGet(() -> DatabaseTypeEngine.getDefaultSchemaName(selectStatementContext.getDatabaseType(), database.getName())); - Map<String, String> expressionTableNames = tablesContext.findTableNamesByColumnProjection(Collections.singleton(columnProjection.get()), database.getSchema(schemaName)); - Optional<String> tableName = findTableName(columnProjection.get(), expressionTableNames); + ColumnProjection originalColumn = new ColumnProjection(columnProjection.get().getOriginalOwner(), columnProjection.get().getOriginalName(), null); + Map<String, String> expressionTableNames = tablesContext.findTableNamesByColumnProjection(Collections.singletonList(originalColumn), database.getSchema(schemaName)); + Optional<String> tableName = findTableName(originalColumn, expressionTableNames); + String originalColumnName = originalColumn.getName(); if (!tableName.isPresent()) { return mergedResult.getValue(columnIndex, type); } - if (!encryptRule.findEncryptTable(tableName.get()).map(optional -> optional.isEncryptColumn(columnProjection.get().getName())).orElse(false)) { + if (!encryptRule.findEncryptTable(tableName.get()).map(optional -> optional.isEncryptColumn(originalColumnName)).orElse(false)) { return mergedResult.getValue(columnIndex, type); } Object cipherValue = mergedResult.getValue(columnIndex, Object.class); - EncryptColumn encryptColumn = encryptRule.getEncryptTable(tableName.get()).getEncryptColumn(columnProjection.get().getName()); - return encryptColumn.getCipher().decrypt(database.getName(), schemaName, tableName.get(), columnProjection.get().getName(), cipherValue); + EncryptColumn encryptColumn = encryptRule.getEncryptTable(tableName.get()).getEncryptColumn(originalColumnName); + return encryptColumn.getCipher().decrypt(database.getName(), schemaName, tableName.get(), originalColumnName, cipherValue); } private Optional<String> findTableName(final ColumnProjection columnProjection, final Map<String, String> columnTableNames) { diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java index 4575a7eeb17..e3b1df2e96a 100644 --- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java +++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java @@ -103,7 +103,9 @@ public final class EncryptOrderByItemTokenGenerator implements CollectionSQLToke } Collection<OrderByItem> result = new LinkedList<>(); SelectStatementContext statementContext = (SelectStatementContext) sqlStatementContext; - result.addAll(statementContext.getOrderByContext().getItems()); + if (!statementContext.getOrderByContext().isGenerated()) { + result.addAll(statementContext.getOrderByContext().getItems()); + } result.addAll(statementContext.getGroupByContext().getItems()); for (SelectStatementContext each : statementContext.getSubqueryContexts().values()) { result.addAll(getOrderByItems(each)); @@ -116,7 +118,7 @@ public final class EncryptOrderByItemTokenGenerator implements CollectionSQLToke return false; } SelectStatementContext statementContext = (SelectStatementContext) sqlStatementContext; - if (!statementContext.getOrderByContext().getItems().isEmpty() || !statementContext.getGroupByContext().getItems().isEmpty()) { + if (!statementContext.getOrderByContext().getItems().isEmpty() && !statementContext.getOrderByContext().isGenerated() || !statementContext.getGroupByContext().getItems().isEmpty()) { return true; } for (SelectStatementContext each : statementContext.getSubqueryContexts().values()) { 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 e0f12b6d497..c7f14e2e817 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 @@ -43,6 +43,8 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.Projecti 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.JoinTableSegment; +import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment; import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue; import java.util.Collection; @@ -95,7 +97,7 @@ public final class EncryptProjectionTokenGenerator implements CollectionSQLToken continue; } Optional<EncryptTable> encryptTable = encryptRule.findEncryptTable(tableName); - if (encryptTable.isPresent() && encryptTable.get().isEncryptColumn(columnProjection.getName())) { + if (encryptTable.isPresent() && encryptTable.get().isEncryptColumn(columnProjection.getName()) && !containsTableSubquery(selectStatementContext)) { sqlTokens.add(generateSQLToken(encryptTable.get().getEncryptColumn(columnProjection.getName()), columnSegment, columnProjection, subqueryType)); } } @@ -123,7 +125,7 @@ public final class EncryptProjectionTokenGenerator implements CollectionSQLToken for (Projection each : actualColumns) { String tableName = columnTableNames.get(each.getExpression()); Optional<EncryptTable> encryptTable = null == tableName ? Optional.empty() : encryptRule.findEncryptTable(tableName); - if (!encryptTable.isPresent() || !encryptTable.get().isEncryptColumn(each.getColumnLabel())) { + if (!encryptTable.isPresent() || !encryptTable.get().isEncryptColumn(each.getColumnLabel()) || containsTableSubquery(selectStatementContext)) { projections.add(each.getAlias().map(optional -> (Projection) new ColumnProjection(null, optional, null)).orElse(each)); } else if (each instanceof ColumnProjection) { projections.addAll(generateProjections(encryptTable.get().getEncryptColumn(((ColumnProjection) each).getName()), (ColumnProjection) each, subqueryType, true, segment)); @@ -134,6 +136,16 @@ public final class EncryptProjectionTokenGenerator implements CollectionSQLToken return new SubstitutableColumnNameToken(startIndex, segment.getStopIndex(), projections, selectStatementContext.getDatabaseType().getQuoteCharacter()); } + private boolean containsTableSubquery(final SelectStatementContext selectStatementContext) { + if (selectStatementContext.getSqlStatement().getFrom() instanceof SubqueryTableSegment) { + return true; + } else if (selectStatementContext.getSqlStatement().getFrom() instanceof JoinTableSegment) { + JoinTableSegment joinTableSegment = (JoinTableSegment) selectStatementContext.getSqlStatement().getFrom(); + return joinTableSegment.getLeft() instanceof SubqueryTableSegment || joinTableSegment.getRight() instanceof SubqueryTableSegment; + } + return false; + } + private ColumnProjection buildColumnProjection(final ColumnProjectionSegment segment) { IdentifierValue owner = segment.getColumn().getOwner().map(OwnerSegment::getIdentifier).orElse(null); return new ColumnProjection(owner, segment.getColumn().getIdentifier(), segment.getAliasName().isPresent() ? segment.getAlias().map(AliasSegment::getIdentifier).orElse(null) : null); @@ -188,7 +200,7 @@ public final class EncryptProjectionTokenGenerator implements CollectionSQLToken private Collection<ColumnProjection> generateTableSubqueryProjections(final EncryptColumn encryptColumn, final ColumnProjection column, final boolean shorthand) { Collection<ColumnProjection> result = new LinkedList<>(); result.add(distinctOwner(new ColumnProjection(column.getOwnerIdentifier(), new IdentifierValue(encryptColumn.getCipher().getName(), - column.getNameIdentifier().getQuoteCharacter()), null), shorthand)); + column.getNameIdentifier().getQuoteCharacter()), Optional.ofNullable(column.getAliasIdentifier()).orElse(column.getNameIdentifier())), shorthand)); encryptColumn.getAssistedQuery().ifPresent(optional -> result.add( new ColumnProjection(column.getOwnerIdentifier(), new IdentifierValue(optional.getName(), column.getNameIdentifier().getQuoteCharacter()), null))); return result; diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/Projection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/Projection.java index fcdca992712..ee6e71e4835 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/Projection.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/Projection.java @@ -48,10 +48,12 @@ public interface Projection { String getColumnLabel(); /** - * Clone with owner. + * Transform subquery projection. * - * @param ownerIdentifier owner identifier + * @param subqueryTableAlias subquery table alias + * @param originalOwner original owner + * @param originalName original name * @return new projection */ - Projection cloneWithOwner(IdentifierValue ownerIdentifier); + Projection transformSubqueryProjection(IdentifierValue subqueryTableAlias, IdentifierValue originalOwner, IdentifierValue originalName); } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/ProjectionsContext.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/ProjectionsContext.java index 28d93f73c23..8b9dd179279 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/ProjectionsContext.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/ProjectionsContext.java @@ -21,6 +21,7 @@ import lombok.Getter; import lombok.ToString; import org.apache.shardingsphere.infra.binder.segment.select.projection.impl.AggregationDistinctProjection; import org.apache.shardingsphere.infra.binder.segment.select.projection.impl.AggregationProjection; +import org.apache.shardingsphere.infra.binder.segment.select.projection.impl.ColumnProjection; import org.apache.shardingsphere.infra.binder.segment.select.projection.impl.DerivedProjection; import org.apache.shardingsphere.infra.binder.segment.select.projection.impl.ShorthandProjection; import org.apache.shardingsphere.sql.parser.sql.common.util.SQLUtils; @@ -108,9 +109,10 @@ public final class ProjectionsContext { public Optional<String> findAlias(final String projectionName) { for (Projection each : projections) { if (each instanceof ShorthandProjection) { - Optional<Projection> projection = ((ShorthandProjection) each).getActualColumns().stream().filter(optional -> projectionName.equalsIgnoreCase(optional.getExpression())).findFirst(); + Optional<Projection> projection = + ((ShorthandProjection) each).getActualColumns().stream().filter(optional -> projectionName.equalsIgnoreCase(getOriginalColumnName(optional))).findFirst(); if (projection.isPresent()) { - return projection.flatMap(Projection::getAlias); + return projection.map(Projection::getExpression); } } if (projectionName.equalsIgnoreCase(SQLUtils.getExactlyValue(each.getExpression()))) { @@ -120,6 +122,10 @@ public final class ProjectionsContext { return Optional.empty(); } + private String getOriginalColumnName(final Projection projection) { + return projection instanceof ColumnProjection ? ((ColumnProjection) projection).getOriginalName().getValue() : projection.getExpression(); + } + /** * Find projection index. * diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngine.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngine.java index db43f0d67d2..806add4a88c 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngine.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngine.java @@ -17,7 +17,6 @@ package org.apache.shardingsphere.infra.binder.segment.select.projection.engine; -import com.google.common.base.Strings; import lombok.RequiredArgsConstructor; import org.apache.shardingsphere.infra.binder.segment.select.projection.DerivedColumn; import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection; @@ -127,7 +126,7 @@ public final class ProjectionEngine { IdentifierValue owner = projectionSegment.getOwner().map(OwnerSegment::getIdentifier).orElse(null); Collection<Projection> projections = new LinkedHashSet<>(); projections.addAll(getShorthandColumnsFromSimpleTableSegment(table, owner)); - projections.addAll(getShorthandColumnsFromSubqueryTableSegment(table)); + projections.addAll(getShorthandColumnsFromSubqueryTableSegment(table, owner)); projections.addAll(getShorthandColumnsFromJoinTableSegment(table, owner, projectionSegment)); return new ShorthandProjection(null == owner ? null : owner.getValue(), projections); } @@ -184,26 +183,30 @@ public final class ProjectionEngine { return result; } - private Collection<Projection> getShorthandColumnsFromSubqueryTableSegment(final TableSegment table) { - if (!(table instanceof SubqueryTableSegment)) { + private Collection<Projection> getShorthandColumnsFromSubqueryTableSegment(final TableSegment table, final IdentifierValue owner) { + if (!(table instanceof SubqueryTableSegment) || isOwnerNotSameWithTableAlias(owner, table)) { return Collections.emptyList(); } SelectStatement subSelectStatement = ((SubqueryTableSegment) table).getSubquery().getSelect(); Collection<Projection> projections = subSelectStatement.getProjections().getProjections().stream().map(each -> createProjection(subSelectStatement.getFrom(), each).orElse(null)) .filter(Objects::nonNull).collect(Collectors.toList()); - return getSubqueryTableActualProjections(projections, table.getAlias().map(AliasSegment::getIdentifier).orElse(null)); + IdentifierValue subqueryTableAlias = table.getAlias().map(AliasSegment::getIdentifier).orElse(null); + return getSubqueryTableActualProjections(projections, subqueryTableAlias); + } + + private boolean isOwnerNotSameWithTableAlias(final IdentifierValue owner, final TableSegment table) { + return null != owner && table.getAliasName().isPresent() && !table.getAliasName().get().equals(owner.getValue()); } private Collection<Projection> getSubqueryTableActualProjections(final Collection<Projection> projections, final IdentifierValue subqueryTableAlias) { - if (null == subqueryTableAlias || Strings.isNullOrEmpty(subqueryTableAlias.getValue())) { - return getActualProjections(projections); - } Collection<Projection> result = new LinkedList<>(); for (Projection each : projections) { if (each instanceof ShorthandProjection) { result.addAll(getSubqueryTableActualProjections(((ShorthandProjection) each).getActualColumns(), subqueryTableAlias)); } else if (!(each instanceof DerivedProjection)) { - result.add(each.cloneWithOwner(subqueryTableAlias)); + IdentifierValue originalOwner = each instanceof ColumnProjection ? ((ColumnProjection) each).getOriginalOwner() : null; + IdentifierValue originalName = each instanceof ColumnProjection ? ((ColumnProjection) each).getOriginalName() : null; + result.add(each.transformSubqueryProjection(subqueryTableAlias, originalOwner, originalName)); } } return result; diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationDistinctProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationDistinctProjection.java index d3651f0966a..93fcd4e7b17 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationDistinctProjection.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationDistinctProjection.java @@ -53,8 +53,11 @@ public final class AggregationDistinctProjection extends AggregationProjection { } @Override - public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) { - // TODO replace column owner when AggregationDistinctProjection contains owner - return new AggregationDistinctProjection(startIndex, stopIndex, getType(), getInnerExpression(), getAlias().orElse(null), distinctInnerExpression, getDatabaseType()); + public Projection transformSubqueryProjection(final IdentifierValue subqueryTableAlias, final IdentifierValue originalOwner, final IdentifierValue originalName) { + // TODO replace getAlias with aliasIdentifier + if (getAlias().isPresent()) { + return new ColumnProjection(subqueryTableAlias, new IdentifierValue(getAlias().get()), null); + } + return new AggregationDistinctProjection(startIndex, stopIndex, getType(), getInnerExpression(), null, distinctInnerExpression, getDatabaseType()); } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationProjection.java index f91ca5d9d1f..13f650071e9 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationProjection.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationProjection.java @@ -75,8 +75,11 @@ public class AggregationProjection implements Projection { } @Override - public Projection cloneWithOwner(final IdentifierValue owner) { - // TODO replace column owner when AggregationProjection contains owner + public Projection transformSubqueryProjection(final IdentifierValue subqueryTableAlias, final IdentifierValue originalOwner, final IdentifierValue originalName) { + // TODO replace getAlias with aliasIdentifier + if (getAlias().isPresent()) { + return new ColumnProjection(subqueryTableAlias, new IdentifierValue(getAlias().get()), null); + } AggregationProjection result = new AggregationProjection(type, innerExpression, alias, databaseType); result.setIndex(index); result.getDerivedAggregationProjections().addAll(derivedAggregationProjections); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ColumnProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ColumnProjection.java index 65b074d0a48..1b12c8a8c60 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ColumnProjection.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ColumnProjection.java @@ -20,6 +20,7 @@ package org.apache.shardingsphere.infra.binder.segment.select.projection.impl; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; +import lombok.Setter; import lombok.ToString; import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection; import org.apache.shardingsphere.sql.parser.sql.common.enums.QuoteCharacter; @@ -32,7 +33,8 @@ import java.util.Optional; */ @RequiredArgsConstructor @Getter -@EqualsAndHashCode +@Setter +@EqualsAndHashCode(exclude = {"originalOwner", "originalName"}) @ToString public final class ColumnProjection implements Projection { @@ -42,6 +44,10 @@ public final class ColumnProjection implements Projection { private final IdentifierValue aliasIdentifier; + private IdentifierValue originalOwner; + + private IdentifierValue originalName; + public ColumnProjection(final String owner, final String name, final String alias) { this(null == owner ? null : new IdentifierValue(owner, QuoteCharacter.NONE), new IdentifierValue(name, QuoteCharacter.NONE), null == alias ? null : new IdentifierValue(alias, QuoteCharacter.NONE)); @@ -81,7 +87,28 @@ public final class ColumnProjection implements Projection { } @Override - public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) { - return new ColumnProjection(ownerIdentifier, nameIdentifier, aliasIdentifier); + public Projection transformSubqueryProjection(final IdentifierValue subqueryTableAlias, final IdentifierValue originalOwner, final IdentifierValue originalName) { + ColumnProjection result = null == aliasIdentifier ? new ColumnProjection(subqueryTableAlias, nameIdentifier, null) : new ColumnProjection(subqueryTableAlias, aliasIdentifier, null); + result.setOriginalOwner(originalOwner); + result.setOriginalName(originalName); + return result; + } + + /** + * Get original owner. + * + * @return original owner + */ + public IdentifierValue getOriginalOwner() { + return null == originalOwner ? ownerIdentifier : originalOwner; + } + + /** + * Get original name. + * + * @return original name + */ + public IdentifierValue getOriginalName() { + return null == originalName ? nameIdentifier : originalName; } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/DerivedProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/DerivedProjection.java index f05b47aaf39..29b2d690fc5 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/DerivedProjection.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/DerivedProjection.java @@ -53,7 +53,8 @@ public final class DerivedProjection implements Projection { } @Override - public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) { - return new DerivedProjection(expression, alias, derivedProjectionSegment); + public Projection transformSubqueryProjection(final IdentifierValue subqueryTableAlias, final IdentifierValue originalOwner, final IdentifierValue originalName) { + // TODO replace getAlias with aliasIdentifier + return getAlias().isPresent() ? new ColumnProjection(subqueryTableAlias, new IdentifierValue(getAlias().get()), null) : new DerivedProjection(expression, alias, derivedProjectionSegment); } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ExpressionProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ExpressionProjection.java index 91ec030aac4..aa28aaa2ab3 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ExpressionProjection.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ExpressionProjection.java @@ -50,8 +50,8 @@ public final class ExpressionProjection implements Projection { } @Override - public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) { - // TODO replace column owner when ExpressionProjection contains owner - return new ExpressionProjection(expression, alias); + public Projection transformSubqueryProjection(final IdentifierValue subqueryTableAlias, final IdentifierValue originalOwner, final IdentifierValue originalName) { + // TODO replace getAlias with aliasIdentifier + return getAlias().isPresent() ? new ColumnProjection(subqueryTableAlias, new IdentifierValue(getAlias().get()), null) : new ExpressionProjection(expression, alias); } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ParameterMarkerProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ParameterMarkerProjection.java index 3c5609ac769..4f09d7e0c32 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ParameterMarkerProjection.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ParameterMarkerProjection.java @@ -58,7 +58,9 @@ public final class ParameterMarkerProjection implements Projection { } @Override - public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) { - return new ParameterMarkerProjection(parameterMarkerIndex, parameterMarkerType, alias); + public Projection transformSubqueryProjection(final IdentifierValue subqueryTableAlias, final IdentifierValue originalOwner, final IdentifierValue originalName) { + // TODO replace getAlias with aliasIdentifier + return getAlias().isPresent() ? new ColumnProjection(subqueryTableAlias, new IdentifierValue(getAlias().get()), null) + : new ParameterMarkerProjection(parameterMarkerIndex, parameterMarkerType, alias); } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ShorthandProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ShorthandProjection.java index f503f04fa32..248413bb463 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ShorthandProjection.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ShorthandProjection.java @@ -59,7 +59,7 @@ public final class ShorthandProjection implements Projection { /** * Get owner. - * + * * @return owner */ public Optional<String> getOwner() { @@ -82,7 +82,7 @@ public final class ShorthandProjection implements Projection { } @Override - public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) { - return new ShorthandProjection(ownerIdentifier.getValue(), actualColumns); + public Projection transformSubqueryProjection(final IdentifierValue subqueryTableAlias, final IdentifierValue originalOwner, final IdentifierValue originalName) { + return new ShorthandProjection(subqueryTableAlias.getValue(), actualColumns); } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/SubqueryProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/SubqueryProjection.java index b456eb08b61..4771a9c7cd2 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/SubqueryProjection.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/SubqueryProjection.java @@ -64,7 +64,8 @@ public final class SubqueryProjection implements Projection { } @Override - public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) { - return new SubqueryProjection(expression, projection, alias, databaseType); + public Projection transformSubqueryProjection(final IdentifierValue subqueryTableAlias, final IdentifierValue originalOwner, final IdentifierValue originalName) { + // TODO replace getAlias with aliasIdentifier + return getAlias().isPresent() ? new ColumnProjection(subqueryTableAlias, new IdentifierValue(getAlias().get()), null) : new SubqueryProjection(expression, projection, alias, databaseType); } } diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngineTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngineTest.java index 5b9c6a11f00..80fcb57ef9d 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngineTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngineTest.java @@ -233,14 +233,15 @@ class ProjectionEngineTest { .createProjection(subqueryTableSegment, shorthandProjectionSegment); assertTrue(actual.isPresent()); assertThat(actual.get(), instanceOf(ShorthandProjection.class)); - assertThat(((ShorthandProjection) actual.get()).getColumnProjections().size(), is(1)); + assertThat(((ShorthandProjection) actual.get()).getColumnProjections().size(), is(2)); assertThat(((ShorthandProjection) actual.get()).getActualColumns().size(), is(2)); Collection<ColumnProjection> columnProjections = new LinkedList<>(); columnProjections.add(new ColumnProjection(null, "name", null)); + columnProjections.add(new ColumnProjection(null, "leave_date", null)); assertThat(((ShorthandProjection) actual.get()).getColumnProjections(), is(columnProjections)); Collection<Projection> expectedColumnProjections = new LinkedHashSet<>(); expectedColumnProjections.add(new ColumnProjection(null, "name", null)); - expectedColumnProjections.add(new ExpressionProjection("nvl(leave_date, '20991231')", "leave_date")); + expectedColumnProjections.add(new ColumnProjection(null, "leave_date", null)); assertThat(((ShorthandProjection) actual.get()).getActualColumns(), is(expectedColumnProjections)); } diff --git a/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLComStmtPrepareExecutor.java b/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLComStmtPrepareExecutor.java index f049bf431b1..cb69cf6a7f6 100644 --- a/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLComStmtPrepareExecutor.java +++ b/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLComStmtPrepareExecutor.java @@ -148,8 +148,9 @@ public final class MySQLComStmtPrepareExecutor implements CommandExecutor { Collection<MySQLPacket> result = new ArrayList<>(projections.size()); for (Projection each : projections) { // TODO Calculate column definition flag for other projection types - if (each instanceof ColumnProjection) { - result.add(Optional.ofNullable(columnToTableMap.get(each.getExpression())).map(schema::getTable).map(table -> table.getColumn(((ColumnProjection) each).getName())) + if (each instanceof ColumnProjection && null != ((ColumnProjection) each).getOriginalName()) { + result.add(Optional.ofNullable(columnToTableMap.get(each.getExpression())).map(schema::getTable) + .map(table -> table.getColumns().get(((ColumnProjection) each).getOriginalName().getValue())) .map(column -> createMySQLColumnDefinition41Packet(characterSet, calculateColumnDefinitionFlag(column), MySQLBinaryColumnType.valueOfJDBCType(column.getDataType()))) .orElseGet(() -> createMySQLColumnDefinition41Packet(characterSet, 0, MySQLBinaryColumnType.VAR_STRING))); } else { 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 94b726421b8..52f6d8768cc 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,32 +24,32 @@ <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.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 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.amount, u.password, o.certificate_number FROM (SELECT cipher_certificate_number AS certificate_number, assisted_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.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 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.amount, u.password, o.certificate_number FROM (SELECT cipher_certificate_number AS certificate_number, assisted_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"> <input sql="SELECT o.certificate_number FROM (SELECT a.certificate_number FROM t_account a) o" /> - <output sql="SELECT o.cipher_certificate_number AS certificate_number FROM (SELECT a.cipher_certificate_number, a.assisted_query_certificate_number FROM t_account a) o" /> + <output sql="SELECT o.certificate_number FROM (SELECT a.cipher_certificate_number AS certificate_number, a.assisted_query_certificate_number FROM t_account a) o" /> </rewrite-assertion> <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.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.`cipher_password`, a.`assisted_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_query_password=?" parameters="assisted_query_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.`cipher_password` AS `password`, a.`assisted_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=?" 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, 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.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.`cipher_password`, a.`assisted_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_query_password=?" parameters="assisted_query_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.`cipher_password` AS `password`, a.`assisted_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=?" parameters="assisted_query_1" /> </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.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.`cipher_password`, t_account.`assisted_query_password`, t_account.`cipher_amount` FROM t_account) o, t_account u WHERE o.assisted_query_certificate_number=u.assisted_query_certificate_number AND u.assisted_query_password=?" [...] + <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.`cipher_password` AS `password`, t_account.`assisted_query_password`, t_account.`cipher_amount` AS `amount` FROM t_account) o, t_account u WHERE o.assisted_query_certificate_number=u.assisted_query_certificate_number AND u.assisted_query_password=?" parameters="as [...] </rewrite-assertion> <rewrite-assertion id="select_not_nested_subquery_in_predicate_right_equal_condition" db-types="MySQL"> @@ -64,7 +64,7 @@ <rewrite-assertion id="select_not_nested_subquery_in_table_with_alias" db-types="MySQL"> <input sql="SELECT count(*) as cnt FROM (SELECT ab.certificate_number FROM t_account ab) X" /> - <output sql="SELECT count(*) as cnt FROM (SELECT ab.cipher_certificate_number, ab.assisted_query_certificate_number FROM t_account ab) X" /> + <output sql="SELECT count(*) as cnt FROM (SELECT ab.cipher_certificate_number AS certificate_number, ab.assisted_query_certificate_number FROM t_account ab) X" /> </rewrite-assertion> <rewrite-assertion id="select_not_nested_subquery_in_predicate_left_and_right_equal_condition" db-types="MySQL"> @@ -89,12 +89,12 @@ <rewrite-assertion id="select_not_nested_subquery_in_tablesegment_from_alias" db-types="MySQL"> <input sql="SELECT b.certificate_number, b.amount FROM (SELECT a.certificate_number as certificate_number, a.amount FROM t_account a WHERE a.amount = 1373) b" /> - <output sql="SELECT b.cipher_certificate_number AS certificate_number, b.cipher_amount AS amount FROM (SELECT a.cipher_certificate_number, a.assisted_query_certificate_number, a.cipher_amount FROM t_account a WHERE a.cipher_amount = 'encrypt_1373') b" /> + <output sql="SELECT b.certificate_number, b.amount FROM (SELECT a.cipher_certificate_number AS certificate_number, a.assisted_query_certificate_number, a.cipher_amount AS amount FROM t_account a WHERE a.cipher_amount = 'encrypt_1373') b" /> </rewrite-assertion> <rewrite-assertion id="select_not_nested_subquery_in_tablesegment_ref_shorthand" db-types="MySQL"> <input sql="SELECT b.* FROM (SELECT a.certificate_number as certificate_number, a.amount FROM t_account a WHERE a.amount = 1373) b" /> - <output sql="SELECT b.cipher_certificate_number AS certificate_number, b.cipher_amount AS amount FROM (SELECT a.cipher_certificate_number, a.assisted_query_certificate_number, a.cipher_amount FROM t_account a WHERE a.cipher_amount = 'encrypt_1373') b" /> + <output sql="SELECT b.certificate_number, b.amount FROM (SELECT a.cipher_certificate_number AS certificate_number, a.assisted_query_certificate_number, a.cipher_amount AS amount FROM t_account a WHERE a.cipher_amount = 'encrypt_1373') b" /> </rewrite-assertion> <rewrite-assertion id="select_with_exists_sub_query" db-types="MySQL"> @@ -104,16 +104,16 @@ <rewrite-assertion id="select_sub_query_with_order_by" db-types="MySQL"> <input sql="SELECT COUNT(1) AS cnt FROM (SELECT a.amount FROM t_account a ORDER BY a.amount DESC ) AS tmp" /> - <output sql="SELECT COUNT(1) AS cnt FROM (SELECT a.cipher_amount FROM t_account a ORDER BY a.cipher_amount DESC ) AS tmp" /> + <output sql="SELECT COUNT(1) AS cnt FROM (SELECT a.cipher_amount AS amount FROM t_account a ORDER BY a.cipher_amount DESC ) AS tmp" /> </rewrite-assertion> <rewrite-assertion id="select_shorthand_from_sub_query_with_simple_select" db-types="MySQL"> <input sql="SELECT * FROM (SELECT * FROM t_account a) AS temp" /> - <output sql="SELECT temp.`account_id`, temp.`cipher_certificate_number` AS `certificate_number`, temp.`cipher_password` AS `password`, temp.`cipher_amount` AS `amount` FROM (SELECT a.`account_id`, a.`cipher_certificate_number`, a.`assisted_query_certificate_number`, a.`cipher_password`, a.`assisted_query_password`, a.`cipher_amount` FROM t_account a) AS temp" /> + <output sql="SELECT temp.`account_id`, temp.`certificate_number`, temp.`password`, temp.`amount` FROM (SELECT a.`account_id`, a.`cipher_certificate_number` AS `certificate_number`, a.`assisted_query_certificate_number`, a.`cipher_password` AS `password`, a.`assisted_query_password`, a.`cipher_amount` AS `amount` FROM t_account a) AS temp" /> </rewrite-assertion> <rewrite-assertion id="select_shorthand_from_sub_query_with_select_join" db-types="MySQL"> <input sql="SELECT * FROM (SELECT a1.* FROM t_account a1 INNER JOIN t_account a2) AS temp" /> - <output sql="SELECT temp.`account_id`, temp.`cipher_certificate_number` AS `certificate_number`, temp.`cipher_password` AS `password`, temp.`cipher_amount` AS `amount` FROM (SELECT a1.`account_id`, a1.`cipher_certificate_number`, a1.`assisted_query_certificate_number`, a1.`cipher_password`, a1.`assisted_query_password`, a1.`cipher_amount` FROM t_account a1 INNER JOIN t_account a2) AS temp" /> + <output sql="SELECT temp.`account_id`, temp.`certificate_number`, temp.`password`, temp.`amount` FROM (SELECT a1.`account_id`, a1.`cipher_certificate_number` AS `certificate_number`, a1.`assisted_query_certificate_number`, a1.`cipher_password` AS `password`, a1.`assisted_query_password`, a1.`cipher_amount` AS `amount` FROM t_account a1 INNER JOIN t_account a2) AS temp" /> </rewrite-assertion> </rewrite-assertions> 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 d36052b2238..866d943f13e 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 @@ -19,25 +19,25 @@ <rewrite-assertions yaml-rule="scenario/mix/config/query-with-cipher.yaml"> <rewrite-assertion id="select_not_nested_subquery_in_table_alias" db-types="MySQL"> <input sql="SELECT count(*) as cnt FROM (SELECT ab.password FROM t_account ab) X" /> - <output sql="SELECT count(*) as cnt FROM (SELECT ab.cipher_password, ab.assisted_query_password FROM t_account_0 ab) X" /> - <output sql="SELECT count(*) as cnt FROM (SELECT ab.cipher_password, ab.assisted_query_password FROM t_account_1 ab) X" /> + <output sql="SELECT count(*) as cnt FROM (SELECT ab.cipher_password AS password, ab.assisted_query_password FROM t_account_0 ab) X" /> + <output sql="SELECT count(*) as cnt FROM (SELECT ab.cipher_password AS password, ab.assisted_query_password FROM t_account_1 ab) X" /> </rewrite-assertion> <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.cipher_amount AS amount, u.cipher_password AS password, o.certificate_number 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 o.certificate_number=u.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.certificate_number 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 o.certificate_number=u.certificate_number AND u.assisted_query_password=?" parameters="assisted_query_1" /> + <output sql="SELECT u.amount, u.password, o.certificate_number 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 o.certificate_number=u.certificate_number AND u.assisted_query_password=?" parameters="assisted_query_1" /> + <output sql="SELECT u.amount, u.password, o.certificate_number 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 o.certificate_number=u.certificate_number AND 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, 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.cipher_amount AS amount, u.cipher_password AS password, o.certificate_number 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 o.certificate_number=u.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.certificate_number 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 o.certificate_number=u.certificate_number AND u.assisted_query_password=?" parameters="assisted_query_1" /> + <output sql="SELECT u.amount, u.password, o.certificate_number 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 o.certificate_number=u.certificate_number AND u.assisted_query_password=?" parameters="assisted_query_1" /> + <output sql="SELECT u.amount, u.password, o.certificate_number 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 o.certificate_number=u.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"> <input sql="SELECT o.password FROM (SELECT a.password FROM t_account a) o" /> - <output sql="SELECT o.cipher_password AS password FROM (SELECT a.cipher_password, a.assisted_query_password FROM t_account_0 a) o" /> - <output sql="SELECT o.cipher_password AS password FROM (SELECT a.cipher_password, a.assisted_query_password FROM t_account_1 a) o" /> + <output sql="SELECT o.password FROM (SELECT a.cipher_password AS password, a.assisted_query_password FROM t_account_0 a) o" /> + <output sql="SELECT o.password FROM (SELECT a.cipher_password AS password, a.assisted_query_password FROM t_account_1 a) o" /> </rewrite-assertion> </rewrite-assertions>