This is an automated email from the ASF dual-hosted git repository.
chengzhang 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 3298333af39 Enhance ExpressionProjection and SubqueryProjection
getColumnName and getColumnLabel logic (#27918)
3298333af39 is described below
commit 3298333af39e6560a49dcd2b98a78a31cfbcdfbf
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Fri Aug 4 17:16:34 2023 +0800
Enhance ExpressionProjection and SubqueryProjection getColumnName and
getColumnLabel logic (#27918)
---
.../select/projection/engine/ProjectionEngine.java | 4 +--
.../projection/impl/ExpressionProjection.java | 15 ++++++++--
.../select/projection/impl/SubqueryProjection.java | 17 +++++++----
.../select/projection/util/ProjectionUtils.java | 35 +++++++++++++++++++++-
.../select/projection/ProjectionsContextTest.java | 8 +++--
.../generic/SubstitutableColumnNameTokenTest.java | 11 ++++---
6 files changed, 72 insertions(+), 18 deletions(-)
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/engine/ProjectionEngine.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/engine/ProjectionEngine.java
index 4746fa90a86..472f7f60ba4 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/engine/ProjectionEngine.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/engine/ProjectionEngine.java
@@ -97,7 +97,7 @@ public final class ProjectionEngine {
private SubqueryProjection createProjection(final TableSegment table,
final SubqueryProjectionSegment projectionSegment) {
Projection subqueryProjection = createProjection(table,
projectionSegment.getSubquery().getSelect().getProjections().getProjections().iterator().next())
.orElseThrow(() -> new IllegalArgumentException("Subquery
projection must have at least one projection column."));
- return new SubqueryProjection(projectionSegment.getText(),
subqueryProjection, projectionSegment.getAlias().orElse(null), databaseType);
+ return new SubqueryProjection(projectionSegment, subqueryProjection,
projectionSegment.getAlias().orElse(null), databaseType);
}
private ShorthandProjection createProjection(final TableSegment table,
final ShorthandProjectionSegment projectionSegment) {
@@ -117,7 +117,7 @@ public final class ProjectionEngine {
}
private ExpressionProjection createProjection(final
ExpressionProjectionSegment projectionSegment) {
- return new ExpressionProjection(projectionSegment.getText(),
projectionSegment.getAlias().orElse(null));
+ return new ExpressionProjection(projectionSegment,
projectionSegment.getAlias().orElse(null), databaseType);
}
private AggregationDistinctProjection createProjection(final
AggregationDistinctProjectionSegment projectionSegment) {
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/impl/ExpressionProjection.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/impl/ExpressionProjection.java
index e441dc535b8..9c0b1aca4a2 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/impl/ExpressionProjection.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/impl/ExpressionProjection.java
@@ -22,6 +22,9 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
+import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.util.ProjectionUtils;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
import java.util.Optional;
@@ -35,10 +38,12 @@ import java.util.Optional;
@ToString
public final class ExpressionProjection implements Projection {
- private final String expression;
+ private final ExpressionProjectionSegment expressionSegment;
private final IdentifierValue alias;
+ private final DatabaseType databaseType;
+
@Override
public String getColumnName() {
return getColumnLabel();
@@ -46,7 +51,13 @@ public final class ExpressionProjection implements
Projection {
@Override
public String getColumnLabel() {
- return getAlias().map(IdentifierValue::getValue).orElse(expression);
+ return getAlias().isPresent() ?
ProjectionUtils.getColumnLabelFromAlias(getAlias().get(), databaseType)
+ :
ProjectionUtils.getColumnNameFromExpression(expressionSegment.getText(),
databaseType);
+ }
+
+ @Override
+ public String getExpression() {
+ return expressionSegment.getText();
}
@Override
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/impl/SubqueryProjection.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/impl/SubqueryProjection.java
index 6a5c883678f..3c39a567297 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/impl/SubqueryProjection.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/impl/SubqueryProjection.java
@@ -22,8 +22,10 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
-import org.apache.shardingsphere.infra.database.oracle.type.OracleDatabaseType;
+import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.util.ProjectionUtils;
import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
+import org.apache.shardingsphere.infra.database.oracle.type.OracleDatabaseType;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
import java.util.Optional;
@@ -37,7 +39,7 @@ import java.util.Optional;
@ToString
public final class SubqueryProjection implements Projection {
- private final String expression;
+ private final SubqueryProjectionSegment subquerySegment;
private final Projection projection;
@@ -52,7 +54,7 @@ public final class SubqueryProjection implements Projection {
@Override
public String getColumnLabel() {
- return getAlias().map(IdentifierValue::getValue).orElse(expression);
+ return getAlias().isPresent() ?
ProjectionUtils.getColumnLabelFromAlias(getAlias().get(), databaseType) :
ProjectionUtils.getColumnNameFromSubquery(subquerySegment, databaseType);
}
@Override
@@ -62,8 +64,13 @@ public final class SubqueryProjection implements Projection {
private Optional<IdentifierValue> buildDefaultAlias(final DatabaseType
databaseType) {
if (databaseType instanceof OracleDatabaseType) {
- return Optional.of(new IdentifierValue(expression.replace(" ",
"").toUpperCase()));
+ return Optional.of(new
IdentifierValue(subquerySegment.getText().replace(" ", "").toUpperCase()));
}
- return Optional.of(new IdentifierValue(expression));
+ return Optional.of(new IdentifierValue(subquerySegment.getText()));
+ }
+
+ @Override
+ public String getExpression() {
+ return subquerySegment.getText();
}
}
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/util/ProjectionUtils.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/util/ProjectionUtils.java
index dba2a93224d..59cabcca66f 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/util/ProjectionUtils.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/util/ProjectionUtils.java
@@ -19,11 +19,12 @@ package
org.apache.shardingsphere.infra.binder.context.segment.select.projection
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
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.opengauss.type.OpenGaussDatabaseType;
import org.apache.shardingsphere.infra.database.oracle.type.OracleDatabaseType;
import
org.apache.shardingsphere.infra.database.postgresql.type.PostgreSQLDatabaseType;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
/**
@@ -84,4 +85,36 @@ public final class ProjectionUtils {
}
return functionExpression;
}
+
+ /**
+ * Get column name from expression.
+ *
+ * @param expression expression
+ * @param databaseType database type
+ * @return column name
+ */
+ public static String getColumnNameFromExpression(final String expression,
final DatabaseType databaseType) {
+ if (databaseType instanceof PostgreSQLDatabaseType || databaseType
instanceof OpenGaussDatabaseType) {
+ return "?column?";
+ }
+ if (databaseType instanceof OracleDatabaseType) {
+ return expression.replace(" ", "").toUpperCase();
+ }
+ return expression;
+ }
+
+ /**
+ * Get column name from subquery segment.
+ *
+ * @param subquerySegment subquery segment
+ * @param databaseType database type
+ * @return column name
+ */
+ public static String getColumnNameFromSubquery(final
SubqueryProjectionSegment subquerySegment, final DatabaseType databaseType) {
+ // TODO support postgresql subquery projection
+ if (databaseType instanceof OracleDatabaseType) {
+ return subquerySegment.getText().replace(" ", "").toUpperCase();
+ }
+ return subquerySegment.getText();
+ }
}
diff --git
a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/ProjectionsContextTest.java
b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/ProjectionsContextTest.java
index 50dd9872be8..8ad09136e9b 100644
---
a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/ProjectionsContextTest.java
+++
b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/projection/ProjectionsContextTest.java
@@ -24,7 +24,9 @@ import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ExpressionProjection;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ShorthandProjection;
import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
+import org.apache.shardingsphere.infra.database.mysql.type.MySQLDatabaseType;
import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
import org.junit.jupiter.api.Test;
@@ -150,9 +152,11 @@ class ProjectionsContextTest {
@Test
void assertIsContainsLastInsertIdProjection() {
- ProjectionsContext lastInsertIdProjection = new ProjectionsContext(0,
0, false, Collections.singletonList(new
ExpressionProjection("LAST_INSERT_ID()", new IdentifierValue("id"))));
+ ProjectionsContext lastInsertIdProjection = new ProjectionsContext(0,
0, false,
+ Collections.singletonList(new ExpressionProjection(new
ExpressionProjectionSegment(0, 0, "LAST_INSERT_ID()"), new
IdentifierValue("id"), new MySQLDatabaseType())));
assertTrue(lastInsertIdProjection.isContainsLastInsertIdProjection());
- ProjectionsContext maxProjection = new ProjectionsContext(0, 0, false,
Collections.singletonList(new ExpressionProjection("MAX(id)", new
IdentifierValue("max"))));
+ ProjectionsContext maxProjection = new ProjectionsContext(0, 0, false,
+ Collections.singletonList(new ExpressionProjection(new
ExpressionProjectionSegment(0, 0, "MAX(id)"), new IdentifierValue("max"), new
MySQLDatabaseType())));
assertFalse(maxProjection.isContainsLastInsertIdProjection());
}
}
diff --git
a/infra/rewrite/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameTokenTest.java
b/infra/rewrite/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameTokenTest.java
index 86a27173d78..3aee39b4c57 100644
---
a/infra/rewrite/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameTokenTest.java
+++
b/infra/rewrite/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameTokenTest.java
@@ -20,10 +20,10 @@ package
org.apache.shardingsphere.infra.rewrite.sql.token.pojo.generic;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ColumnProjection;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.SubqueryProjection;
+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.route.context.RouteUnit;
-import
org.apache.shardingsphere.infra.database.core.metadata.database.enums.QuoteCharacter;
-import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
import org.junit.jupiter.api.Test;
@@ -64,9 +64,8 @@ class SubstitutableColumnNameTokenTest {
void assertToStringWithSubqueryProjection() {
Collection<Projection> projections = Arrays.asList(new
ColumnProjection(new IdentifierValue("temp", QuoteCharacter.BACK_QUOTE),
new IdentifierValue("id", QuoteCharacter.BACK_QUOTE), new
IdentifierValue("id", QuoteCharacter.BACK_QUOTE), mock(DatabaseType.class)),
- new SubqueryProjection("(SELECT name FROM t_order)", new
ColumnProjection(null, "name", null, mock(DatabaseType.class)), new
IdentifierValue("name"),
- TypedSPILoader.getService(DatabaseType.class,
"Oracle")));
- assertThat(new SubstitutableColumnNameToken(0, 1, projections,
QuoteCharacter.BACK_QUOTE).toString(mock(RouteUnit.class)),
- is("`temp`.`id` AS `id`, `name`"));
+ new SubqueryProjection(new SubqueryProjectionSegment(null,
"(SELECT name FROM t_order)"), new ColumnProjection(null, "name", null,
mock(DatabaseType.class)),
+ new IdentifierValue("name"),
mock(DatabaseType.class)));
+ assertThat(new SubstitutableColumnNameToken(0, 1, projections,
QuoteCharacter.BACK_QUOTE).toString(mock(RouteUnit.class)), is("`temp`.`id` AS
`id`, `name`"));
}
}