Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/nanoarrow/ipc/decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -1275,9 +1275,11 @@ static int ArrowIpcDecoderSetType(struct ArrowSchema* schema, ns(Field_table_t)
}

// When decoding dictionaries, we move the value type to the schema->dictionary
// member, but we need to move the field metadata back because in IPC there
// is no such thing as dictionary metadata (even extension metadata)
// https://github.com/apache/arrow/issues/49704
// member, but we need to move the field metadata back because Field.custom_metadata
// is the metadata of the field (i.e., the dictionary-encoded ArrowSchema). The
// metadata of the dictionary value type is DictionaryEncoding.custom_metadata
// (format version 1.6, https://github.com/apache/arrow/issues/49704), which is
// set on schema->dictionary separately.
static int ArrowIpcMoveDictionaryMetadataBackToField(struct ArrowSchema* schema) {
NANOARROW_DCHECK(schema->dictionary != NULL);
NANOARROW_RETURN_NOT_OK(ArrowSchemaSetMetadata(schema, schema->dictionary->metadata));
Expand Down Expand Up @@ -1338,6 +1340,13 @@ static int ArrowIpcSetDictionaryEncoding(
NANOARROW_RETURN_NOT_OK_WITH_ERROR(ArrowIpcMoveDictionaryMetadataBackToField(schema),
error);

// The metadata of the dictionary value type (e.g., the extension type of the values),
// which is absent if the writer predates format version 1.6 or the value type has no
// metadata.
NANOARROW_RETURN_NOT_OK(ArrowIpcDecoderSetMetadata(
schema->dictionary, ns(DictionaryEncoding_custom_metadata(dictionary_encoding)),
error));

// Track the identifier if we have a dictionaries object in which to track it
if (dictionaries != NULL) {
int64_t id = ns(DictionaryEncoding_id(dictionary_encoding));
Expand Down
544 changes: 531 additions & 13 deletions src/nanoarrow/ipc/decoder_test.cc

Large diffs are not rendered by default.

41 changes: 29 additions & 12 deletions src/nanoarrow/ipc/encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -608,20 +608,37 @@ static ArrowErrorCode ArrowIpcEncodeField(
return EINVAL;
}

// Create the Int type for the index type
ns(Int_ref_t) index_type_ref =
ns(Int_create(builder, index_bitwidth, index_is_signed));
FLATCC_RETURN_IF_NULL(index_type_ref, error);

// Create the DictionaryEncoding with id, indexType, isOrdered, and dictionaryKind
// Add the DictionaryEncoding with id, indexType, isOrdered, dictionaryKind, and
// custom_metadata to the field
flatbuffers_bool_t is_ordered = (schema->flags & ARROW_FLAG_DICTIONARY_ORDERED) != 0;
ns(DictionaryEncoding_ref_t) dict_encoding_ref =
ns(DictionaryEncoding_create(builder, encoding->id, index_type_ref, is_ordered,
ns(DictionaryKind_DenseArray)));
FLATCC_RETURN_IF_NULL(dict_encoding_ref, error);
FLATCC_RETURN_UNLESS_0(Field_dictionary_start(builder), error);
FLATCC_RETURN_UNLESS_0(DictionaryEncoding_id_add(builder, encoding->id), error);
FLATCC_RETURN_UNLESS_0(
DictionaryEncoding_indexType_create(builder, index_bitwidth, index_is_signed),
error);
FLATCC_RETURN_UNLESS_0(DictionaryEncoding_isOrdered_add(builder, is_ordered), error);
FLATCC_RETURN_UNLESS_0(
DictionaryEncoding_dictionaryKind_add(builder, ns(DictionaryKind_DenseArray)),
error);

// The metadata of the dictionary (value) schema is the metadata of the dictionary
// value type, whose IPC counterpart is DictionaryEncoding.custom_metadata (format
// version 1.6, https://github.com/apache/arrow/issues/49704). The metadata of the
// field itself (i.e., schema->metadata) is written to Field.custom_metadata below.
// Writers omit DictionaryEncoding.custom_metadata if there is no value metadata.
struct ArrowMetadataReader value_metadata;
NANOARROW_RETURN_NOT_OK_WITH_ERROR(
ArrowMetadataReaderInit(&value_metadata, schema->dictionary->metadata), error);
if (value_metadata.remaining_keys > 0) {
FLATCC_RETURN_UNLESS_0(DictionaryEncoding_custom_metadata_start(builder), error);
NANOARROW_RETURN_NOT_OK(ArrowIpcEncodeMetadata(
builder, schema->dictionary->metadata,
&ns(DictionaryEncoding_custom_metadata_push_start),
&ns(DictionaryEncoding_custom_metadata_push_end), error));
FLATCC_RETURN_UNLESS_0(DictionaryEncoding_custom_metadata_end(builder), error);
}

// Add the dictionary encoding to the field
FLATCC_RETURN_UNLESS_0(Field_dictionary_add(builder, dict_encoding_ref), error);
FLATCC_RETURN_UNLESS_0(Field_dictionary_end(builder), error);

// Support dictionary values with children by encoding children from
// schema->dictionary (and add a roundtrip test for a nested value type).
Expand Down
Loading
Loading