You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ch...@apache.org on 2023/08/04 09:16:41 UTC
[shardingsphere] branch master updated: Enhance ExpressionProjection and SubqueryProjection getColumnName and getColumnLabel logic (#27918)
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 <du...@apache.org>
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`"));
}
}