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 b9a4671484 [core] Read expire_tags older_than as a wall clock, not as 
an instant (#9263)
b9a4671484 is described below

commit b9a467148459eb0e9c39b2dd0603a38cfd926ba0
Author: ZIHAN DAI <[email protected]>
AuthorDate: Thu Aug 20 12:22:09 2026 +1000

    [core] Read expire_tags older_than as a wall clock, not as an instant 
(#9263)
---
 .../paimon/flink/procedure/ExpireTagsProcedure.java    |  5 +----
 .../paimon/flink/procedure/ExpireTagsProcedure.java    |  5 +----
 .../paimon/flink/action/ExpireTagsActionTest.java      |  8 ++++----
 .../flink/procedure/ExpireTagsProcedureITCase.java     | 18 +++++++++---------
 .../paimon/spark/procedure/ExpireTagsProcedure.java    |  5 +----
 .../spark/procedure/ExpireTagsProcedureTest.scala      | 16 +++++++---------
 6 files changed, 23 insertions(+), 34 deletions(-)

diff --git 
a/paimon-flink/paimon-flink-1.18/src/main/java/org/apache/paimon/flink/procedure/ExpireTagsProcedure.java
 
b/paimon-flink/paimon-flink-1.18/src/main/java/org/apache/paimon/flink/procedure/ExpireTagsProcedure.java
index 037c4bb71d..6a3c2cc59c 100644
--- 
a/paimon-flink/paimon-flink-1.18/src/main/java/org/apache/paimon/flink/procedure/ExpireTagsProcedure.java
+++ 
b/paimon-flink/paimon-flink-1.18/src/main/java/org/apache/paimon/flink/procedure/ExpireTagsProcedure.java
@@ -29,7 +29,6 @@ import org.apache.flink.table.procedure.ProcedureContext;
 import java.time.LocalDateTime;
 import java.util.Collections;
 import java.util.List;
-import java.util.TimeZone;
 
 /** A procedure to expire tags by time. */
 public class ExpireTagsProcedure extends ProcedureBase {
@@ -51,9 +50,7 @@ public class ExpireTagsProcedure extends ProcedureBase {
         TagTimeExpire tagTimeExpire =
                 
fileStoreTable.store().newTagAutoManager(fileStoreTable).getTagTimeExpire();
         if (olderThanStr != null) {
-            LocalDateTime olderThanTime =
-                    DateTimeUtils.parseTimestampData(olderThanStr, 3, 
TimeZone.getDefault())
-                            .toLocalDateTime();
+            LocalDateTime olderThanTime = 
DateTimeUtils.toLocalDateTime(olderThanStr, 3);
             tagTimeExpire.withOlderThanTime(olderThanTime);
         }
         List<String> expired = tagTimeExpire.expire();
diff --git 
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/procedure/ExpireTagsProcedure.java
 
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/procedure/ExpireTagsProcedure.java
index 2c03cf31d1..9b0ca3af87 100644
--- 
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/procedure/ExpireTagsProcedure.java
+++ 
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/procedure/ExpireTagsProcedure.java
@@ -35,7 +35,6 @@ import javax.annotation.Nullable;
 import java.time.LocalDateTime;
 import java.util.Collections;
 import java.util.List;
-import java.util.TimeZone;
 
 /** A procedure to expire tags by time. */
 public class ExpireTagsProcedure extends ProcedureBase {
@@ -61,9 +60,7 @@ public class ExpireTagsProcedure extends ProcedureBase {
         TagTimeExpire tagTimeExpire =
                 
fileStoreTable.store().newTagAutoManager(fileStoreTable).getTagTimeExpire();
         if (olderThanStr != null) {
-            LocalDateTime olderThanTime =
-                    DateTimeUtils.parseTimestampData(olderThanStr, 3, 
TimeZone.getDefault())
-                            .toLocalDateTime();
+            LocalDateTime olderThanTime = 
DateTimeUtils.toLocalDateTime(olderThanStr, 3);
             tagTimeExpire.withOlderThanTime(olderThanTime);
         }
         List<String> expired = tagTimeExpire.expire();
diff --git 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/ExpireTagsActionTest.java
 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/ExpireTagsActionTest.java
index b07cf50816..5d711e822f 100644
--- 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/ExpireTagsActionTest.java
+++ 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/ExpireTagsActionTest.java
@@ -18,7 +18,6 @@
 
 package org.apache.paimon.flink.action;
 
-import org.apache.paimon.data.Timestamp;
 import org.apache.paimon.table.FileStoreTable;
 
 import org.junit.jupiter.api.BeforeEach;
@@ -29,6 +28,7 @@ import org.junit.jupiter.params.provider.ValueSource;
 
 import java.nio.file.Path;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.concurrent.ThreadLocalRandom;
 
 import static org.apache.paimon.flink.util.ReadWriteTableTestUtil.bEnv;
@@ -128,8 +128,8 @@ public class ExpireTagsActionTest extends ActionITCaseBase {
 
         // tag-3 as the base older_than time
         LocalDateTime olderThanTime = 
table.tagManager().getOrThrow("tag-3").getTagCreateTime();
-        java.sql.Timestamp timestamp =
-                new 
java.sql.Timestamp(Timestamp.fromLocalDateTime(olderThanTime).getMillisecond());
+        String timestamp =
+                DateTimeFormatter.ofPattern("yyyy-MM-dd 
HH:mm:ss.SSS").format(olderThanTime);
 
         createAction(
                         ExpireTagsAction.class,
@@ -141,7 +141,7 @@ public class ExpireTagsActionTest extends ActionITCaseBase {
                         "--table",
                         "T",
                         "--older_than",
-                        timestamp.toString(),
+                        timestamp,
                         "--force_start_flink_job",
                         Boolean.toString(forceStartFlinkJob))
                 .run();
diff --git 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/procedure/ExpireTagsProcedureITCase.java
 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/procedure/ExpireTagsProcedureITCase.java
index e44769e648..1c59fbbb5c 100644
--- 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/procedure/ExpireTagsProcedureITCase.java
+++ 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/procedure/ExpireTagsProcedureITCase.java
@@ -18,7 +18,6 @@
 
 package org.apache.paimon.flink.procedure;
 
-import org.apache.paimon.data.Timestamp;
 import org.apache.paimon.flink.CatalogITCaseBase;
 import org.apache.paimon.table.FileStoreTable;
 import org.apache.paimon.utils.SnapshotManager;
@@ -28,6 +27,7 @@ import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.List;
 import java.util.concurrent.ThreadLocalRandom;
 
@@ -106,13 +106,11 @@ public class ExpireTagsProcedureITCase extends 
CatalogITCaseBase {
         // tag-2 as the base older_than time.
         // tag-1 expired by its file creation time.
         LocalDateTime olderThanTime1 = 
table.tagManager().getOrThrow("tag-2").getTagCreateTime();
-        java.sql.Timestamp timestamp1 =
-                new java.sql.Timestamp(
-                        
Timestamp.fromLocalDateTime(olderThanTime1).getMillisecond());
+        String timestamp1 = WALL_CLOCK.format(olderThanTime1);
         assertThat(
                         sql(
                                 "CALL sys.expire_tags(`table` => 'default.T', 
older_than => '"
-                                        + timestamp1.toString()
+                                        + timestamp1
                                         + "')"))
                 .containsExactlyInAnyOrder(Row.of("tag-1"));
 
@@ -123,19 +121,21 @@ public class ExpireTagsProcedureITCase extends 
CatalogITCaseBase {
         // tag-4 as the base older_than time.
         // tag-2,tag-3,tag-5 expired, tag-5 reached its tagTimeRetained.
         LocalDateTime olderThanTime2 = 
table.tagManager().getOrThrow("tag-4").getTagCreateTime();
-        java.sql.Timestamp timestamp2 =
-                new java.sql.Timestamp(
-                        
Timestamp.fromLocalDateTime(olderThanTime2).getMillisecond());
+        String timestamp2 = WALL_CLOCK.format(olderThanTime2);
         assertThat(
                         sql(
                                 "CALL sys.expire_tags(`table` => 'default.T', 
older_than => '"
-                                        + timestamp2.toString()
+                                        + timestamp2
                                         + "')"))
                 .containsExactlyInAnyOrder(Row.of("tag-2"), Row.of("tag-3"), 
Row.of("tag-5"));
 
         assertThat(sql("select tag_name from 
`T$tags`")).containsExactly(Row.of("tag-4"));
     }
 
+    /** The plain wall clock a user types, as the documented example does. */
+    private static final DateTimeFormatter WALL_CLOCK =
+            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
+
     private void checkSnapshots(SnapshotManager sm, int earliest, int latest) 
throws IOException {
         assertThat(sm.snapshotCount()).isEqualTo(latest - earliest + 1);
         assertThat(sm.earliestSnapshotId()).isEqualTo(earliest);
diff --git 
a/paimon-spark/paimon-spark-common/src/main/java/org/apache/paimon/spark/procedure/ExpireTagsProcedure.java
 
b/paimon-spark/paimon-spark-common/src/main/java/org/apache/paimon/spark/procedure/ExpireTagsProcedure.java
index f8e685cf2e..3f36105f39 100644
--- 
a/paimon-spark/paimon-spark-common/src/main/java/org/apache/paimon/spark/procedure/ExpireTagsProcedure.java
+++ 
b/paimon-spark/paimon-spark-common/src/main/java/org/apache/paimon/spark/procedure/ExpireTagsProcedure.java
@@ -34,7 +34,6 @@ import org.apache.spark.unsafe.types.UTF8String;
 import java.time.LocalDateTime;
 import java.util.Collections;
 import java.util.List;
-import java.util.TimeZone;
 
 import static org.apache.spark.sql.types.DataTypes.StringType;
 
@@ -86,9 +85,7 @@ public class ExpireTagsProcedure extends BaseProcedure {
                                     .getTagTimeExpire();
                     if (olderThanStr != null) {
                         LocalDateTime olderThanTime =
-                                DateTimeUtils.parseTimestampData(
-                                                olderThanStr, 3, 
TimeZone.getDefault())
-                                        .toLocalDateTime();
+                                DateTimeUtils.toLocalDateTime(olderThanStr, 3);
                         tagTimeExpire.withOlderThanTime(olderThanTime);
                     }
                     List<String> expired = tagTimeExpire.expire();
diff --git 
a/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/procedure/ExpireTagsProcedureTest.scala
 
b/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/procedure/ExpireTagsProcedureTest.scala
index d1e1d3f52d..86019d856f 100644
--- 
a/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/procedure/ExpireTagsProcedureTest.scala
+++ 
b/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/procedure/ExpireTagsProcedureTest.scala
@@ -18,7 +18,6 @@
 
 package org.apache.paimon.spark.procedure;
 
-import org.apache.paimon.data.Timestamp
 import org.apache.paimon.spark.PaimonSparkTestBase
 import org.apache.paimon.utils.SnapshotManager
 
@@ -27,6 +26,9 @@ import org.assertj.core.api.Assertions.assertThat
 
 class ExpireTagsProcedureTest extends PaimonSparkTestBase {
 
+  /** The plain wall clock a user types, as the documented example does. */
+  private val WALL_CLOCK = 
java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
+
   test("Paimon procedure: expire tags that reached its timeRetained") {
     val tagTimeExpireEnabled = scala.util.Random.nextBoolean()
     spark.sql(s"""
@@ -100,11 +102,9 @@ class ExpireTagsProcedureTest extends PaimonSparkTestBase {
     // tag-2 as the base older_than time.
     // tag-1 expired by its file creation time.
     val olderThanTime1 = 
table.tagManager().getOrThrow("tag-2").getTagCreateTime
-    val timestamp1 =
-      new 
java.sql.Timestamp(Timestamp.fromLocalDateTime(olderThanTime1).getMillisecond)
+    val timestamp1 = WALL_CLOCK.format(olderThanTime1)
     checkAnswer(
-      spark.sql(
-        s"CALL paimon.sys.expire_tags(table => 'test.T', older_than => 
'${timestamp1.toString}')"),
+      spark.sql(s"CALL paimon.sys.expire_tags(table => 'test.T', older_than => 
'$timestamp1')"),
       Row("tag-1") :: Nil
     )
 
@@ -115,11 +115,9 @@ class ExpireTagsProcedureTest extends PaimonSparkTestBase {
     // tag-4 as the base older_than time.
     // tag-2,tag-3,tag-5 expired, tag-5 reached its tagTimeRetained.
     val olderThanTime2 = 
table.tagManager().getOrThrow("tag-4").getTagCreateTime
-    val timestamp2 =
-      new 
java.sql.Timestamp(Timestamp.fromLocalDateTime(olderThanTime2).getMillisecond)
+    val timestamp2 = WALL_CLOCK.format(olderThanTime2)
     checkAnswer(
-      spark.sql(
-        s"CALL paimon.sys.expire_tags(table => 'test.T', older_than => 
'${timestamp2.toString}')"),
+      spark.sql(s"CALL paimon.sys.expire_tags(table => 'test.T', older_than => 
'$timestamp2')"),
       Row("tag-2") :: Row("tag-3") :: Row("tag-5") :: Nil
     )
 

Reply via email to