You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by gi...@apache.org on 2026/10/18 02:25:08 UTC
(arrow-rs) branch gh-readonly-queue/main/pr-11630-a8306d68e57527a6b929a15cf046bd8550e995ea created (now 8a9f96070f)
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a change to branch gh-readonly-queue/main/pr-11630-a8306d68e57527a6b929a15cf046bd8550e995ea
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
at 8a9f96070f fix(arrow-schema): keep map keys-sorted flag in FFI field export (#11630)
This branch includes the following new commits:
new 8a9f96070f fix(arrow-schema): keep map keys-sorted flag in FFI field export (#11630)
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(arrow-rs) 01/01: fix(arrow-schema): keep map keys-sorted flag in FFI field export (#11630)
Posted by gi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-11630-a8306d68e57527a6b929a15cf046bd8550e995ea
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
commit 8a9f96070f405e5a5f85a63cdc4a3d9c32a20086
Author: Spicy Shark <32...@users.noreply.github.com>
AuthorDate: Sun Oct 18 02:25:00 2026 +0000
fix(arrow-schema): keep map keys-sorted flag in FFI field export (#11630)
# Which issue does this PR close?
- Closes #11603
# Rationale for this change
Exporting a sorted map as a `Field` drops the keys-sorted flag. With
`DataType::Map(entries, true)`, `FFI_ArrowSchema::try_from(&DataType)`
sets `ARROW_FLAG_MAP_KEYS_SORTED`, but
`FFI_ArrowSchema::try_from(&Field)` replaces it with only the nullable
and dictionary-ordered flags, so `Field::try_from(&c_schema)` returns
`Map(.., false)`. Struct, list, union and `Schema` children are exported
as fields, so a sorted map inside any of them is imported as unsorted as
well. Exporting the bare `DataType` already round-trips.
# What changes are included in this PR?
`TryFrom<&Field> for FFI_ArrowSchema` now sets `MAP_KEYS_SORTED` when
the field's data type is `DataType::Map(_, true)`, the same way it sets
the nullable and dictionary-ordered flags. `FFI_ArrowSchema::with_flags`
is unchanged.
# Are these changes tested?
Yes, two unit tests in `arrow-schema/src/ffi.rs`, using the existing
round-trip helpers. Both fail on `main` and pass with this change:
- `test_map_keys_sorted_field`: a map field with sorted and unsorted
keys, nullable and not, keeps the keys-sorted and nullable flags and its
data type through a round trip.
- `test_map_keys_sorted_nested`: sorted and unsorted maps round-trip as
children of a struct, a `List`, a dense union and a `Schema`.
# Are there any significant user-facing changes?
No.
---
arrow-schema/src/ffi.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/arrow-schema/src/ffi.rs b/arrow-schema/src/ffi.rs
index 85fb327285..823a42086a 100644
--- a/arrow-schema/src/ffi.rs
+++ b/arrow-schema/src/ffi.rs
@@ -889,6 +889,10 @@ impl TryFrom<&Field> for FFI_ArrowSchema {
flags |= Flags::DICTIONARY_ORDERED;
}
+ if let DataType::Map(_, true) = field.data_type() {
+ flags |= Flags::MAP_KEYS_SORTED;
+ }
+
let schema = FFI_ArrowSchema::try_from(field.data_type())?
.with_name(field.name())?
.with_flags(flags)?;
@@ -1068,6 +1072,56 @@ mod tests {
assert!(arrow_schema.map_keys_sorted());
}
+ fn map_type(keys_sorted: bool) -> DataType {
+ let entries = Field::new(
+ Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
+ DataType::Struct(Fields::from(vec![
+ Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, DataType::Utf8, false),
+ Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, DataType::Int32, true),
+ ])),
+ false,
+ );
+ DataType::Map(Arc::new(entries), keys_sorted)
+ }
+
+ #[test]
+ fn test_map_keys_sorted_field() {
+ for keys_sorted in [false, true] {
+ for nullable in [false, true] {
+ let field = Field::new("m", map_type(keys_sorted), nullable);
+ let c_schema = FFI_ArrowSchema::try_from(&field).unwrap();
+ assert_eq!(c_schema.map_keys_sorted(), keys_sorted);
+ assert_eq!(c_schema.nullable(), nullable);
+ round_trip_field(field);
+ }
+ }
+ }
+
+ #[test]
+ fn test_map_keys_sorted_nested() {
+ let map = |keys_sorted| Field::new("m", map_type(keys_sorted), true);
+
+ for keys_sorted in [false, true] {
+ round_trip_type(DataType::Struct(Fields::from(vec![
+ Field::new("a", DataType::Int32, true),
+ map(keys_sorted),
+ ])));
+ round_trip_type(DataType::List(Arc::new(map(keys_sorted))));
+ round_trip_type(DataType::Union(
+ UnionFields::try_new(
+ vec![0, 1],
+ vec![Field::new("i", DataType::Int32, true), map(keys_sorted)],
+ )
+ .unwrap(),
+ UnionMode::Dense,
+ ));
+ round_trip_schema(Schema::new(vec![
+ Field::new("id", DataType::Int64, false),
+ map(keys_sorted),
+ ]));
+ }
+ }
+
#[test]
fn test_dictionary_ordered() {
#[expect(deprecated)]