szehon-ho commented on code in PR #16972:
URL: https://github.com/apache/iceberg/pull/16972#discussion_r3484567562


##########
format/spec.md:
##########
@@ -345,6 +346,33 @@ For example, a struct column `point` with fields `x` 
(default 0) and `y` (defaul
 
 Default values are attributes of fields in schemas and serialized with fields 
in the JSON format. See [Appendix C](#appendix-c-json-serialization).
 
+#### Collations
+
+A `string` field may carry a **collation**, an attribute that changes how the 
field's values are compared and ordered without changing how they are stored. 
Collations enable case-insensitive, accent-insensitive, and locale-aware 
comparison and sorting. A collation only affects comparison: the stored value 
is returned unchanged (a value written as `'appLE'` is read back as `'appLE'`).
+
+A field's collation is stored as a `collation` attribute on the field (see 
[Appendix C](#appendix-c-json-serialization)). The attribute is allowed only on 
`string` fields. If a field has no `collation` attribute, comparison defaults 
to UTF-8 byte order, which is the behavior of all prior versions.
+
+A collation is identified by a provider-qualified name of the form 
`<provider>.<name>`, for example `icu.en_US-ci`. The provider names the library 
that defines the collation (`icu` for collations defined by the [Unicode 
Collation Algorithm](https://unicode.org/reports/tr10/) over 
[CLDR](https://cldr.unicode.org/) locale data; other providers may define 
engine-specific collations such as case-folding variants). The name selects a 
locale and optional modifiers for case sensitivity (`ci`/`cs`), accent 
sensitivity (`ai`/`as`), trimming, and case folding. The reserved name `utf8` 
denotes UTF-8 byte-order comparison.
+
+The schema stores the collation **name without a version**, so any engine that 
supports the collation can read the table. UCA, DUCET, CLDR, and ICU collation 
orders are [not stable across 
versions](https://unicode.org/reports/tr10/#Non-Goals), so collation-aware 
metrics carry the implementation version they were produced under (see below) 
and a reader uses them only when it can produce the same order.
+
+##### Collation Bounds
+
+Because a collation can reorder values (for example `'a' < 'B'` under a 
case-insensitive collation, but `'a' > 'B'` in byte order), the byte-order 
`lower_bounds` and `upper_bounds` cannot be used to evaluate predicates on a 
collated column. Collation-aware bounds are stored separately in 
`data_file.collation_bounds`, a map from column id to a list of 
`collation_bound` structs:
+
+| Field id, name | Type | Description |
+|----------------|------|-------------|
+| **`151 collation`** | `string` | Collation the bounds were produced for, 
e.g. `icu.en_US-ci` |
+| **`152 version`** | `string` | Collation implementation version the bounds 
were selected under |
+| **`153 lower_bound`** | `binary` | Minimum value under the collation order, 
serialized as the original value (Appendix D) |
+| **`154 upper_bound`** | `binary` | Maximum value under the collation order, 
serialized as the original value (Appendix D) |
+
+Bounds store the **original values** that are the minimum and maximum under 
the collation order, not collation sort keys (sort keys are not stable across 
implementation versions). The same single-value serialization and truncation 
rules as `lower_bounds`/`upper_bounds` apply, except that when truncating an 
upper bound, the appended successor must be the next value **in collation 
order**. A column may have more than one entry, one per collation version, so a 
file can serve readers pinned to different versions during an upgrade.
+
+**Writers** must continue to write the byte-order 
`lower_bounds`/`upper_bounds` for collated columns (so collation-unaware 
readers stay correct). A writer should additionally write `collation_bounds` 
when it supports the column's collation, tagging each entry with the collation 
and the exact implementation version used. A writer that does not support the 
collation or version must not write `collation_bounds` for that column.

Review Comment:
   in iceberg, lower_bounds and upper_bounds are optional, so 'must' is too 
strong here.



##########
format/spec.md:
##########
@@ -345,6 +346,33 @@ For example, a struct column `point` with fields `x` 
(default 0) and `y` (defaul
 
 Default values are attributes of fields in schemas and serialized with fields 
in the JSON format. See [Appendix C](#appendix-c-json-serialization).
 
+#### Collations
+
+A `string` field may carry a **collation**, an attribute that changes how the 
field's values are compared and ordered without changing how they are stored. 
Collations enable case-insensitive, accent-insensitive, and locale-aware 
comparison and sorting. A collation only affects comparison: the stored value 
is returned unchanged (a value written as `'appLE'` is read back as `'appLE'`).
+
+A field's collation is stored as a `collation` attribute on the field (see 
[Appendix C](#appendix-c-json-serialization)). The attribute is allowed only on 
`string` fields. If a field has no `collation` attribute, comparison defaults 
to UTF-8 byte order, which is the behavior of all prior versions.
+
+A collation is identified by a provider-qualified name of the form 
`<provider>.<name>`, for example `icu.en_US-ci`. The provider names the library 
that defines the collation (`icu` for collations defined by the [Unicode 
Collation Algorithm](https://unicode.org/reports/tr10/) over 
[CLDR](https://cldr.unicode.org/) locale data; other providers may define 
engine-specific collations such as case-folding variants). The name selects a 
locale and optional modifiers for case sensitivity (`ci`/`cs`), accent 
sensitivity (`ai`/`as`), trimming, and case folding. The reserved name `utf8` 
denotes UTF-8 byte-order comparison.

Review Comment:
   is it missing and end parens (after locale data)



##########
format/spec.md:
##########
@@ -54,6 +54,7 @@ Version 3 of the Iceberg spec extends data types and existing 
metadata structure
 * Row Lineage tracking
 * Binary deletion vectors
 * Table encryption keys
+* Collations for string types

Review Comment:
   V3 spec is already formally adopted , should we put it in v4?



##########
format/spec.md:
##########
@@ -345,6 +346,33 @@ For example, a struct column `point` with fields `x` 
(default 0) and `y` (defaul
 
 Default values are attributes of fields in schemas and serialized with fields 
in the JSON format. See [Appendix C](#appendix-c-json-serialization).
 
+#### Collations
+
+A `string` field may carry a **collation**, an attribute that changes how the 
field's values are compared and ordered without changing how they are stored. 
Collations enable case-insensitive, accent-insensitive, and locale-aware 
comparison and sorting. A collation only affects comparison: the stored value 
is returned unchanged (a value written as `'appLE'` is read back as `'appLE'`).
+
+A field's collation is stored as a `collation` attribute on the field (see 
[Appendix C](#appendix-c-json-serialization)). The attribute is allowed only on 
`string` fields. If a field has no `collation` attribute, comparison defaults 
to UTF-8 byte order, which is the behavior of all prior versions.
+
+A collation is identified by a provider-qualified name of the form 
`<provider>.<name>`, for example `icu.en_US-ci`. The provider names the library 
that defines the collation (`icu` for collations defined by the [Unicode 
Collation Algorithm](https://unicode.org/reports/tr10/) over 
[CLDR](https://cldr.unicode.org/) locale data; other providers may define 
engine-specific collations such as case-folding variants). The name selects a 
locale and optional modifiers for case sensitivity (`ci`/`cs`), accent 
sensitivity (`ai`/`as`), trimming, and case folding. The reserved name `utf8` 
denotes UTF-8 byte-order comparison.
+
+The schema stores the collation **name without a version**, so any engine that 
supports the collation can read the table. UCA, DUCET, CLDR, and ICU collation 
orders are [not stable across 
versions](https://unicode.org/reports/tr10/#Non-Goals), so collation-aware 
metrics carry the implementation version they were produced under (see below) 
and a reader uses them only when it can produce the same order.
+
+##### Collation Bounds
+
+Because a collation can reorder values (for example `'a' < 'B'` under a 
case-insensitive collation, but `'a' > 'B'` in byte order), the byte-order 
`lower_bounds` and `upper_bounds` cannot be used to evaluate predicates on a 
collated column. Collation-aware bounds are stored separately in 
`data_file.collation_bounds`, a map from column id to a list of 
`collation_bound` structs:
+
+| Field id, name | Type | Description |
+|----------------|------|-------------|
+| **`151 collation`** | `string` | Collation the bounds were produced for, 
e.g. `icu.en_US-ci` |
+| **`152 version`** | `string` | Collation implementation version the bounds 
were selected under |
+| **`153 lower_bound`** | `binary` | Minimum value under the collation order, 
serialized as the original value (Appendix D) |
+| **`154 upper_bound`** | `binary` | Maximum value under the collation order, 
serialized as the original value (Appendix D) |
+
+Bounds store the **original values** that are the minimum and maximum under 
the collation order, not collation sort keys (sort keys are not stable across 
implementation versions). The same single-value serialization and truncation 
rules as `lower_bounds`/`upper_bounds` apply, except that when truncating an 
upper bound, the appended successor must be the next value **in collation 
order**. A column may have more than one entry, one per collation version, so a 
file can serve readers pinned to different versions during an upgrade.
+
+**Writers** must continue to write the byte-order 
`lower_bounds`/`upper_bounds` for collated columns (so collation-unaware 
readers stay correct). A writer should additionally write `collation_bounds` 
when it supports the column's collation, tagging each entry with the collation 
and the exact implementation version used. A writer that does not support the 
collation or version must not write `collation_bounds` for that column.
+
+**Readers** may use a `collation_bounds` entry to prune a file only when both 
the entry's `collation` and `version` match the collation the reader resolves 
for the column; otherwise the entry must be ignored. A reader must not use the 
byte-order `lower_bounds`/`upper_bounds` to prune comparison, equality, or 
prefix predicates on a collated column. When no usable collation bounds are 
available, the file must be scanned. A collation-unaware reader ignores the 
`collation` attribute and the `collation_bounds` field and reads the column as 
a UTF-8 byte-order string.

Review Comment:
   suggestion to clarify what kind of predicate requires collation match, and 
clarify what collation unaware readers may do
   ```
   Readers that evaluate string predicates using a field’s declared collation 
must not use byte-order lower_bounds or upper_bounds to prune predicates whose 
result depends on collation ordering or collation equality. This includes range 
comparisons, equality and inequality comparisons, prefix predicates, and any 
pattern predicate the reader evaluates using collation semantics. Such readers 
may use a collation_bounds entry only when the entry’s collation name matches 
the field’s resolved collation and the entry’s implementation version is known 
to produce the same ordering. If no matching collation_bounds entry is 
available, the reader must treat the file as possibly matching the predicate.
   
   Collation-unaware readers ignore the field `collation` attribute and the 
`collation_bounds` field. Such readers continue to interpret string values and 
byte-order `lower_bounds` / `upper_bounds` using ordinary UTF-8 byte-order 
semantics.
   ```



##########
format/spec.md:
##########
@@ -345,6 +346,33 @@ For example, a struct column `point` with fields `x` 
(default 0) and `y` (defaul
 
 Default values are attributes of fields in schemas and serialized with fields 
in the JSON format. See [Appendix C](#appendix-c-json-serialization).
 
+#### Collations
+
+A `string` field may carry a **collation**, an attribute that changes how the 
field's values are compared and ordered without changing how they are stored. 
Collations enable case-insensitive, accent-insensitive, and locale-aware 
comparison and sorting. A collation only affects comparison: the stored value 
is returned unchanged (a value written as `'appLE'` is read back as `'appLE'`).
+
+A field's collation is stored as a `collation` attribute on the field (see 
[Appendix C](#appendix-c-json-serialization)). The attribute is allowed only on 
`string` fields. If a field has no `collation` attribute, comparison defaults 
to UTF-8 byte order, which is the behavior of all prior versions.
+
+A collation is identified by a provider-qualified name of the form 
`<provider>.<name>`, for example `icu.en_US-ci`. The provider names the library 
that defines the collation (`icu` for collations defined by the [Unicode 
Collation Algorithm](https://unicode.org/reports/tr10/) over 
[CLDR](https://cldr.unicode.org/) locale data; other providers may define 
engine-specific collations such as case-folding variants). The name selects a 
locale and optional modifiers for case sensitivity (`ci`/`cs`), accent 
sensitivity (`ai`/`as`), trimming, and case folding. The reserved name `utf8` 
denotes UTF-8 byte-order comparison.
+
+The schema stores the collation **name without a version**, so any engine that 
supports the collation can read the table. UCA, DUCET, CLDR, and ICU collation 
orders are [not stable across 
versions](https://unicode.org/reports/tr10/#Non-Goals), so collation-aware 
metrics carry the implementation version they were produced under (see below) 
and a reader uses them only when it can produce the same order.
+
+##### Collation Bounds
+
+Because a collation can reorder values (for example `'a' < 'B'` under a 
case-insensitive collation, but `'a' > 'B'` in byte order), the byte-order 
`lower_bounds` and `upper_bounds` cannot be used to evaluate predicates on a 
collated column. Collation-aware bounds are stored separately in 
`data_file.collation_bounds`, a map from column id to a list of 
`collation_bound` structs:
+
+| Field id, name | Type | Description |
+|----------------|------|-------------|
+| **`151 collation`** | `string` | Collation the bounds were produced for, 
e.g. `icu.en_US-ci` |
+| **`152 version`** | `string` | Collation implementation version the bounds 
were selected under |

Review Comment:
   may be worth to give an example



##########
format/spec.md:
##########
@@ -345,6 +346,33 @@ For example, a struct column `point` with fields `x` 
(default 0) and `y` (defaul
 
 Default values are attributes of fields in schemas and serialized with fields 
in the JSON format. See [Appendix C](#appendix-c-json-serialization).
 
+#### Collations
+
+A `string` field may carry a **collation**, an attribute that changes how the 
field's values are compared and ordered without changing how they are stored. 
Collations enable case-insensitive, accent-insensitive, and locale-aware 
comparison and sorting. A collation only affects comparison: the stored value 
is returned unchanged (a value written as `'appLE'` is read back as `'appLE'`).
+
+A field's collation is stored as a `collation` attribute on the field (see 
[Appendix C](#appendix-c-json-serialization)). The attribute is allowed only on 
`string` fields. If a field has no `collation` attribute, comparison defaults 
to UTF-8 byte order, which is the behavior of all prior versions.
+
+A collation is identified by a provider-qualified name of the form 
`<provider>.<name>`, for example `icu.en_US-ci`. The provider names the library 
that defines the collation (`icu` for collations defined by the [Unicode 
Collation Algorithm](https://unicode.org/reports/tr10/) over 
[CLDR](https://cldr.unicode.org/) locale data; other providers may define 
engine-specific collations such as case-folding variants). The name selects a 
locale and optional modifiers for case sensitivity (`ci`/`cs`), accent 
sensitivity (`ai`/`as`), trimming, and case folding. The reserved name `utf8` 
denotes UTF-8 byte-order comparison.
+
+The schema stores the collation **name without a version**, so any engine that 
supports the collation can read the table. UCA, DUCET, CLDR, and ICU collation 
orders are [not stable across 
versions](https://unicode.org/reports/tr10/#Non-Goals), so collation-aware 
metrics carry the implementation version they were produced under (see below) 
and a reader uses them only when it can produce the same order.

Review Comment:
   nit: its describing too much about bounds which is already covered below?  
Also 'can read the table' is a bit vague as it should be read without 
stats-pruning
   
   how about just a reference: `The schema stores the logical collation name 
without a version. Collation-aware file metrics store the implementation 
version used to compute their bounds (see below)`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to