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")));
+  }
 }

Reply via email to