You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Put dictionary value extension metadata on the C Data dictionary child - #474
For a dictionary-encoded extension type such as dictionary<int32, arrow.uuid>, Arrow C++ puts the value type's ARROW:extension:name on the dictionary child ArrowSchema. On the field itself, the same keys mean the extension's storage is the whole dictionary. CArrowSchemaExporter put a value type's extension metadata on the field. As a result, pyarrow rejected such fields (Invalid storage type for UuidType: dictionary<...>), and the importer didn't resolve them in either direction (#473).
Export
When a dictionary's value type is an ExtensionType, its extension metadata is written on the dictionary child. If the field metadata names that same extension, which is how the IPC reader leaves it, those keys move to the child as well. Other field metadata stays on the field.
Unresolved extension metadata on a dictionary field, where the value type isn't an ExtensionType, stays on the field. There, it describes an extension over the whole dictionary, which is how Arrow C++ exports one.
ExportType now writes extension metadata when given an ExtensionType, as Arrow C++ does. The dictionary child is exported through it. Behavior change:ExportType(GuidType.Default, ptr) previously produced a bare w:16 with no extension name.
Import
The dictionary child's extension metadata resolves the value type against the registry. It isn't copied to the field, where it would mean something else. Like Arrow C++, an unresolved value type's extension metadata is dropped.
Extension metadata on a dictionary field is resolved against the whole dictionary type only, as in Arrow C++. Behavior change: schemas exported by earlier versions of this library put a value type's extension metadata there, so importing one gives a dictionary of the storage type. C Data schemas aren't persisted, so this only affects exchanges between different Apache.Arrow versions in the same process.
Tests
.NET: where export puts the metadata, including field-level keys from IPC. Unresolved field-level metadata stays on the field across an import and re-export without a registry. Also schema round trips with and without a registry, field-level metadata on a dictionary not being applied to the values, and a DictionaryArray of GuidArray round trip.
pyarrow: .NET → pyarrow gives dictionary<values=extension<arrow.uuid>, indices=int32> with equal values, and pyarrow → .NET gives a DictionaryArray whose Dictionary is a GuidArray.
IPC has the same ambiguity, and Apache.Arrow's IPC reader resolves it the opposite way from Arrow C++. That's filed separately as #475.
For a dictionary-encoded extension type, Arrow C++ puts the value type's
ARROW:extension:name on the dictionary child ArrowSchema, but the C Data
exporter put it on the field, where IPC keeps it. pyarrow rejected such
fields, and the importer never resolved them in either direction.
Export: write a dictionary field's extension keys on the dictionary
child, and have ExportType emit extension metadata for extension types.
Import: resolve the dictionary child's extension metadata against the
value type and copy it to the field metadata, matching the IPC reader.
For data exported by older versions, a field-level extension name on a
dictionary field is also tried against the value type.
Fixesapache#473
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a dictionary field, C Data extension metadata means the extension's
storage is the whole dictionary. The exporter moved any such metadata to
the dictionary child, so an unresolved extension over a dictionary was
re-exported as an extension over its values. Move it only when it names
the resolved value type, as the IPC reader leaves it.
The importer no longer copies dictionary child extension metadata to the
field, where it would take on that other meaning. As in Arrow C++, an
unresolved value type's extension metadata is dropped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ImportField invokes the foreign schema's release callback but does not free the CArrowSchema allocation itself (the API docs require callers to call CArrowSchema.Free afterward). This test frees cArray but never frees cSchema, leaking the unmanaged schema allocation on every successful run; add CArrowSchema.Free(cSchema) after importing (ideally in a finally).
Extension metadata on a dictionary field describes the whole dictionary.
Stop also trying it against the value type to resolve schemas exported
by earlier versions of this library; C Data schemas aren't persisted,
and Arrow C++ has no such fallback.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
## What's Changed
`ImportArray`, `ImportRecordBatch`, `ImportGuidArray` and
`ImportBool8Array` in `CDataInterfacePythonTests.cs` allocate a
`CArrowSchema`, have pyarrow export into it, and import it, but never
call `CArrowSchema.Free`. The importer calls pyarrow's release callback,
so what leaked was the `CArrowSchema` struct itself. They now free the
schema right after importing it, as `ImportDictionaryOfGuidArray` does
since #474, so a failing assertion can't skip the free.
This only changes tests. Every `CArrowSchema.Create` in the test
projects now has a matching `CArrowSchema.Free`.
## Tests
The full `Apache.Arrow.Tests` suite passes on net8.0, net462 and net472,
with the pyarrow tests enabled.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's Changed
For a dictionary-encoded extension type such as
dictionary<int32, arrow.uuid>, Arrow C++ puts the value type'sARROW:extension:nameon thedictionarychildArrowSchema. On the field itself, the same keys mean the extension's storage is the whole dictionary.CArrowSchemaExporterput a value type's extension metadata on the field. As a result, pyarrow rejected such fields (Invalid storage type for UuidType: dictionary<...>), and the importer didn't resolve them in either direction (#473).Export
ExtensionType, its extension metadata is written on thedictionarychild. If the field metadata names that same extension, which is how the IPC reader leaves it, those keys move to the child as well. Other field metadata stays on the field.ExtensionType, stays on the field. There, it describes an extension over the whole dictionary, which is how Arrow C++ exports one.ExportTypenow writes extension metadata when given anExtensionType, as Arrow C++ does. The dictionary child is exported through it. Behavior change:ExportType(GuidType.Default, ptr)previously produced a barew:16with no extension name.Import
dictionarychild's extension metadata resolves the value type against the registry. It isn't copied to the field, where it would mean something else. Like Arrow C++, an unresolved value type's extension metadata is dropped.Tests
DictionaryArrayofGuidArrayround trip.dictionary<values=extension<arrow.uuid>, indices=int32>with equal values, and pyarrow → .NET gives aDictionaryArraywhoseDictionaryis aGuidArray.IPC has the same ambiguity, and Apache.Arrow's IPC reader resolves it the opposite way from Arrow C++. That's filed separately as #475.
Closes #473.
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com