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

rubenql pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new d5b6b5c01f [CALCITE-6338] RelMdCollation#project can return an 
incomplete list of collations in the presence of aliasing
d5b6b5c01f is described below

commit d5b6b5c01ff17cac100a591a4cc4c9e83d4e1ace
Author: Ruben Quesada Lopez <rube...@gmail.com>
AuthorDate: Thu Mar 21 16:43:37 2024 +0000

    [CALCITE-6338] RelMdCollation#project can return an incomplete list of 
collations in the presence of aliasing
---
 .../calcite/rel/metadata/RelMdCollation.java       | 20 ++++++++---
 .../org/apache/calcite/test/RelMetadataTest.java   | 40 ++++++++++++++++++++++
 core/src/test/resources/sql/sub-query.iq           |  5 ++-
 3 files changed, 57 insertions(+), 8 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java 
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
index 7c107d39d6..9c728384f4 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
@@ -316,22 +316,32 @@ public class RelMdCollation
         targetsWithMonotonicity.put(project.i, 
call.getOperator().getMonotonicity(binding));
       }
     }
-    final List<RelFieldCollation> fieldCollations = new ArrayList<>();
+    List<List<RelFieldCollation>> fieldCollationsList = new ArrayList<>();
   loop:
     for (RelCollation ic : inputCollations) {
       if (ic.getFieldCollations().isEmpty()) {
         continue;
       }
-      fieldCollations.clear();
+      fieldCollationsList.clear();
+      fieldCollationsList.add(new ArrayList<>());
       for (RelFieldCollation ifc : ic.getFieldCollations()) {
         final Collection<Integer> integers = targets.get(ifc.getFieldIndex());
         if (integers.isEmpty()) {
           continue loop; // cannot do this collation
         }
-        fieldCollations.add(ifc.withFieldIndex(integers.iterator().next()));
+        fieldCollationsList = fieldCollationsList.stream()
+            .flatMap(fieldCollations -> integers.stream()
+                .map(integer -> {
+                  List<RelFieldCollation> newFieldCollations = new 
ArrayList<>(fieldCollations);
+                  newFieldCollations.add(ifc.withFieldIndex(integer));
+                  return newFieldCollations;
+                })).collect(Collectors.toList());
+      }
+      assert !fieldCollationsList.isEmpty();
+      for (List<RelFieldCollation> fieldCollations : fieldCollationsList) {
+        assert !fieldCollations.isEmpty();
+        collations.add(RelCollations.of(fieldCollations));
       }
-      assert !fieldCollations.isEmpty();
-      collations.add(RelCollations.of(fieldCollations));
     }
 
     final List<RelFieldCollation> fieldCollationsForRexCalls =
diff --git a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java 
b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
index db1f65c242..d9733486bd 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -1948,6 +1948,46 @@ public class RelMetadataTest {
     assertEquals("[[0]]", collations.toString());
   }
 
+  /**
+   * Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6338";>[CALCITE-6338]
+   * RelMdCollation#project can return an incomplete list of collations
+   * in the presence of aliasing</a>.
+   */
+  @Test void testCollationProjectAliasing() {
+    final RelBuilder builder = RelBuilderTest.createBuilder();
+    final RelNode relNode1 = builder
+        .scan("EMP")
+        .sort(2, 3)
+        .project(builder.field(0), builder.field(2), builder.field(2), 
builder.field(3))
+        .build();
+    checkCollationProjectAliasing(relNode1, "[[1, 3], [2, 3]]");
+    final RelNode relNode2 = builder
+        .scan("EMP")
+        .sort(0, 1)
+        .project(builder.field(0), builder.field(0), builder.field(1), 
builder.field(1))
+        .build();
+    checkCollationProjectAliasing(relNode2, "[[0, 2], [0, 3], [1, 2], [1, 
3]]");
+    final RelNode relNode3 = builder
+        .scan("EMP")
+        .sort(0, 1, 2)
+        .project(
+            builder.field(0), builder.field(0),
+            builder.field(1), builder.field(1), builder.field(1),
+            builder.field(2))
+        .build();
+    checkCollationProjectAliasing(relNode3,
+        "[[0, 2, 5], [0, 3, 5], [0, 4, 5], [1, 2, 5], [1, 3, 5], [1, 4, 5]]");
+  }
+
+  private void checkCollationProjectAliasing(RelNode relNode, String 
expectedCollation) {
+    final RelMetadataQuery mq = relNode.getCluster().getMetadataQuery();
+    assertThat(relNode, instanceOf(Project.class));
+    final ImmutableList<RelCollation> collations = mq.collations(relNode);
+    assertThat(collations, notNullValue());
+    assertEquals(expectedCollation, collations.toString());
+  }
+
   /** Unit test for
    * {@link org.apache.calcite.rel.metadata.RelMdCollation#project}
    * and other helper functions for deducing collations. */
diff --git a/core/src/test/resources/sql/sub-query.iq 
b/core/src/test/resources/sql/sub-query.iq
index 4d76b3fb6b..16cf991f13 100644
--- a/core/src/test/resources/sql/sub-query.iq
+++ b/core/src/test/resources/sql/sub-query.iq
@@ -2260,9 +2260,8 @@ EnumerableCalc(expr#0..5=[{inputs}], expr#6=[<>($t2, 
$t1)], expr#7=[1], expr#8=[
   EnumerableMergeJoin(condition=[=($0, $5)], joinType=[left])
     EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0])
       EnumerableTableScan(table=[[scott, EMP]])
-    EnumerableSort(sort0=[$4], dir0=[ASC])
-      EnumerableCalc(expr#0..7=[{inputs}], expr#8=[1:BIGINT], expr#9=[true], 
c=[$t8], d=[$t8], m=[$t0], trueLiteral=[$t9], EMPNO1=[$t0])
-        EnumerableTableScan(table=[[scott, EMP]])
+    EnumerableCalc(expr#0..7=[{inputs}], expr#8=[1:BIGINT], expr#9=[true], 
c=[$t8], d=[$t8], m=[$t0], trueLiteral=[$t9], EMPNO1=[$t0])
+      EnumerableTableScan(table=[[scott, EMP]])
 !plan
 +-------+
 | EMPNO |

Reply via email to