This is an automated email from the ASF dual-hosted git repository.
mihaibudiu 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 b3b8d64d18 [CALCITE-7206] Avoid duplicate compare(Object, Object)
bridge method in the Enumerable merge join comparator
b3b8d64d18 is described below
commit b3b8d64d18cdf45fe0188a1f0198c84610091aba
Author: Anas Khan <[email protected]>
AuthorDate: Fri Jul 3 07:18:57 2026 +0530
[CALCITE-7206] Avoid duplicate compare(Object, Object) bridge method in the
Enumerable merge join comparator
PhysTypeImpl.generateComparator always appends a bridge
compare(Object, Object) method when EnumerableRules.BRIDGE_METHODS is
enabled. When the boxed row Java class is already Object (for example a
merge join key of type ANY, represented as a bare Object), the primary
compare method already has the signature compare(Object, Object), so the
bridge collapses to the same signature and the generated Comparator
declares two identical methods, which fails to compile with "Error while
compiling generated Java code".
Skip the bridge method when javaRowClass is Object, since the primary
method already satisfies the Comparator contract. The normal Object[] row
case is unchanged.
---
.../calcite/adapter/enumerable/PhysTypeImpl.java | 5 +++-
.../calcite/adapter/enumerable/PhysTypeTest.java | 33 ++++++++++++++++++++++
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git
a/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
b/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
index a44d4f69df..ce7d016a6c 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
@@ -499,7 +499,10 @@ private Expression generateComparator(RelCollation
collation,
ImmutableList.of(parameterV0, parameterV1),
body.toBlock()));
- if (EnumerableRules.BRIDGE_METHODS) {
+ // When javaRowClass is Object the primary compare method already has the
+ // signature compare(Object, Object), so a bridge method would be a
+ // duplicate and the generated Comparator would fail to compile.
+ if (EnumerableRules.BRIDGE_METHODS && javaRowClass != Object.class) {
final ParameterExpression parameterO0 =
Expressions.parameter(Object.class, "o0");
final ParameterExpression parameterO1 =
diff --git
a/core/src/test/java/org/apache/calcite/adapter/enumerable/PhysTypeTest.java
b/core/src/test/java/org/apache/calcite/adapter/enumerable/PhysTypeTest.java
index 494dc21a2a..ed61ad90fc 100644
--- a/core/src/test/java/org/apache/calcite/adapter/enumerable/PhysTypeTest.java
+++ b/core/src/test/java/org/apache/calcite/adapter/enumerable/PhysTypeTest.java
@@ -21,6 +21,8 @@
import org.apache.calcite.linq4j.Enumerable;
import org.apache.calcite.linq4j.tree.Expression;
import org.apache.calcite.linq4j.tree.Expressions;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.sql.type.SqlTypeName;
@@ -29,7 +31,9 @@
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
/**
* Test for {@link org.apache.calcite.adapter.enumerable.PhysTypeImpl}.
@@ -98,4 +102,33 @@ public final class PhysTypeTest {
+ ")";
assertThat(expected, is(Expressions.toString(e)));
}
+
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-7206">[CALCITE-7206]
+ * Duplicate 'compare' method in the Enumerable merge join comparator when
the
+ * row Java class is Object</a>.
+ *
+ * <p>When the row is a single column whose Java class is {@link Object} (for
+ * example a merge join key of type {@code ANY}), the primary
+ * {@code compare(Object, Object)} method and the generated bridge method
have
+ * the same signature, so the emitted {@link java.util.Comparator} must not
+ * declare the bridge method twice or it fails to compile. */
+ @Test void testMergeJoinComparatorWithObjectRowHasNoDuplicateBridge() {
+ final RelDataType rowType =
+ TYPE_FACTORY.createStructType(
+ ImmutableList.of(
+ TYPE_FACTORY.createSqlType(SqlTypeName.ANY)),
+ ImmutableList.of("anyField"));
+ final PhysType rowPhysType =
+ PhysTypeImpl.of(TYPE_FACTORY, rowType, JavaRowFormat.SCALAR, false);
+ final RelCollation collation = RelCollations.of(0);
+ final Expression comparator =
+ rowPhysType.generateMergeJoinComparator(collation);
+ final String generated = Expressions.toString(comparator);
+ // The primary compare method is still generated ...
+ assertThat(generated, containsString("public int compare(Object v0, Object
v1)"));
+ // ... but the bridge compare(Object o0, Object o1) would collide with it
and
+ // must therefore be omitted.
+ assertThat(generated, not(containsString("Object o0, Object o1")));
+ }
}