Skip to content

Commit 96b33cf

Browse files
committed
Omit zero-millis fractional in resolved date-math timestamps
The previous {@code "yyyy-MM-dd HH:mm:ss.SSSSSSSSS"} format always emitted a 9-digit fractional component, which Calcite's TIMESTAMP literal parser rejected with IllegalArgumentException on {@code yyyy-MM-dd HH:mm:ss.000000000}-shape inputs. Round at millisecond precision and emit the {@code .SSS} suffix only when non-zero so whole-second values (epoch-millis ending in {@code 000}, {@code "now"} resolved on an exact-second boundary) match the canonical PPL form the analyzer accepts. Fixes {@code testSearchWithNumericTimeRange} which previously failed with {@code IllegalArgumentException: "2025-08-01 03:47:41."} after the visitor resolved {@code latest=1754020061} (whole-second millis-since-epoch) to a {@code .000}-suffixed literal. Signed-off-by: Kai Huang <ahkcs@amazon.com>
1 parent 52ffeb8 commit 96b33cf

1 file changed

Lines changed: 9 additions & 1 deletion

File tree

core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,16 @@ private static Optional<UnresolvedExpression> tryResolveOpenSearchDateMath(
515515
} else {
516516
return Optional.empty();
517517
}
518+
// PPL TIMESTAMP literals downstream are parsed by Calcite, which accepts
519+
// {@code yyyy-MM-dd HH:mm:ss} or {@code yyyy-MM-dd HH:mm:ss.SSS}. Round at
520+
// millisecond precision; emit a fractional component only when non-zero so a
521+
// whole-second value matches the canonical PPL form (the analyzer rejects
522+
// {@code yyyy-MM-dd HH:mm:ss.000}-shape literals with a trailing-zero parse
523+
// error).
524+
long millis = result.getEpochSecond() * 1000 + result.getNano() / 1_000_000;
525+
String pattern = (millis % 1000 == 0) ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd HH:mm:ss.SSS";
518526
String formatted =
519-
java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS")
527+
java.time.format.DateTimeFormatter.ofPattern(pattern)
520528
.withZone(java.time.ZoneOffset.UTC)
521529
.format(result);
522530
return Optional.of(AstDSL.timestampLiteral(formatted));

0 commit comments

Comments
 (0)