Ruiqi Dong created CALCITE-7555:
-----------------------------------

             Summary: Sarg.compareTo() collapses semantically different search 
arguments that have different nullAs
                 Key: CALCITE-7555
                 URL: https://issues.apache.org/jira/browse/CALCITE-7555
             Project: Calcite
          Issue Type: Bug
          Components: core
    Affects Versions: 1.41.0
            Reporter: Ruiqi Dong


*Summary*
Sarg.compareTo() compares only the underlying rangeSet, while equals() and 
hashCode() also include nullAs. This means two search arguments over the same 
ranges but with different null semantics compare as equal in the natural 
ordering even though they are not equal as objects. Any sorted collection keyed 
on Sarg can therefore silently merge semantically different values.
 
*Affected code*
File: core/src/main/java/org/apache/calcite/util/Sarg.java
{code:java}
@Override public int compareTo(Sarg<C> o) {
  return RangeSets.compare(rangeSet, o.rangeSet);
}

@Override public int hashCode() {
  return RangeSets.hashCode(rangeSet) * 31 + nullAs.ordinal();
}

@Override public boolean equals(@Nullable Object o) {
  return o == this
      || o instanceof Sarg
      && nullAs == ((Sarg) o).nullAs
      && rangeSet.equals(((Sarg) o).rangeSet);
} {code}
 
*Reproducer*
Add the following test to 
core/src/test/java/org/apache/calcite/util/MtClawCalciteBugTest.jav
{code:java}
@Test void testSargNaturalOrderingKeepsDistinctNullSemantics() {
  final ImmutableRangeSet<Integer> singleton =
      ImmutableRangeSet.of(Range.singleton(1));
  final Sarg<Integer> unknown =
      Sarg.of(RexUnknownAs.UNKNOWN, singleton);
  final Sarg<Integer> falseSarg =
      Sarg.of(RexUnknownAs.FALSE, singleton);

  assertFalse(unknown.equals(falseSarg));

  final TreeSet<Sarg<Integer>> values = new TreeSet<>();
  values.add(unknown);
  values.add(falseSarg);

  assertThat(values, hasSize(2));
} {code}
Run:
{code:java}
./gradlew :core:test \
  --tests 
org.apache.calcite.util.MtClawCalciteBugTest.testSargNaturalOrderingKeepsDistinctNullSemantics
{code}
Observed behavior:
The test fails because the natural ordering collapses the two distinct Sarg 
values
{code:java}
Expected: a collection with size <2>
     but: collection size was <1> {code}
Expected behavior:
nullAs changes the meaning of a search argument. Two Sarg instances that differ 
in nullAs should not compare as the same element in sorted collections.
 
This is a semantic bug, not just a Comparable cleanliness issue. A Sarg is more 
than its range set. nullAs changes SQL three-valued semantics, but compareTo() 
ignores it completely and allows sorted collections to merge semantically 
different search arguments.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to