This is an automated email from the ASF dual-hosted git repository.

etudenhoefner pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/main by this push:
     new c9a2459465 Core: Support timestamp nanos in single value parser 
(#13487)
c9a2459465 is described below

commit c9a2459465e9c32c21d805f942f116f7db573751
Author: Yuya Ebihara <[email protected]>
AuthorDate: Fri Aug 8 19:32:33 2025 +0900

    Core: Support timestamp nanos in single value parser (#13487)
---
 .../java/org/apache/iceberg/SingleValueParser.java | 23 ++++++++++++++++++++++
 .../org/apache/iceberg/TestSingleValueParser.java  | 11 +++++++++++
 2 files changed, 34 insertions(+)

diff --git a/core/src/main/java/org/apache/iceberg/SingleValueParser.java 
b/core/src/main/java/org/apache/iceberg/SingleValueParser.java
index 3de6a0bcc6..c7f07ea1a2 100644
--- a/core/src/main/java/org/apache/iceberg/SingleValueParser.java
+++ b/core/src/main/java/org/apache/iceberg/SingleValueParser.java
@@ -140,6 +140,20 @@ public class SingleValueParser {
         } else {
           return DateTimeUtil.isoTimestampToMicros(defaultValue.textValue());
         }
+      case TIMESTAMP_NANO:
+        Preconditions.checkArgument(
+            defaultValue.isTextual(), "Cannot parse default as a %s value: 
%s", type, defaultValue);
+        if (((Types.TimestampNanoType) type).shouldAdjustToUTC()) {
+          String timestampTzNano = defaultValue.textValue();
+          Preconditions.checkArgument(
+              DateTimeUtil.isUTCTimestamptz(timestampTzNano),
+              "Cannot parse default as a %s value: %s, offset must be +00:00",
+              type,
+              defaultValue);
+          return DateTimeUtil.isoTimestamptzToNanos(timestampTzNano);
+        } else {
+          return DateTimeUtil.isoTimestampToNanos(defaultValue.textValue());
+        }
       case FIXED:
         Preconditions.checkArgument(
             defaultValue.isTextual(), "Cannot parse default as a %s value: 
%s", type, defaultValue);
@@ -289,6 +303,15 @@ public class SingleValueParser {
           generator.writeString(DateTimeUtil.microsToIsoTimestamp((Long) 
defaultValue));
         }
         break;
+      case TIMESTAMP_NANO:
+        Preconditions.checkArgument(
+            defaultValue instanceof Long, "Invalid default %s value: %s", 
type, defaultValue);
+        if (((Types.TimestampNanoType) type).shouldAdjustToUTC()) {
+          generator.writeString(DateTimeUtil.nanosToIsoTimestamptz((Long) 
defaultValue));
+        } else {
+          generator.writeString(DateTimeUtil.nanosToIsoTimestamp((Long) 
defaultValue));
+        }
+        break;
       case STRING:
         Preconditions.checkArgument(
             defaultValue instanceof CharSequence,
diff --git a/core/src/test/java/org/apache/iceberg/TestSingleValueParser.java 
b/core/src/test/java/org/apache/iceberg/TestSingleValueParser.java
index cc1578b0e0..92a5f3caff 100644
--- a/core/src/test/java/org/apache/iceberg/TestSingleValueParser.java
+++ b/core/src/test/java/org/apache/iceberg/TestSingleValueParser.java
@@ -46,6 +46,8 @@ public class TestSingleValueParser {
           {Types.TimeType.get(), "\"10:15:30\""},
           {Types.TimestampType.withoutZone(), "\"2007-12-03T10:15:30\""},
           {Types.TimestampType.withZone(), "\"2007-12-03T10:15:30+00:00\""},
+          {Types.TimestampNanoType.withoutZone(), 
"\"2007-12-03T10:15:30.123456789\""},
+          {Types.TimestampNanoType.withZone(), 
"\"2007-12-03T10:15:30.123456789+00:00\""},
           {Types.StringType.get(), "\"foo\""},
           {Types.UUIDType.get(), "\"eb26bdb1-a1d8-4aa6-990e-da940875492c\""},
           {Types.FixedType.ofLength(2), "\"111f\""},
@@ -157,6 +159,15 @@ public class TestSingleValueParser {
         .hasMessageStartingWith("Cannot parse default as a timestamptz value");
   }
 
+  @Test
+  public void testInvalidTimestamptzNano() {
+    Type expectedType = Types.TimestampNanoType.withZone();
+    String defaultJson = "\"2007-12-03T10:15:30+01:00\"";
+    assertThatThrownBy(() -> 
defaultValueParseAndUnParseRoundTrip(expectedType, defaultJson))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessageStartingWith("Cannot parse default as a timestamptz_ns 
value");
+  }
+
   // serialize to json and deserialize back should return the same result
   private static String defaultValueParseAndUnParseRoundTrip(Type type, String 
defaultValue) {
     Object javaDefaultValue = SingleValueParser.fromJson(type, defaultValue);

Reply via email to