From 550051959f550b849e879726c53605146489dea3 Mon Sep 17 00:00:00 2001 From: Animesh Kumar Date: Tue, 6 Oct 2026 04:18:46 +0530 Subject: [PATCH] GH-51779: [C++][IPC] Read a DictionaryEncoding without indexType as int32 indices --- cpp/src/arrow/ipc/message_internal_test.cc | 24 ++++++++++++++++++++++ cpp/src/arrow/ipc/metadata_internal.cc | 8 ++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/ipc/message_internal_test.cc b/cpp/src/arrow/ipc/message_internal_test.cc index 90b091c6b671..5d7fcb899b3d 100644 --- a/cpp/src/arrow/ipc/message_internal_test.cc +++ b/cpp/src/arrow/ipc/message_internal_test.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -114,6 +115,29 @@ TEST(TestMessageInternal, TestEndiannessRoundtrip) { } } +// GH-51779: Schema.fbs allows DictionaryEncoding.indexType to be omitted, in +// which case the indices are signed int32. +TEST(TestMessageInternal, DictionaryEncodingWithoutIndexType) { + FBB fbb; + auto name = fbb.CreateString("f0"); + auto value_type = flatbuf::CreateUtf8(fbb); + auto encoding = flatbuf::CreateDictionaryEncoding(fbb, /*id=*/0, /*indexType=*/0); + auto fb_field = flatbuf::CreateField(fbb, name, /*nullable=*/true, flatbuf::Type_Utf8, + value_type.Union(), encoding); + auto fb_schema = flatbuf::CreateSchema(fbb, flatbuf::Endianness_Little, + fbb.CreateVector({fb_field})); + fbb.Finish(flatbuf::CreateMessage(fbb, flatbuf::MetadataVersion_V5, + flatbuf::MessageHeader_Schema, fb_schema.Union())); + auto metadata = Buffer::FromString( + std::string(reinterpret_cast(fbb.GetBufferPointer()), fbb.GetSize())); + + ASSERT_OK_AND_ASSIGN(auto message, Message::Open(metadata, /*body=*/nullptr)); + DictionaryMemo memo; + ASSERT_OK_AND_ASSIGN(auto schema, ReadSchema(*message, &memo)); + AssertSchemaEqual(*::arrow::schema({field("f0", dictionary(int32(), utf8()))}), + *schema); +} + struct SampleMessageParams { std::shared_ptr custom_metadata = {}; int64_t body_length = 0; diff --git a/cpp/src/arrow/ipc/metadata_internal.cc b/cpp/src/arrow/ipc/metadata_internal.cc index 94a956916162..7ac5990513a6 100644 --- a/cpp/src/arrow/ipc/metadata_internal.cc +++ b/cpp/src/arrow/ipc/metadata_internal.cc @@ -898,8 +898,12 @@ Status FieldFromFlatbuffer(const flatbuf::Field* field, FieldPosition field_pos, // dictionary_memo std::shared_ptr index_type; auto int_data = encoding->indexType(); - CHECK_FLATBUFFERS_NOT_NULL(int_data, "DictionaryEncoding.indexType"); - RETURN_NOT_OK(IntFromFlatbuffer(int_data, &index_type)); + if (int_data == nullptr) { + // Schema.fbs: "If this field is null, the indices must be signed int32." + index_type = int32(); + } else { + RETURN_NOT_OK(IntFromFlatbuffer(int_data, &index_type)); + } dict_value_type = type; ARROW_ASSIGN_OR_RAISE(type, DictionaryType::Make(index_type, type, encoding->isOrdered()));