@@ -1024,8 +1024,7 @@ class DictDecoderImpl : public TypedDecoderImpl<Type>, public DictDecoder<Type>
10241024 // memory use in most cases
10251025 std::shared_ptr<ResizableBuffer> byte_array_offsets_;
10261026
1027- // Reusable buffer for decoding dictionary indices to be appended to a
1028- // BinaryDictionary32Builder
1027+ // Reusable buffer for decoding dictionary indices into Arrow builders.
10291028 std::shared_ptr<ResizableBuffer> indices_scratch_space_;
10301029
10311030 ::arrow::util::RleBitPackedDecoder<int32_t > idx_decoder_;
@@ -1295,12 +1294,80 @@ class DictByteArrayDecoderImpl : public DictDecoderImpl<ByteArrayType> {
12951294 int64_t valid_bits_offset,
12961295 typename EncodingTraits<ByteArrayType>::Accumulator* out,
12971296 int * out_num_values) {
1297+ const auto * dict_values = dictionary_->data_as <ByteArray>();
1298+ const int values_to_decode = num_values - null_count;
1299+
1300+ switch (out->builder ->type ()->id ()) {
1301+ case ::arrow::Type::BINARY :
1302+ case ::arrow::Type::STRING :
1303+ case ::arrow::Type::LARGE_BINARY :
1304+ case ::arrow::Type::LARGE_STRING : {
1305+ if (values_to_decode > 0 ) {
1306+ RETURN_NOT_OK (indices_scratch_space_->TypedResize <int32_t >(
1307+ values_to_decode, /* shrink_to_fit=*/ false ));
1308+ }
1309+ auto * decoded_indices = indices_scratch_space_->mutable_data_as <int32_t >();
1310+ const int num_indices = idx_decoder_.GetBatch (decoded_indices, values_to_decode);
1311+ if (ARROW_PREDICT_FALSE (num_indices != values_to_decode)) {
1312+ return Status::Invalid (" Invalid number of indices: " , num_indices);
1313+ }
1314+
1315+ int64_t data_length = 0 ;
1316+ for (int i = 0 ; i < values_to_decode; ++i) {
1317+ const auto index = decoded_indices[i];
1318+ RETURN_NOT_OK (IndexInBounds (index));
1319+ if (ARROW_PREDICT_FALSE (AddWithOverflow (
1320+ data_length, static_cast <int64_t >(dict_values[index].len ),
1321+ &data_length))) {
1322+ return Status::Invalid (
1323+ " excess expansion while decoding dictionary-encoded BYTE_ARRAY" );
1324+ }
1325+ }
1326+
1327+ auto append_predecoded = [&](auto * helper) {
1328+ int values_decoded = 0 ;
1329+ int pos_indices = 0 ;
1330+ int64_t remaining_data_length = data_length;
1331+
1332+ RETURN_NOT_OK (VisitBitRuns (
1333+ valid_bits, valid_bits_offset, num_values,
1334+ [&](int64_t position, int64_t length, bool valid) {
1335+ if (valid) {
1336+ for (int64_t i = 0 ; i < length; ++i) {
1337+ const auto & val = dict_values[decoded_indices[pos_indices++]];
1338+ RETURN_NOT_OK (helper->AppendValue (
1339+ val.ptr , static_cast <int32_t >(val.len ), remaining_data_length));
1340+ remaining_data_length -= val.len ;
1341+ }
1342+ values_decoded += static_cast <int >(length);
1343+ } else {
1344+ for (int64_t i = 0 ; i < length; ++i) {
1345+ helper->UnsafeAppendNull ();
1346+ }
1347+ }
1348+ return Status::OK ();
1349+ }));
1350+ DCHECK_EQ (pos_indices, values_to_decode);
1351+ DCHECK_EQ (remaining_data_length, 0 );
1352+ *out_num_values = values_decoded;
1353+ return Status::OK ();
1354+ };
1355+
1356+ return DispatchArrowBinaryHelper<ByteArrayType>(out, num_values, data_length,
1357+ append_predecoded);
1358+ }
1359+ default :
1360+ // Binary-view builders don't benefit from reserving the dictionary values'
1361+ // total byte length, since short values are stored inline. Keep their
1362+ // existing bounded streaming decode path. Unsupported builder types are
1363+ // rejected by DispatchArrowBinaryHelper below before decoding any indices.
1364+ break ;
1365+ }
1366+
12981367 constexpr int32_t kBufferSize = 1024 ;
12991368 int32_t indices[kBufferSize ];
13001369
1301- auto visit_binary_helper = [&](auto * helper) {
1302- const auto * dict_values = dictionary_->data_as <ByteArray>();
1303- const int values_to_decode = num_values - null_count;
1370+ auto append_streaming = [&](auto * helper) {
13041371 int values_decoded = 0 ;
13051372 int num_indices = 0 ;
13061373 int pos_indices = 0 ;
@@ -1309,7 +1376,7 @@ class DictByteArrayDecoderImpl : public DictDecoderImpl<ByteArrayType> {
13091376 if (valid) {
13101377 while (length > 0 ) {
13111378 if (num_indices == pos_indices) {
1312- // Refill indices buffer
1379+ // Refill the bounded indices buffer for binary-view builders.
13131380 const auto max_batch_size =
13141381 std::min<int32_t >(kBufferSize , values_to_decode - values_decoded);
13151382 num_indices = idx_decoder_.GetBatch (indices, max_batch_size);
@@ -1341,11 +1408,9 @@ class DictByteArrayDecoderImpl : public DictDecoderImpl<ByteArrayType> {
13411408 *out_num_values = values_decoded;
13421409 return Status::OK ();
13431410 };
1344- // The `len_` in the ByteArrayDictDecoder is the total length of the
1345- // RLE/Bit-pack encoded data size, so, we cannot use `len_` to reserve
1346- // space for binary data.
1411+
13471412 return DispatchArrowBinaryHelper<ByteArrayType>(
1348- out, num_values, /* estimated_data_length=*/ {}, visit_binary_helper );
1413+ out, num_values, /* estimated_data_length=*/ {}, append_streaming );
13491414 }
13501415
13511416 template <typename BuilderType>
0 commit comments