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

kevinjqliu 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 44bf484e89 Spec: Clarify variant type classification and primitive 
type scoping (#16836)
44bf484e89 is described below

commit 44bf484e895f21d385bbf0c32363e2fd6b0f0db9
Author: Junwang Zhao <[email protected]>
AuthorDate: Sun Aug 2 00:05:19 2026 +0800

    Spec: Clarify variant type classification and primitive type scoping 
(#16836)
    
    This PR clarifies how the Iceberg specification classifies and references 
the `variant` type.
    
    - Clarifies that `variant` is a semi-structured type and is neither 
primitive nor nested.
    - Uses primitive-type scoping consistently when describing supported source 
types for identity and bucket transforms.
    - Applies the same terminology to the availability of `tight_bounds`.
    
    The previous wording explicitly excluded `variant` from constructs already 
scoped to primitive types, which could create ambiguity about how `variant` is 
classified. This is a specification clarification only and does not change 
format semantics or supported behavior.
---
 format/expressions-spec.md | 4 ++--
 format/spec.md             | 8 +++++---
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/format/expressions-spec.md b/format/expressions-spec.md
index 01aa7d8b35..2975648a25 100644
--- a/format/expressions-spec.md
+++ b/format/expressions-spec.md
@@ -223,7 +223,7 @@ All partition transforms produce `null` for a `null` input 
value.
 
 | Function name     | Description                                              
    | Source types                                                         | 
Result type |
 
|-------------------|--------------------------------------------------------------|----------------------------------------------------------------------|-------------|
-| `identity(value)` | Source value, unmodified                                 
    | Any primitive except for `geometry`, `geography`, and `variant`      | 
Source type |
+| `identity(value)` | Source value, unmodified                                 
    | Any primitive except for `geometry` and `geography` | Source type |
 | `year(value)`     | Extract a date or timestamp year, as years from 1970     
    | `date`, `timestamp`, `timestamptz`, `timestamp_ns`, `timestamptz_ns` | 
`int`       |
 | `month(value)`    | Extract a date or timestamp month, as months from 
1970-01-01 | `date`, `timestamp`, `timestamptz`, `timestamp_ns`, 
`timestamptz_ns` | `int`       |
 | `day(value)`      | Extract a date or timestamp day, as days from 1970-01-01 
    | `date`, `timestamp`, `timestamptz`, `timestamp_ns`, `timestamptz_ns` | 
`date`      |
@@ -235,7 +235,7 @@ Note that `year`, `month`, and `hour` transforms produce 
ordinal values and not
 
 | Parameterized function name | Description                                    
                       | Source types                                           
                                      | Result type |
 
|-----------------------------|-----------------------------------------------------------------------|----------------------------------------------------------------------------------------------|-------------|
-| `bucket(N, value)`          | Hash of value, mod `N` (see [table spec 
details][bucket-ref])         | Any primitive except for `geometry`, 
`geography`, `variant`, `boolean`, `float`, or `double` | `int`       |
+| `bucket(N, value)`          | Hash of value, mod `N` (see [table spec 
details][bucket-ref])         | Any primitive except for `geometry`, 
`geography`, `boolean`, `float`, or `double` | `int`       |
 | `truncate(W, value)`        | Value truncated to width `W` (see [table spec 
details][truncate-ref]) | `int`, `long`, `decimal`, `string`, `binary`          
                                       | Source type |
 
 [bucket-ref]: spec/#bucket-transform-details
diff --git a/format/spec.md b/format/spec.md
index ebb0125989..42be123524 100644
--- a/format/spec.md
+++ b/format/spec.md
@@ -228,7 +228,7 @@ When the `location` field is present in table metadata, it 
is used directly as t
 
 ### Schemas and Data Types
 
-A table's **schema** is a list of named columns. All data types are either 
primitives or nested types, which are maps, lists, or structs. A table schema 
is also a struct type.
+A table's **schema** is a list of named columns. Data types are primitive, 
nested, or semi-structured. Nested types are maps, lists, or structs. A table 
schema is also a struct type.
 
 For the representations of these types in Avro, ORC, and Parquet file formats, 
see Appendix A.
 
@@ -244,6 +244,8 @@ A **`map`** is a collection of key-value pairs with a key 
type and a value type.
 
 A **`variant`** is a value that stores semi-structured data. The structure and 
data types in a variant are not necessarily consistent across rows in a table 
or data file. The variant type and binary encoding are defined in the [Parquet 
project](https://github.com/apache/parquet-format/blob/master/VariantEncoding.md),
 with support currently available for V1. Support for Variant is added in 
Iceberg v3.
 
+As a semi-structured type, `variant` is neither a primitive type nor a nested 
type.
+
 Variants are similar to JSON with a wider set of primitive values including 
date, timestamp, timestamptz, binary, and decimals.
 
 Variant values may contain nested types:
@@ -567,7 +569,7 @@ Partition field IDs must be reused if an existing partition 
spec contains an equ
 
 | Transform name    | Description                                              
    | Source types                                                              
                                | Result type |
 
|-------------------|--------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------|-------------|
-| **`identity`**    | Source value, unmodified                                 
    | Any except for `geometry`, `geography`, and `variant`                     
                                | Source type |
+| **`identity`**    | Source value, unmodified                                 
    | Any primitive except for `geometry` and `geography` | Source type |
 | **`bucket[N]`**   | Hash of value, mod `N` (see below)                       
    | `int`, `long`, `decimal`, `date`, `time`, `timestamp`, `timestamptz`, 
`timestamp_ns`, `timestamptz_ns`, `string`, `uuid`, `fixed`, `binary` | `int`   
    |
 | **`truncate[W]`** | Value truncated to width `W` (see below)                 
    | `int`, `long`, `decimal`, `string`, `binary`                              
                                | Source type |
 | **`year`**        | Extract a date or timestamp year, as years from 1970     
    | `date`, `timestamp`, `timestamptz`, `timestamp_ns`, `timestamptz_ns`      
                                | `int`       |
@@ -818,7 +820,7 @@ Each stats struct holds statistics for one table field. It 
may contain the follo
 
|-------------|--------|---------------------------|---------------------------|-----------------------------------------------|-------------|
 | _optional_  | 1      | `lower_bound`             | Field type or `geo_lower` 
| all primitives or `variant`                   | Lower bound stored as the 
field's type, or `geo_lower` for geo types |
 | _optional_  | 2      | `upper_bound`             | Field type or `geo_upper` 
| all primitives or `variant`                   | Upper bound stored as the 
field's type, or `geo_upper` for geo types |
-| _optional_  | 3      | `tight_bounds`            | `boolean`                 
| all except `geometry`, `geography`, `variant` | When true, `lower_bound` and 
`upper_bound` must be equal to the min and max values |
+| _optional_  | 3      | `tight_bounds`            | `boolean`                 
| all primitives except for `geometry` and `geography` | When true, 
`lower_bound` and `upper_bound` must be equal to the min and max values |
 | _optional_  | 4      | `value_count`             | `long`                    
| all                                           | Number of values in the 
column (including null and NaN values) |
 | _optional_  | 5      | `null_value_count`        | `long`                    
| optional fields                               | Number of null values in the 
column |
 | _optional_  | 6      | `nan_value_count`         | `long`                    
| `float`, `double`                             | Number of NaN values in the 
column |

Reply via email to