Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CALCITE-6338] RelMdCollation#project can return an incomplete list of collations in the presence of aliasing #3739

Merged
merged 1 commit into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -316,22 +316,32 @@ public static List<RelCollation> sort(RelCollation collation) {
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 =
Expand Down
40 changes: 40 additions & 0 deletions core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1948,6 +1948,46 @@ public String colType(MyRelMetadataQuery myRelMetadataQuery, RelNode rel, int co
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. */
Expand Down
5 changes: 2 additions & 3 deletions core/src/test/resources/sql/sub-query.iq
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
Loading