You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by du...@apache.org on 2022/11/23 01:31:10 UTC

[shardingsphere] branch master updated: fix ShardingSphereResultSet bug. (#21768)

This is an automated email from the ASF dual-hosted git repository.

duanzhengqiang 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 ad95d407845 fix ShardingSphereResultSet bug. (#21768)
ad95d407845 is described below

commit ad95d407845e2b0dd5d81b24da20770d5c8fd1e9
Author: fang1025 <fa...@126.com>
AuthorDate: Wed Nov 23 09:31:03 2022 +0800

    fix ShardingSphereResultSet bug. (#21768)
    
    * fix ShardingSphereResultSet bug.
    
    * fix ShardingSphereResultSet bug.
    
    * fix ShardingSphereResultSet bug.
    
    * merge actualColumns and resultSetColumns to one field
    
    * test ShorthandProjection.resultSetColumns
    
    * fix ProjectionEngineTest&ShorthandProjection code style
    
    * fix ShorthandProjection code style
---
 .../select/projection/ProjectionsContext.java      |  6 ++--
 .../select/projection/engine/ProjectionEngine.java | 31 +++++++++++----------
 .../projection/impl/ShorthandProjection.java       | 25 +++++++++++++----
 .../projection/engine/ProjectionEngineTest.java    | 32 ++++++++++++++++++++++
 4 files changed, 71 insertions(+), 23 deletions(-)

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 97784c192e6..a5cc6c6cb4f 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
@@ -78,7 +78,7 @@ public final class ProjectionsContext {
         List<Projection> result = new ArrayList<>();
         for (Projection each : projections) {
             if (each instanceof ShorthandProjection) {
-                result.addAll(((ShorthandProjection) each).getActualColumns().values());
+                result.addAll(((ShorthandProjection) each).getResultSetColumns().values());
             } else if (!(each instanceof DerivedProjection)) {
                 result.add(each);
             }
@@ -107,8 +107,8 @@ public final class ProjectionsContext {
      */
     public Optional<String> findAlias(final String projectionName) {
         for (Projection each : projections) {
-            if (each instanceof ShorthandProjection && ((ShorthandProjection) each).getActualColumns().containsKey(projectionName.toLowerCase())) {
-                return ((ShorthandProjection) each).getActualColumns().get(projectionName.toLowerCase()).getAlias();
+            if (each instanceof ShorthandProjection && ((ShorthandProjection) each).getResultSetColumns().containsKey(projectionName.toLowerCase())) {
+                return ((ShorthandProjection) each).getResultSetColumns().get(projectionName.toLowerCase()).getAlias();
             }
             if (projectionName.equalsIgnoreCase(SQLUtil.getExactlyValue(each.getExpression()))) {
                 return each.getAlias();
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 8f144f0d97e..3709a34a869 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
@@ -115,11 +115,11 @@ public final class ProjectionEngine {
     
     private ShorthandProjection createProjection(final TableSegment table, final ShorthandProjectionSegment projectionSegment) {
         String owner = projectionSegment.getOwner().map(optional -> optional.getIdentifier().getValue()).orElse(null);
-        Collection<ColumnProjection> columnProjections = new LinkedHashSet<>();
-        columnProjections.addAll(getShorthandColumnsFromSimpleTableSegment(table, owner));
-        columnProjections.addAll(getShorthandColumnsFromSubqueryTableSegment(table));
-        columnProjections.addAll(getShorthandColumnsFromJoinTableSegment(table, projectionSegment));
-        return new ShorthandProjection(owner, columnProjections);
+        Collection<Projection> projections = new LinkedHashSet<>();
+        projections.addAll(getShorthandColumnsFromSimpleTableSegment(table, owner));
+        projections.addAll(getShorthandColumnsFromSubqueryTableSegment(table));
+        projections.addAll(getShorthandColumnsFromJoinTableSegment(table, projectionSegment));
+        return new ShorthandProjection(owner, projections);
     }
     
     private ColumnProjection createProjection(final ColumnProjectionSegment projectionSegment) {
@@ -171,34 +171,35 @@ public final class ProjectionEngine {
         return result;
     }
     
-    private Collection<ColumnProjection> getShorthandColumnsFromSubqueryTableSegment(final TableSegment table) {
+    private Collection<Projection> getShorthandColumnsFromSubqueryTableSegment(final TableSegment table) {
         if (!(table instanceof SubqueryTableSegment)) {
             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 getColumnProjections(projections);
+        return getResultSetProjections(projections);
     }
     
-    private Collection<ColumnProjection> getShorthandColumnsFromJoinTableSegment(final TableSegment table, final ProjectionSegment projectionSegment) {
+    private Collection<Projection> getShorthandColumnsFromJoinTableSegment(final TableSegment table, final ProjectionSegment projectionSegment) {
         if (!(table instanceof JoinTableSegment)) {
             return Collections.emptyList();
         }
         Collection<Projection> projections = new LinkedList<>();
         createProjection(((JoinTableSegment) table).getLeft(), projectionSegment).ifPresent(projections::add);
         createProjection(((JoinTableSegment) table).getRight(), projectionSegment).ifPresent(projections::add);
-        return getColumnProjections(projections);
+        return getResultSetProjections(projections);
     }
     
-    private Collection<ColumnProjection> getColumnProjections(final Collection<Projection> projections) {
-        Collection<ColumnProjection> result = new LinkedList<>();
+    private Collection<Projection> getResultSetProjections(final Collection<Projection> projections) {
+        Collection<Projection> result = new LinkedList<>();
         for (Projection each : projections) {
             if (each instanceof ColumnProjection) {
-                result.add((ColumnProjection) each);
-            }
-            if (each instanceof ShorthandProjection) {
-                result.addAll(((ShorthandProjection) each).getActualColumns().values());
+                result.add(each);
+            } else if (each instanceof ExpressionProjection) {
+                result.add(each);
+            } else if (each instanceof ShorthandProjection) {
+                result.addAll(((ShorthandProjection) each).getResultSetColumns().values());
             }
         }
         return result;
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 4be24043b54..44f70ca4a13 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
@@ -37,12 +37,12 @@ import java.util.Optional;
 public final class ShorthandProjection implements Projection {
     
     private final String owner;
-    
-    private final Map<String, ColumnProjection> actualColumns = new LinkedHashMap<>();
-    
-    public ShorthandProjection(final String owner, final Collection<ColumnProjection> columnProjections) {
+
+    private final Map<String, Projection> resultSetColumns = new LinkedHashMap<>();
+
+    public ShorthandProjection(final String owner, final Collection<Projection> projections) {
         this.owner = owner;
-        columnProjections.forEach(each -> actualColumns.put(each.getExpression().toLowerCase(), each));
+        projections.forEach(each -> resultSetColumns.put(each.getExpression().toLowerCase(), each));
     }
     
     @Override
@@ -68,4 +68,19 @@ public final class ShorthandProjection implements Projection {
     public Optional<String> getOwner() {
         return Optional.ofNullable(owner);
     }
+
+    /**
+     * get actualColumns, exclude ExpressionProjection.
+     *
+     * @return actualColumns
+     */
+    public Map<String, ColumnProjection> getActualColumns() {
+        Map<String, ColumnProjection> actualColumns = new LinkedHashMap<>();
+        for (Map.Entry<String, Projection> entry : resultSetColumns.entrySet()) {
+            if (entry.getValue() instanceof ColumnProjection) {
+                actualColumns.put(entry.getKey(), (ColumnProjection) entry.getValue());
+            }
+        }
+        return actualColumns;
+    }
 }
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 e63bacd51f4..8493ce69abe 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
@@ -32,18 +32,22 @@ import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationDistinctProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.dml.OracleSelectStatement;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -201,4 +205,32 @@ public final class ProjectionEngineTest {
         ShorthandProjectionSegment shorthandProjectionSegment = new ShorthandProjectionSegment(0, 0);
         new ProjectionEngine(DefaultDatabase.LOGIC_NAME, Collections.singletonMap(DefaultDatabase.LOGIC_NAME, schema), databaseType).createProjection(tableSegment, shorthandProjectionSegment);
     }
+
+    @Test
+    public void assertResultSetColumnsWithColumnProjectionAndExpressionProjectionOfShorthandProjection() {
+        ProjectionsSegment subQuerySegment = new ProjectionsSegment(0, 0);
+        ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("name"));
+        subQuerySegment.getProjections().add(new ColumnProjectionSegment(columnSegment));
+        ExpressionProjectionSegment expressionProjectionSegment = new ExpressionProjectionSegment(0, 0, "nvl(leave_date, '20991231')");
+        expressionProjectionSegment.setAlias(new AliasSegment(0, 0, new IdentifierValue("leave_date")));
+        subQuerySegment.getProjections().add(expressionProjectionSegment);
+        OracleSelectStatement subSelectStatement = new OracleSelectStatement();
+        subSelectStatement.setProjections(subQuerySegment);
+        subSelectStatement.setFrom(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("staff_info"))));
+        ShorthandProjectionSegment shorthandProjectionSegment = new ShorthandProjectionSegment(0, 0);
+        SubqueryTableSegment subqueryTableSegment = new SubqueryTableSegment(new SubquerySegment(0, 0, subSelectStatement));
+        Optional<Projection> actual = new ProjectionEngine(DefaultDatabase.LOGIC_NAME, Collections.singletonMap(DefaultDatabase.LOGIC_NAME, schema), databaseType)
+                .createProjection(subqueryTableSegment, shorthandProjectionSegment);
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), instanceOf(ShorthandProjection.class));
+        assertThat(((ShorthandProjection) actual.get()).getActualColumns().size(), is(1));
+        assertThat(((ShorthandProjection) actual.get()).getResultSetColumns().size(), is(2));
+        Map<String, ColumnProjection> actualColumns = new LinkedHashMap<>();
+        actualColumns.put("name", new ColumnProjection(null, "name", null));
+        assertThat(((ShorthandProjection) actual.get()).getActualColumns(), is(actualColumns));
+        Map<String, Projection> resultSetColumns = new LinkedHashMap<>();
+        resultSetColumns.put("name", new ColumnProjection(null, "name", null));
+        resultSetColumns.put("nvl(leave_date, '20991231')", new ExpressionProjection("nvl(leave_date, '20991231')", "leave_date"));
+        assertThat(((ShorthandProjection) actual.get()).getResultSetColumns(), is(resultSetColumns));
+    }
 }