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 94a97255a0 [vortex] Do not push nanosecond timestamp literals that
overflow int64 (#9810)
94a97255a0 is described below
commit 94a97255a09bf66e6452cada22138073d5c167a4
Author: jackylee <[email protected]>
AuthorDate: Tue Sep 15 11:17:01 2026 +0800
[vortex] Do not push nanosecond timestamp literals that overflow int64
(#9810)
---
.../format/vortex/VortexPredicateConverter.java | 18 ++++++++++++++----
.../format/vortex/VortexPredicateConverterTest.java | 21 +++++++++++++++++++++
2 files changed, 35 insertions(+), 4 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 a4ec47aba5..baf315e86b 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
@@ -205,10 +205,20 @@ public class VortexPredicateConverter implements
PredicateVisitor<Expression> {
Expression.TimeUnit.MICROSECONDS,
timeZone);
} else {
- return Expression.literalTimestamp(
- ts.getMillisecond() * 1_000_000 +
ts.getNanoOfMillisecond(),
- Expression.TimeUnit.NANOSECONDS,
- timeZone);
+ // A TIMESTAMP value reaches year 9999, so nanoseconds since the
epoch are not
+ // representable as an int64 outside roughly [1677-09-21,
2262-04-11]. A wrapped bound
+ // silently excludes matching rows, so refuse to push the literal
down for the same
+ // reason as the grain checks above.
+ long nanos;
+ try {
+ nanos =
+ Math.addExact(
+ Math.multiplyExact(ts.getMillisecond(),
1_000_000L),
+ ts.getNanoOfMillisecond());
+ } catch (ArithmeticException e) {
+ return null;
+ }
+ return Expression.literalTimestamp(nanos,
Expression.TimeUnit.NANOSECONDS, timeZone);
}
}
}
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 63b2099a57..222e6bd0ce 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
@@ -494,6 +494,27 @@ public class VortexPredicateConverterTest {
assertEquals(1_500L, rows.get(0).getTimestamp(0, 0).getMillisecond());
}
+ @Test
+ public void testTimestampNanosOverflowingLiteralNotPushed(@TempDir
java.nio.file.Path tempDir)
+ throws Exception {
+ // epoch millis times 1_000_000 overflows int64 nanoseconds beyond
2262-04-11, and the
+ // wrapped bound landed before the epoch, so "< 9999-12-31" dropped
the epoch row
+ RowType tsRowType = RowType.builder().field("f_ts",
DataTypes.TIMESTAMP(9)).build();
+ PredicateBuilder tsBuilder = new PredicateBuilder(tsRowType);
+ List<Predicate> predicates =
+ Collections.singletonList(
+ tsBuilder.lessThan(0,
Timestamp.fromEpochMillis(253402214400000L)));
+ assertNull(VortexPredicateConverter.toVortexExpression(predicates));
+ List<InternalRow> rows =
+ roundTrip(
+ tempDir,
+ tsRowType,
+ new GenericRow[]
{GenericRow.of(Timestamp.fromEpochMillis(0L))},
+ predicates);
+ assertEquals(1, rows.size());
+ assertEquals(0L, rows.get(0).getTimestamp(0, 0).getMillisecond());
+ }
+
private List<InternalRow> roundTrip(
java.nio.file.Path tempDir,
RowType rowType,