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 c331aeb983 [vortex] Fix predicate pushdown literals for DATE and 
second-precision TIMESTAMP (#9558)
c331aeb983 is described below

commit c331aeb98396409955a3e100133352550d03fdd1
Author: Eunbin Son <[email protected]>
AuthorDate: Thu Sep 3 17:24:03 2026 +0900

    [vortex] Fix predicate pushdown literals for DATE and second-precision 
TIMESTAMP (#9558)
---
 .../format/vortex/VortexPredicateConverter.java    |  8 ++-
 .../vortex/VortexPredicateConverterTest.java       | 63 ++++++++++++++++++++++
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git 
a/paimon-vortex/paimon-vortex-format/src/main/java/org/apache/paimon/format/vortex/VortexPredicateConverter.java
 
b/paimon-vortex/paimon-vortex-format/src/main/java/org/apache/paimon/format/vortex/VortexPredicateConverter.java
index e66f6cbece..d957daddfb 100644
--- 
a/paimon-vortex/paimon-vortex-format/src/main/java/org/apache/paimon/format/vortex/VortexPredicateConverter.java
+++ 
b/paimon-vortex/paimon-vortex-format/src/main/java/org/apache/paimon/format/vortex/VortexPredicateConverter.java
@@ -147,8 +147,9 @@ public class VortexPredicateConverter implements 
PredicateVisitor<Expression> {
             case SMALLINT:
                 return Expression.literal((Short) value);
             case INTEGER:
-            case DATE:
                 return Expression.literal((Integer) value);
+            case DATE:
+                return Expression.literalDate((Integer) value, 
Expression.TimeUnit.DAYS);
             case BIGINT:
                 return Expression.literal((Long) value);
             case FLOAT:
@@ -179,7 +180,10 @@ public class VortexPredicateConverter implements 
PredicateVisitor<Expression> {
 
     private static Expression toTimestampLiteral(
             Timestamp ts, int precision, @Nullable String timeZone) {
-        if (precision <= 3) {
+        if (precision == 0) {
+            return Expression.literalTimestamp(
+                    ts.getMillisecond() / 1000, Expression.TimeUnit.SECONDS, 
timeZone);
+        } else if (precision <= 3) {
             return Expression.literalTimestamp(
                     ts.getMillisecond(), Expression.TimeUnit.MILLISECONDS, 
timeZone);
         } else if (precision <= 6) {
diff --git 
a/paimon-vortex/paimon-vortex-format/src/test/java/org/apache/paimon/format/vortex/VortexPredicateConverterTest.java
 
b/paimon-vortex/paimon-vortex-format/src/test/java/org/apache/paimon/format/vortex/VortexPredicateConverterTest.java
index 59a46a0a51..b36860ae7d 100644
--- 
a/paimon-vortex/paimon-vortex-format/src/test/java/org/apache/paimon/format/vortex/VortexPredicateConverterTest.java
+++ 
b/paimon-vortex/paimon-vortex-format/src/test/java/org/apache/paimon/format/vortex/VortexPredicateConverterTest.java
@@ -361,6 +361,69 @@ public class VortexPredicateConverterTest {
         assertEquals(BinaryString.fromString("hello"), 
rows.get(0).getString(2));
     }
 
+    @Test
+    public void testDateSemantic(@TempDir java.nio.file.Path tempDir) throws 
Exception {
+        // f_date >= 20 (epoch day) should return rows with f_date=20,30
+        RowType dateRowType = RowType.builder().field("f_date", 
DataTypes.DATE()).build();
+        PredicateBuilder dateBuilder = new PredicateBuilder(dateRowType);
+        List<InternalRow> rows =
+                roundTrip(
+                        tempDir,
+                        dateRowType,
+                        new GenericRow[] {GenericRow.of(10), 
GenericRow.of(20), GenericRow.of(30)},
+                        
Collections.singletonList(dateBuilder.greaterOrEqual(0, 20)));
+        assertEquals(2, rows.size());
+        assertEquals(20, rows.get(0).getInt(0));
+        assertEquals(30, rows.get(1).getInt(0));
+    }
+
+    @Test
+    public void testTimestampSecondsPrecisionSemantic(@TempDir 
java.nio.file.Path tempDir)
+            throws Exception {
+        // f_ts >= 2000s should return rows with f_ts=2000s,3000s
+        RowType tsRowType = RowType.builder().field("f_ts", 
DataTypes.TIMESTAMP(0)).build();
+        PredicateBuilder tsBuilder = new PredicateBuilder(tsRowType);
+        List<InternalRow> rows =
+                roundTrip(
+                        tempDir,
+                        tsRowType,
+                        new GenericRow[] {
+                            
GenericRow.of(Timestamp.fromEpochMillis(1_000_000L)),
+                            
GenericRow.of(Timestamp.fromEpochMillis(2_000_000L)),
+                            
GenericRow.of(Timestamp.fromEpochMillis(3_000_000L))
+                        },
+                        Collections.singletonList(
+                                tsBuilder.greaterOrEqual(
+                                        0, 
Timestamp.fromEpochMillis(2_000_000L))));
+        assertEquals(2, rows.size());
+        assertEquals(2_000_000L, rows.get(0).getTimestamp(0, 
0).getMillisecond());
+        assertEquals(3_000_000L, rows.get(1).getTimestamp(0, 
0).getMillisecond());
+    }
+
+    @Test
+    public void testTimestampLtzSecondsPrecisionSemantic(@TempDir 
java.nio.file.Path tempDir)
+            throws Exception {
+        // f_ts_ltz == 2000s should return only the row with f_ts_ltz=2000s
+        RowType tsRowType =
+                RowType.builder()
+                        .field("f_ts_ltz", 
DataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(0))
+                        .build();
+        PredicateBuilder tsBuilder = new PredicateBuilder(tsRowType);
+        List<InternalRow> rows =
+                roundTrip(
+                        tempDir,
+                        tsRowType,
+                        new GenericRow[] {
+                            
GenericRow.of(Timestamp.fromEpochMillis(1_000_000L)),
+                            
GenericRow.of(Timestamp.fromEpochMillis(2_000_000L)),
+                            
GenericRow.of(Timestamp.fromEpochMillis(3_000_000L))
+                        },
+                        Collections.singletonList(
+                                tsBuilder.equal(0, 
Timestamp.fromEpochMillis(2_000_000L))));
+        assertEquals(1, rows.size());
+        assertEquals(2_000_000L, rows.get(0).getTimestamp(0, 
0).getMillisecond());
+    }
+
     private List<InternalRow> roundTrip(
             java.nio.file.Path tempDir,
             RowType rowType,

Reply via email to