@@ -449,6 +449,59 @@ TEST_F(LiteralConverterTest, TestDictType) {
449449 Literal (FieldType::STRING , " foo" , 3 ), Literal (FieldType::STRING )}));
450450}
451451
452+ TEST_F (LiteralConverterTest, TestDictionaryValueAndIndexTypes) {
453+ const std::vector<std::pair<std::shared_ptr<arrow::DataType>, std::shared_ptr<arrow::DataType>>>
454+ types = {{arrow::utf8 (), arrow::int32 ()},
455+ {arrow::binary (), arrow::int32 ()},
456+ {arrow::large_utf8 (), arrow::int64 ()},
457+ {arrow::large_binary (), arrow::int64 ()}};
458+ for (const auto & [value_type, index_type] : types) {
459+ SCOPED_TRACE (value_type->ToString ());
460+ const FieldType literal_type =
461+ arrow::is_string (value_type->id ()) ? FieldType::STRING : FieldType::BINARY ;
462+ auto dictionary = arrow::ipc::internal::json::ArrayFromJSON (
463+ value_type, R"( ["unused", "a\u0000b", "", "middle", "tail"])" )
464+ .ValueOrDie ()
465+ ->Slice (1 );
466+ const std::vector<Literal> expected = {
467+ Literal (literal_type, " a\0 b" , 3 ), Literal (literal_type),
468+ Literal (literal_type, " " , 0 ), Literal (literal_type, " middle" , 6 ),
469+ Literal (literal_type, " tail" , 4 ), Literal (literal_type, " a\0 b" , 3 )};
470+ SCOPED_TRACE (index_type->ToString ());
471+ auto indices =
472+ arrow::ipc::internal::json::ArrayFromJSON (index_type, " [3, 0, null, 1, 2, 3, 0]" )
473+ .ValueOrDie ();
474+ auto array = arrow::DictionaryArray::FromArrays (indices, dictionary).ValueOrDie ();
475+ ASSERT_TRUE (array->ValidateFull ().ok ());
476+ auto sliced = array->Slice (1 );
477+ for (bool own_data : {false , true }) {
478+ SCOPED_TRACE (own_data);
479+ ASSERT_OK_AND_ASSIGN (std::vector<Literal> actual,
480+ LiteralConverter::ConvertLiteralsFromArray (*sliced, own_data));
481+ ASSERT_EQ (expected, actual);
482+ }
483+ }
484+ }
485+
486+ TEST_F (LiteralConverterTest, TestBinaryDictionaryPreservesBytes) {
487+ const std::string bytes (" \x00\xff\x80 " , 3 );
488+ arrow::BinaryBuilder builder;
489+ ASSERT_TRUE (builder.Append (bytes).ok ());
490+ std::shared_ptr<arrow::Array> dictionary;
491+ ASSERT_TRUE (builder.Finish (&dictionary).ok ());
492+ auto indices =
493+ arrow::ipc::internal::json::ArrayFromJSON (arrow::int32 (), " [0, null, 0]" ).ValueOrDie ();
494+ auto array = arrow::DictionaryArray::FromArrays (indices, dictionary).ValueOrDie ();
495+ ASSERT_OK_AND_ASSIGN (std::vector<Literal> actual,
496+ LiteralConverter::ConvertLiteralsFromArray (*array, /* own_data=*/ true ));
497+ array.reset ();
498+ dictionary.reset ();
499+ ASSERT_EQ (actual,
500+ std::vector<Literal>({Literal (FieldType::BINARY , bytes.data (), bytes.size ()),
501+ Literal (FieldType::BINARY ),
502+ Literal (FieldType::BINARY , bytes.data (), bytes.size ())}));
503+ }
504+
452505TEST_F (LiteralConverterTest, TestLiteralsToArray) {
453506 // Every writable field type converts to an array and back, the null literal included, so each
454507 // case asserts `ConvertLiteralsToArray` and `ConvertLiteralsFromArray` agree on every type.
0 commit comments