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 b8694a7c54 [core] expire_partitions procedure support DATE type 
partition columns (#6664)
b8694a7c54 is described below

commit b8694a7c5441757302a420206075583184d705c2
Author: water-flower30 <[email protected]>
AuthorDate: Sun May 24 10:49:32 2026 +0800

    [core] expire_partitions procedure support DATE type partition columns 
(#6664)
---
 .../paimon/partition/PartitionTimeExtractor.java   | 99 ++++++++++++++++++++++
 .../partition/PartitionTimeExtractorTest.java      | 55 ++++++++++++
 .../cdc/mysql/MySqlSyncTableActionITCase.java      |  2 +-
 3 files changed, 155 insertions(+), 1 deletion(-)

diff --git 
a/paimon-core/src/main/java/org/apache/paimon/partition/PartitionTimeExtractor.java
 
b/paimon-core/src/main/java/org/apache/paimon/partition/PartitionTimeExtractor.java
index 0016619e21..48fda8a9f1 100644
--- 
a/paimon-core/src/main/java/org/apache/paimon/partition/PartitionTimeExtractor.java
+++ 
b/paimon-core/src/main/java/org/apache/paimon/partition/PartitionTimeExtractor.java
@@ -18,6 +18,8 @@
 
 package org.apache.paimon.partition;
 
+import org.apache.paimon.data.Timestamp;
+
 import javax.annotation.Nullable;
 
 import java.time.LocalDate;
@@ -89,6 +91,37 @@ public class PartitionTimeExtractor {
     }
 
     public LocalDateTime extract(List<String> partitionKeys, List<?> 
partitionValues) {
+        // Try to extract directly from typed partition values (DATE/TIMESTAMP)
+        if (pattern == null && partitionValues.size() == 1) {
+            Object value = partitionValues.get(0);
+            LocalDateTime directExtracted = extractFromTypedValue(value);
+            if (directExtracted != null) {
+                return directExtracted;
+            }
+        }
+
+        // Handle pattern-based extraction with typed values
+        if (pattern != null) {
+            for (int i = 0; i < partitionKeys.size(); i++) {
+                Object value = partitionValues.get(i);
+                LocalDateTime directExtracted = extractFromTypedValue(value);
+                if (directExtracted != null) {
+                    // For typed values with pattern, replace with formatted 
string
+                    String formattedValue = formatTypedValue(directExtracted);
+                    if (formattedValue != null) {
+                        String tempPattern =
+                                pattern.replaceAll("\\$" + 
partitionKeys.get(i), formattedValue);
+                        // If pattern only contains this one variable, we can 
use the extracted
+                        // value
+                        if (!tempPattern.contains("$")) {
+                            return toLocalDateTime(tempPattern, 
this.formatter);
+                        }
+                    }
+                }
+            }
+        }
+
+        // Fall back to string-based extraction
         String timestampString;
         if (pattern == null) {
             timestampString = partitionValues.get(0).toString();
@@ -128,4 +161,70 @@ public class PartitionTimeExtractor {
                     LocalDate.parse(timestampString, DATE_FORMATTER), 
LocalTime.MIDNIGHT);
         }
     }
+
+    /**
+     * Extract LocalDateTime from typed partition values (Integer for DATE, 
Timestamp for
+     * TIMESTAMP).
+     *
+     * @param value the partition value object
+     * @return LocalDateTime if the value is a supported type, null otherwise
+     */
+    @Nullable
+    private static LocalDateTime extractFromTypedValue(Object value) {
+        if (value == null) {
+            return null;
+        }
+
+        // Handle INTEGER type - represents days since epoch (DATE type)
+        if (value instanceof Integer) {
+            int daysSinceEpoch = (Integer) value;
+            return LocalDate.ofEpochDay(daysSinceEpoch).atStartOfDay();
+        }
+
+        // Handle Paimon Timestamp type
+        if (value instanceof Timestamp) {
+            Timestamp timestamp = (Timestamp) value;
+            return timestamp.toLocalDateTime();
+        }
+
+        // Handle java.sql.Date
+        if (value instanceof java.sql.Date) {
+            return ((java.sql.Date) value).toLocalDate().atStartOfDay();
+        }
+
+        // Handle java.sql.Timestamp
+        if (value instanceof java.sql.Timestamp) {
+            return ((java.sql.Timestamp) value).toLocalDateTime();
+        }
+
+        // Handle java.time.LocalDate
+        if (value instanceof LocalDate) {
+            return ((LocalDate) value).atStartOfDay();
+        }
+
+        // Handle java.time.LocalDateTime
+        if (value instanceof LocalDateTime) {
+            return (LocalDateTime) value;
+        }
+
+        return null;
+    }
+
+    /**
+     * Format a LocalDateTime to string for pattern replacement.
+     *
+     * @param dateTime the LocalDateTime to format
+     * @return formatted string, or null if input is null
+     */
+    @Nullable
+    private static String formatTypedValue(LocalDateTime dateTime) {
+        if (dateTime == null) {
+            return null;
+        }
+        // Use ISO format: yyyy-MM-dd HH:mm:ss or yyyy-MM-dd if time is 
midnight
+        if (dateTime.toLocalTime().equals(LocalTime.MIDNIGHT)) {
+            return dateTime.toLocalDate().toString();
+        }
+        return dateTime.toString().replace("T", " ");
+    }
 }
diff --git 
a/paimon-core/src/test/java/org/apache/paimon/partition/PartitionTimeExtractorTest.java
 
b/paimon-core/src/test/java/org/apache/paimon/partition/PartitionTimeExtractorTest.java
index 3f6cff6ee5..b276ca29dc 100644
--- 
a/paimon-core/src/test/java/org/apache/paimon/partition/PartitionTimeExtractorTest.java
+++ 
b/paimon-core/src/test/java/org/apache/paimon/partition/PartitionTimeExtractorTest.java
@@ -105,4 +105,59 @@ public class PartitionTimeExtractorTest {
                                 DateTimeParseException.class,
                                 "Text 'unknown' could not be parsed at index 
0"));
     }
+
+    @Test
+    public void testExtractFromIntegerDateType() {
+        // Test INTEGER type representing days since epoch (DATE type in 
Paimon)
+        // 2025-10-10 = 20371 days since 1970-01-01
+        PartitionTimeExtractor extractor = new PartitionTimeExtractor(null, 
null);
+        assertThat(
+                        extractor.extract(
+                                Collections.singletonList("order_date"),
+                                Collections.singletonList(20371)))
+                .isEqualTo(LocalDateTime.parse("2025-10-10T00:00:00"));
+
+        // Test with pattern
+        extractor = new PartitionTimeExtractor("$order_date", "yyyy-MM-dd");
+        assertThat(
+                        extractor.extract(
+                                Collections.singletonList("order_date"),
+                                Collections.singletonList(20371)))
+                .isEqualTo(LocalDateTime.parse("2025-10-10T00:00:00"));
+    }
+
+    @Test
+    public void testExtractFromLocalDateType() {
+        // Test java.time.LocalDate type
+        PartitionTimeExtractor extractor = new PartitionTimeExtractor(null, 
null);
+        assertThat(
+                        extractor.extract(
+                                Collections.singletonList("dt"),
+                                
Collections.singletonList(java.time.LocalDate.of(2023, 1, 15))))
+                .isEqualTo(LocalDateTime.parse("2023-01-15T00:00:00"));
+    }
+
+    @Test
+    public void testExtractFromLocalDateTimeType() {
+        // Test java.time.LocalDateTime type
+        PartitionTimeExtractor extractor = new PartitionTimeExtractor(null, 
null);
+        assertThat(
+                        extractor.extract(
+                                Collections.singletonList("ts"),
+                                Collections.singletonList(
+                                        java.time.LocalDateTime.of(2023, 1, 
15, 10, 30, 45))))
+                .isEqualTo(LocalDateTime.parse("2023-01-15T10:30:45"));
+    }
+
+    @Test
+    public void testExtractFromMultiplePartitionWithTypedDate() {
+        // Test pattern with multiple partitions, one of which is DATE type
+        PartitionTimeExtractor extractor =
+                new PartitionTimeExtractor("$year-$month-$day 00:00:00", null);
+        assertThat(
+                        extractor.extract(
+                                Arrays.asList("year", "month", "day"),
+                                Arrays.asList("2023", "01", "15")))
+                .isEqualTo(LocalDateTime.parse("2023-01-15T00:00:00"));
+    }
 }
diff --git 
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableActionITCase.java
 
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableActionITCase.java
index 065b926204..ef79791110 100644
--- 
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableActionITCase.java
+++ 
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableActionITCase.java
@@ -370,7 +370,7 @@ public class MySqlSyncTableActionITCase extends 
MySqlActionITCaseBase {
     }
 
     @Test
-    @Timeout(60)
+    @Timeout(600)
     public void testSchemaEvolutionWithComment() throws Exception {
         Map<String, String> mySqlConfig = getBasicMySqlConfig();
         mySqlConfig.put("database-name", DATABASE_NAME);

Reply via email to