This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new 77279da3a3 [core] Fix record comparator cache key for sort order
(#7222)
77279da3a3 is described below
commit 77279da3a3ef34f9ef9b49fac1181f45174967e2
Author: Liulietong <[email protected]>
AuthorDate: Mon Feb 9 11:00:54 2026 +0800
[core] Fix record comparator cache key for sort order (#7222)
## Problem
The cache key for `recordComparator` only considered the sort key types
but ignored the sort order (ascending/descending). This caused
comparators with different sort orders to share the same cached class,
leading to incorrect sorting behavior.
## Solution
Include `SortOrder` in the cache key generation to ensure each unique
sort order combination gets its own generated comparator class.
## Summary
- Include sort order in the codegen cache key for record comparators
- Add a regression test for ascending/descending comparator cache
collisions
## Testing
```bash
mvn -pl paimon-core -Dtest=CodeGenUtilsTest test
```
---
.../org/apache/paimon/codegen/CodeGenUtils.java | 23 ++++++++++++++++++----
.../apache/paimon/codegen/CodeGenUtilsTest.java | 18 +++++++++++++++++
2 files changed, 37 insertions(+), 4 deletions(-)
diff --git
a/paimon-core/src/main/java/org/apache/paimon/codegen/CodeGenUtils.java
b/paimon-core/src/main/java/org/apache/paimon/codegen/CodeGenUtils.java
index 18f8e628f2..5270f92462 100644
--- a/paimon-core/src/main/java/org/apache/paimon/codegen/CodeGenUtils.java
+++ b/paimon-core/src/main/java/org/apache/paimon/codegen/CodeGenUtils.java
@@ -80,6 +80,7 @@ public class CodeGenUtils {
RecordComparator.class,
inputTypes,
sortFields,
+ isAscendingOrder,
() ->
getCodeGenerator()
.generateRecordComparator(
@@ -103,7 +104,16 @@ public class CodeGenUtils {
List<DataType> fields,
int[] fieldsIndex,
Supplier<GeneratedClass<T>> supplier) {
- ClassKey classKey = new ClassKey(classType, fields, fieldsIndex);
+ return generate(classType, fields, fieldsIndex, null, supplier);
+ }
+
+ private static <T> T generate(
+ Class<?> classType,
+ List<DataType> fields,
+ int[] fieldsIndex,
+ Object extraKey,
+ Supplier<GeneratedClass<T>> supplier) {
+ ClassKey classKey = new ClassKey(classType, fields, fieldsIndex,
extraKey);
try {
Pair<Class<?>, Object[]> result =
@@ -153,10 +163,14 @@ public class CodeGenUtils {
private final int[] fieldsIndex;
- public ClassKey(Class<?> classType, List<DataType> fields, int[]
fieldsIndex) {
+ private final Object extraKey;
+
+ public ClassKey(
+ Class<?> classType, List<DataType> fields, int[] fieldsIndex,
Object extraKey) {
this.classType = classType;
this.fields = fields;
this.fieldsIndex = fieldsIndex;
+ this.extraKey = extraKey;
}
@Override
@@ -170,12 +184,13 @@ public class CodeGenUtils {
ClassKey classKey = (ClassKey) o;
return Objects.equals(classType, classKey.classType)
&& Objects.equals(fields, classKey.fields)
- && Arrays.equals(fieldsIndex, classKey.fieldsIndex);
+ && Arrays.equals(fieldsIndex, classKey.fieldsIndex)
+ && Objects.equals(extraKey, classKey.extraKey);
}
@Override
public int hashCode() {
- int result = Objects.hash(classType, fields);
+ int result = Objects.hash(classType, fields, extraKey);
result = 31 * result + Arrays.hashCode(fieldsIndex);
return result;
}
diff --git
a/paimon-core/src/test/java/org/apache/paimon/codegen/CodeGenUtilsTest.java
b/paimon-core/src/test/java/org/apache/paimon/codegen/CodeGenUtilsTest.java
index 5872750dd7..2d98596a28 100644
--- a/paimon-core/src/test/java/org/apache/paimon/codegen/CodeGenUtilsTest.java
+++ b/paimon-core/src/test/java/org/apache/paimon/codegen/CodeGenUtilsTest.java
@@ -18,6 +18,9 @@
package org.apache.paimon.codegen;
+import org.apache.paimon.data.BinaryString;
+import org.apache.paimon.data.GenericRow;
+import org.apache.paimon.data.InternalRow;
import org.apache.paimon.types.RowType;
import org.junit.jupiter.api.Test;
@@ -101,6 +104,21 @@ class CodeGenUtilsTest {
Arrays.asList(STRING(), INT(), DOUBLE()), new int[]
{0, 1, 2}, true));
}
+ @Test
+ public void testRecordComparatorOrderCacheMiss() {
+ RecordComparator ascending =
+ newRecordComparator(Arrays.asList(STRING(), INT()), new int[]
{0, 1}, true);
+ RecordComparator descending =
+ newRecordComparator(Arrays.asList(STRING(), INT()), new int[]
{0, 1}, false);
+
+ InternalRow row1 = GenericRow.of(BinaryString.fromString("a"), 1);
+ InternalRow row2 = GenericRow.of(BinaryString.fromString("b"), 1);
+
+ assertThat(ascending.compare(row1, row2)).isLessThan(0);
+ assertThat(descending.compare(row1, row2)).isGreaterThan(0);
+ assertThat(ascending.getClass()).isNotEqualTo(descending.getClass());
+ }
+
@Test
public void testRecordEqualiserCodegenCache() {
assertClassEquals(() -> newRecordEqualiser(Arrays.asList(STRING(),
INT())));