You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by ze...@apache.org on 2026/06/08 19:06:22 UTC

(iceberg-go) branch main updated: fix(table): reject time64[ns] in partition literal extraction (#1115) (#1159)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 8d85415a fix(table): reject time64[ns] in partition literal extraction (#1115) (#1159)
8d85415a is described below

commit 8d85415a5f2ec0b7ee992cb663dfe56724b47b62
Author: Tanmay Rauth <t_...@apple.com>
AuthorDate: Tue Jun 9 00:36:16 2026 +0530

    fix(table): reject time64[ns] in partition literal extraction (#1115) (#1159)
    
    `getArrowValueAsIcebergLiteral` previously assumed every `*array.Time64`
    already held microseconds and ignored the Arrow `Time64Type.Unit`. This
    is unreachable today because the schema-conversion path in
    `arrow_utils.go` only accepts `time64[us]`, but the helper was still
    silently producing wrong partition keys if `time64[ns]` ever reached it.
    
    Inspect `Time64Type.Unit` and return `iceberg.ErrInvalidSchema` for any
    unit other than microseconds, mirroring the schema-conversion error. Add
    a focused unit test covering both the success and rejection paths.
    
    Closes https://github.com/apache/iceberg-go/issues/1115
---
 table/partitioned_fanout_writer.go      |  4 ++++
 table/partitioned_fanout_writer_test.go | 24 ++++++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/table/partitioned_fanout_writer.go b/table/partitioned_fanout_writer.go
index 0d0c5378..87ad78b4 100644
--- a/table/partitioned_fanout_writer.go
+++ b/table/partitioned_fanout_writer.go
@@ -390,6 +390,10 @@ func getArrowValueAsIcebergLiteral(column arrow.Array, row int, sourceType icebe
 
 		return iceberg.NewLiteral(iceberg.Date(arr.Value(row))), nil
 	case *array.Time64:
+		dt, ok := arr.DataType().(*arrow.Time64Type)
+		if !ok || dt.Unit != arrow.Microsecond {
+			return nil, fmt.Errorf("%w: unsupported arrow type for conversion - %s", iceberg.ErrInvalidSchema, arr.DataType())
+		}
 
 		return iceberg.NewLiteral(iceberg.Time(arr.Value(row))), nil
 	case *array.Timestamp:
diff --git a/table/partitioned_fanout_writer_test.go b/table/partitioned_fanout_writer_test.go
index ae29b76a..677f2152 100644
--- a/table/partitioned_fanout_writer_test.go
+++ b/table/partitioned_fanout_writer_test.go
@@ -585,3 +585,27 @@ func (s *FanoutWriterTestSuite) createComprehensiveTestRecord() arrow.RecordBatc
 
 	return bldr.NewRecordBatch()
 }
+
+func (s *FanoutWriterTestSuite) TestGetArrowValueAsIcebergLiteralTime64() {
+	// time64[us]: value passes through unchanged.
+	usBldr := array.NewTime64Builder(s.mem, &arrow.Time64Type{Unit: arrow.Microsecond})
+	defer usBldr.Release()
+	usBldr.Append(arrow.Time64(5_000_000))
+	usArr := usBldr.NewTime64Array()
+	defer usArr.Release()
+
+	lit, err := getArrowValueAsIcebergLiteral(usArr, 0, iceberg.PrimitiveTypes.Time)
+	s.Require().NoError(err)
+	s.Equal(iceberg.NewLiteral(iceberg.Time(5_000_000)), lit)
+
+	// time64[ns]: explicitly rejected to avoid silently producing wrong partition keys.
+	nsBldr := array.NewTime64Builder(s.mem, &arrow.Time64Type{Unit: arrow.Nanosecond})
+	defer nsBldr.Release()
+	nsBldr.Append(arrow.Time64(5_000_000_000))
+	nsArr := nsBldr.NewTime64Array()
+	defer nsArr.Release()
+
+	_, err = getArrowValueAsIcebergLiteral(nsArr, 0, iceberg.PrimitiveTypes.Time)
+	s.Require().ErrorIs(err, iceberg.ErrInvalidSchema)
+	s.Contains(err.Error(), "time64[ns]")
+}