This is an automated email from the ASF dual-hosted git repository.

JingsongLi 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 f498ab13fb [core] Skip surrogate code points in truncated string max 
(#10335)
f498ab13fb is described below

commit f498ab13fba2e46789784af9be5e7f7c57880b7a
Author: spancer <[email protected]>
AuthorDate: Sat Oct 3 17:03:41 2026 +0800

    [core] Skip surrogate code points in truncated string max (#10335)
---
 .../statistics/TruncateSimpleColStatsCollector.java   |  4 ++++
 .../statistics/SimpleColStatsCollectorTest.java       | 19 +++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git 
a/paimon-common/src/main/java/org/apache/paimon/statistics/TruncateSimpleColStatsCollector.java
 
b/paimon-common/src/main/java/org/apache/paimon/statistics/TruncateSimpleColStatsCollector.java
index fc8d9d8cc2..b135e0d9bb 100644
--- 
a/paimon-common/src/main/java/org/apache/paimon/statistics/TruncateSimpleColStatsCollector.java
+++ 
b/paimon-common/src/main/java/org/apache/paimon/statistics/TruncateSimpleColStatsCollector.java
@@ -157,6 +157,10 @@ public class TruncateSimpleColStatsCollector extends 
AbstractSimpleColStatsColle
                 // characters = i
                 int offsetByCodePoint = 
truncatedStringBuilder.offsetByCodePoints(0, i);
                 int nextCodePoint = 
truncatedStringBuilder.codePointAt(offsetByCodePoint) + 1;
+                if (nextCodePoint >= Character.MIN_SURROGATE
+                        && nextCodePoint <= Character.MAX_SURROGATE) {
+                    nextCodePoint = Character.MAX_SURROGATE + 1;
+                }
                 // No overflow
                 if (nextCodePoint != 0 && 
Character.isValidCodePoint(nextCodePoint)) {
                     truncatedStringBuilder.setLength(offsetByCodePoint);
diff --git 
a/paimon-common/src/test/java/org/apache/paimon/statistics/SimpleColStatsCollectorTest.java
 
b/paimon-common/src/test/java/org/apache/paimon/statistics/SimpleColStatsCollectorTest.java
index a1be45b0ba..543bf09a1a 100644
--- 
a/paimon-common/src/test/java/org/apache/paimon/statistics/SimpleColStatsCollectorTest.java
+++ 
b/paimon-common/src/test/java/org/apache/paimon/statistics/SimpleColStatsCollectorTest.java
@@ -174,6 +174,25 @@ public class SimpleColStatsCollectorTest {
         
assertThat(fieldStats.max()).isEqualTo(BinaryString.fromString("\uD83E\uDD19"));
     }
 
+    @Test
+    public void testTruncateMaxSkipsSurrogateCodePoints() {
+        String prefix = "0123456789abcde";
+        BinaryString value = BinaryString.fromString(prefix + "\uD7FFzz");
+        BinaryString laterValue = BinaryString.fromString(prefix + "A");
+        BinaryString expectedMax = BinaryString.fromString(prefix + "\uE000");
+
+        TruncateSimpleColStatsCollector collector = new 
TruncateSimpleColStatsCollector(16);
+        collector.collect(value, (Serializer) BinaryStringSerializer.INSTANCE);
+        collector.collect(laterValue, (Serializer) 
BinaryStringSerializer.INSTANCE);
+        SimpleColStats stats = collector.result();
+        assertThat(stats.max()).isEqualTo(expectedMax);
+        assertThat(((BinaryString) 
stats.max()).compareTo(value)).isGreaterThan(0);
+
+        SimpleColStats converted = collector.convert(new 
SimpleColStats(laterValue, value, 0L));
+        assertThat(converted.max()).isEqualTo(expectedMax);
+        assertThat(((BinaryString) 
converted.max()).compareTo(value)).isGreaterThan(0);
+    }
+
     @Test
     public void testTruncateCopied() {
         TruncateSimpleColStatsCollector collector = new 
TruncateSimpleColStatsCollector(16);

Reply via email to