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 1a1ac57330 [core] Introduce truncatedString for representations of 
large collections (#7000)
1a1ac57330 is described below

commit 1a1ac57330c1860916328975c36188b2208129f1
Author: Zouxxyy <[email protected]>
AuthorDate: Mon Jan 12 16:48:25 2026 +0800

    [core] Introduce truncatedString for representations of large collections 
(#7000)
---
 .../java/org/apache/paimon/utils/StringUtils.java  | 46 +++++++++++
 .../org/apache/paimon/predicate/LeafPredicate.java |  8 +-
 .../apache/paimon/predicate/PredicateBuilder.java  |  2 +-
 .../org/apache/paimon/predicate/PredicateTest.java | 13 +++
 .../org/apache/paimon/utils/StringUtilsTest.java   | 95 ++++++++++++++++++++++
 5 files changed, 160 insertions(+), 4 deletions(-)

diff --git a/paimon-api/src/main/java/org/apache/paimon/utils/StringUtils.java 
b/paimon-api/src/main/java/org/apache/paimon/utils/StringUtils.java
index e20151f35e..75f9cd2aab 100644
--- a/paimon-api/src/main/java/org/apache/paimon/utils/StringUtils.java
+++ b/paimon-api/src/main/java/org/apache/paimon/utils/StringUtils.java
@@ -19,6 +19,7 @@
 package org.apache.paimon.utils;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
@@ -45,6 +46,9 @@ public class StringUtils {
     /** The empty String {@code ""}. */
     public static final String EMPTY = "";
 
+    /** Default maximum number of fields for truncated string representation. 
*/
+    public static final int DEFAULT_MAX_FIELDS = 25;
+
     /**
      * Checks if the string is null, empty, or contains only whitespace 
characters. A whitespace
      * character is defined via {@link Character#isWhitespace(char)}.
@@ -562,4 +566,46 @@ public class StringUtils {
     public static boolean isCloseBracket(char c) {
         return c == ']' || c == '}' || c == ')';
     }
+
+    /**
+     * Converts a sequence to a string with truncation if it exceeds the 
maximum number of fields.
+     * This is useful for limiting the size of string representations of large 
collections.
+     *
+     * @param lst the collection to convert to string
+     * @param start the prefix string
+     * @param sep the separator between elements
+     * @param end the suffix string
+     * @param maxFields the maximum number of fields to include before 
truncation
+     * @return the truncated string representation
+     */
+    public static String truncatedString(
+            Collection<?> lst, String start, String sep, String end, int 
maxFields) {
+        boolean truncated = lst.size() > maxFields;
+        int numFields = truncated ? Math.max(0, maxFields - 1) : lst.size();
+
+        StringBuilder builder = new StringBuilder();
+        builder.append(start);
+
+        Iterator<?> iterator = lst.iterator();
+        for (int i = 0; i < numFields; i++) {
+            if (i > 0) {
+                builder.append(sep);
+            }
+            builder.append(iterator.next());
+        }
+
+        if (truncated) {
+            builder.append(sep)
+                    .append("... ")
+                    .append(lst.size() - numFields)
+                    .append(" more fields");
+        }
+
+        builder.append(end);
+        return builder.toString();
+    }
+
+    public static String truncatedString(Collection<?> lst, String start, 
String sep, String end) {
+        return truncatedString(lst, start, sep, end, DEFAULT_MAX_FIELDS);
+    }
 }
diff --git 
a/paimon-common/src/main/java/org/apache/paimon/predicate/LeafPredicate.java 
b/paimon-common/src/main/java/org/apache/paimon/predicate/LeafPredicate.java
index 6be9449556..3ea68121c3 100644
--- a/paimon-common/src/main/java/org/apache/paimon/predicate/LeafPredicate.java
+++ b/paimon-common/src/main/java/org/apache/paimon/predicate/LeafPredicate.java
@@ -26,6 +26,7 @@ import org.apache.paimon.data.serializer.NullableSerializer;
 import org.apache.paimon.io.DataInputViewStreamWrapper;
 import org.apache.paimon.io.DataOutputViewStreamWrapper;
 import org.apache.paimon.types.DataType;
+import org.apache.paimon.utils.StringUtils;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -119,12 +120,13 @@ public class LeafPredicate extends TransformPredicate {
     @Override
     public String toString() {
         String literalsStr;
-        if (literals == null || literals.isEmpty()) {
+        int literalsSize = literals == null ? 0 : literals.size();
+        if (literalsSize == 0) {
             literalsStr = "";
-        } else if (literals.size() == 1) {
+        } else if (literalsSize == 1) {
             literalsStr = Objects.toString(literals.get(0));
         } else {
-            literalsStr = literals.toString();
+            literalsStr = StringUtils.truncatedString(literals, "[", ", ", 
"]");
         }
         return literalsStr.isEmpty()
                 ? function + "(" + fieldName() + ")"
diff --git 
a/paimon-common/src/main/java/org/apache/paimon/predicate/PredicateBuilder.java 
b/paimon-common/src/main/java/org/apache/paimon/predicate/PredicateBuilder.java
index 3e88a58b17..58634f3edf 100644
--- 
a/paimon-common/src/main/java/org/apache/paimon/predicate/PredicateBuilder.java
+++ 
b/paimon-common/src/main/java/org/apache/paimon/predicate/PredicateBuilder.java
@@ -197,7 +197,7 @@ public class PredicateBuilder {
     public Predicate in(int idx, List<Object> literals) {
         // In the IN predicate, 20 literals are critical for performance.
         // If there are more than 20 literals, the performance will decrease.
-        if (literals.size() > 20 || literals.size() == 0) {
+        if (literals.size() > 20 || literals.isEmpty()) {
             DataField field = rowType.getFields().get(idx);
             return new LeafPredicate(In.INSTANCE, field.type(), idx, 
field.name(), literals);
         }
diff --git 
a/paimon-common/src/test/java/org/apache/paimon/predicate/PredicateTest.java 
b/paimon-common/src/test/java/org/apache/paimon/predicate/PredicateTest.java
index 5e011c6e7f..e8ad446387 100644
--- a/paimon-common/src/test/java/org/apache/paimon/predicate/PredicateTest.java
+++ b/paimon-common/src/test/java/org/apache/paimon/predicate/PredicateTest.java
@@ -712,4 +712,17 @@ public class PredicateTest {
                 .isEqualTo(
                         "NotIn(f0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 
14, 15, 16, 17, 18, 19, 20, 21])");
     }
+
+    @Test
+    public void testPredicateToStringWithManyFields() {
+        PredicateBuilder builder = new PredicateBuilder(RowType.of(new 
IntType()));
+        List<Object> literals = new ArrayList<>();
+        for (int i = 1; i <= 100; i++) {
+            literals.add(i);
+        }
+        Predicate p = builder.in(0, literals);
+        assertThat(p.toString())
+                .isEqualTo(
+                        "In(f0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, ... 76 more fields])");
+    }
 }
diff --git 
a/paimon-common/src/test/java/org/apache/paimon/utils/StringUtilsTest.java 
b/paimon-common/src/test/java/org/apache/paimon/utils/StringUtilsTest.java
index 10b56a97b7..b281812a13 100644
--- a/paimon-common/src/test/java/org/apache/paimon/utils/StringUtilsTest.java
+++ b/paimon-common/src/test/java/org/apache/paimon/utils/StringUtilsTest.java
@@ -411,6 +411,101 @@ class StringUtilsTest {
         }
     }
 
+    @Nested
+    class TruncatedStringTests {
+
+        @Test
+        void testTruncatedStringWithinMaxFields() {
+            List<String> items = Arrays.asList("a", "b", "c");
+            String result = StringUtils.truncatedString(items, "[", ", ", "]", 
5);
+            assertThat(result).isEqualTo("[a, b, c]");
+        }
+
+        @Test
+        void testTruncatedStringExactlyMaxFields() {
+            List<String> items = Arrays.asList("a", "b", "c");
+            String result = StringUtils.truncatedString(items, "[", ", ", "]", 
3);
+            assertThat(result).isEqualTo("[a, b, c]");
+        }
+
+        @Test
+        void testTruncatedStringExceedsMaxFields() {
+            List<String> items = Arrays.asList("a", "b", "c", "d", "e");
+            String result = StringUtils.truncatedString(items, "[", ", ", "]", 
3);
+            assertThat(result).isEqualTo("[a, b, ... 3 more fields]");
+        }
+
+        @Test
+        void testTruncatedStringExceedsMaxFieldsWithSeparator() {
+            List<Integer> items = Arrays.asList(1, 2, 3, 4, 5, 6);
+            String result = StringUtils.truncatedString(items, "(", "-", ")", 
4);
+            assertThat(result).isEqualTo("(1-2-3-... 3 more fields)");
+        }
+
+        @Test
+        void testTruncatedStringEmptyCollection() {
+            List<String> items = Arrays.asList();
+            String result = StringUtils.truncatedString(items, "[", ", ", "]", 
3);
+            assertThat(result).isEqualTo("[]");
+        }
+
+        @Test
+        void testTruncatedStringSingleElement() {
+            List<String> items = Arrays.asList("only");
+            String result = StringUtils.truncatedString(items, "[", ", ", "]", 
5);
+            assertThat(result).isEqualTo("[only]");
+        }
+
+        @Test
+        void testTruncatedStringMaxFieldsZero() {
+            List<String> items = Arrays.asList("a", "b", "c");
+            String result = StringUtils.truncatedString(items, "[", ", ", "]", 
0);
+            assertThat(result).isEqualTo("[, ... 3 more fields]");
+        }
+
+        @Test
+        void testTruncatedStringMaxFieldsOne() {
+            List<String> items = Arrays.asList("a", "b", "c", "d");
+            String result = StringUtils.truncatedString(items, "[", ", ", "]", 
1);
+            assertThat(result).isEqualTo("[, ... 4 more fields]");
+        }
+
+        @Test
+        void testTruncatedStringLargeCollection() {
+            List<Integer> items = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+            String result = StringUtils.truncatedString(items, "{", ", ", "}", 
5);
+            assertThat(result).isEqualTo("{1, 2, 3, 4, ... 6 more fields}");
+        }
+
+        @Test
+        void testTruncatedStringWithEmptyStrings() {
+            List<String> items = Arrays.asList("", "a", "", "b", "");
+            String result = StringUtils.truncatedString(items, "[", "|", "]", 
3);
+            assertThat(result).isEqualTo("[|a|... 3 more fields]");
+        }
+
+        @Test
+        void testTruncatedStringWithNullElements() {
+            List<String> items = Arrays.asList("a", null, "b", "c");
+            String result = StringUtils.truncatedString(items, "[", ", ", "]", 
3);
+            assertThat(result).isEqualTo("[a, null, ... 2 more fields]");
+        }
+
+        @Test
+        void testTruncatedStringWithCustomDelimiters() {
+            List<String> items = Arrays.asList("apple", "banana", "cherry", 
"date");
+            String result = StringUtils.truncatedString(items, "<", " | ", 
">", 3);
+            assertThat(result).isEqualTo("<apple | banana | ... 2 more 
fields>");
+        }
+
+        @Test
+        void testTruncatedStringWithEmptyDelimiters() {
+            List<String> items = Arrays.asList("a", "b", "c");
+            String result = StringUtils.truncatedString(items, "", "", "", 5);
+            assertThat(result).isEqualTo("abc");
+        }
+    }
+
     @Nested
     class EdgeCaseTests {
 

Reply via email to