From 3952224c973c3b324b472c6c0a1d14cda5b0c25e Mon Sep 17 00:00:00 2001 From: dkp116 Date: Thu, 9 Jul 2026 17:57:24 +0100 Subject: [PATCH 1/3] [C++][Docs] Add description to KeyValueMetadata::DeleteMany --- cpp/src/arrow/util/key_value_metadata.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cpp/src/arrow/util/key_value_metadata.h b/cpp/src/arrow/util/key_value_metadata.h index 57ade11e7586..b65bbb3dfd46 100644 --- a/cpp/src/arrow/util/key_value_metadata.h +++ b/cpp/src/arrow/util/key_value_metadata.h @@ -50,6 +50,12 @@ class ARROW_EXPORT KeyValueMetadata { // Note that deleting may invalidate known indices Status Delete(std::string_view key); Status Delete(int64_t index); + + /// \brief Delete metadata entries at specified index in keys and values array + /// \param indices Vector of distinct indices identifying the entries to + /// remove from the metadata. + /// \return Status indicating success or failure. + Status DeleteMany(std::vector indices); Status Set(std::string key, std::string value); From cf5003c5a110fe9832c978c25cfba6b440d243dd Mon Sep 17 00:00:00 2001 From: dkp116 Date: Sun, 20 Sep 2026 16:17:45 +0100 Subject: [PATCH 2/3] GH-50351: [C++] Change validation of DeleteMany to return Status errors so errors would return on all build types --- cpp/src/arrow/util/key_value_metadata.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/cpp/src/arrow/util/key_value_metadata.cc b/cpp/src/arrow/util/key_value_metadata.cc index 67bf02b4e1ac..f8c0be9a3bb5 100644 --- a/cpp/src/arrow/util/key_value_metadata.cc +++ b/cpp/src/arrow/util/key_value_metadata.cc @@ -121,10 +121,17 @@ Status KeyValueMetadata::DeleteMany(std::vector indices) { ++shift; const auto start = indices[i] + 1; const auto stop = indices[i + 1]; - DCHECK_GE(start, 0); - DCHECK_LE(start, size); - DCHECK_GE(stop, 0); - DCHECK_LE(stop, size); + + if (ARROW_PREDICT_TRUE(start < 0 || start > size)) { + return Status::IndexError("KeyValueMetadata::DeleteMany: Start index ", start - 1, + " out of bounds for metadata of size ", size); + } + + if (ARROW_PREDICT_TRUE(stop < 0 || stop > size)) { + return Status::IndexError("KeyValueMetadata::DeleteMany: Stop index ", stop, + " out of bounds for metadata of size ", size); + } + for (int64_t index = start; index < stop; ++index) { keys_[index - shift] = std::move(keys_[index]); values_[index - shift] = std::move(values_[index]); From 8633f6b699b31536deac31b78f94dc557dbb3bf3 Mon Sep 17 00:00:00 2001 From: dkp116 Date: Sun, 20 Sep 2026 16:18:41 +0100 Subject: [PATCH 3/3] GH-50351: [C++] Add bug fix for duplicate values in keyvaluemetadata deletemany with unit test --- cpp/src/arrow/util/key_value_metadata.cc | 8 ++++ cpp/src/arrow/util/key_value_metadata_test.cc | 41 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/cpp/src/arrow/util/key_value_metadata.cc b/cpp/src/arrow/util/key_value_metadata.cc index f8c0be9a3bb5..95f0b806ff19 100644 --- a/cpp/src/arrow/util/key_value_metadata.cc +++ b/cpp/src/arrow/util/key_value_metadata.cc @@ -112,6 +112,9 @@ Status KeyValueMetadata::Delete(int64_t index) { } Status KeyValueMetadata::DeleteMany(std::vector indices) { + if (indices.size() == 1) { + return Delete(indices[0]); + } std::sort(indices.begin(), indices.end()); const int64_t size = static_cast(keys_.size()); indices.push_back(size); @@ -133,6 +136,11 @@ Status KeyValueMetadata::DeleteMany(std::vector indices) { } for (int64_t index = start; index < stop; ++index) { + if (ARROW_PREDICT_TRUE(index < shift)) { + return Status::IndexError("KeyValueMetadata::DeleteMany: duplicate index ", index, + " in indices to delete"); + } + keys_[index - shift] = std::move(keys_[index]); values_[index - shift] = std::move(values_[index]); } diff --git a/cpp/src/arrow/util/key_value_metadata_test.cc b/cpp/src/arrow/util/key_value_metadata_test.cc index 7c021429ac17..946b363277e3 100644 --- a/cpp/src/arrow/util/key_value_metadata_test.cc +++ b/cpp/src/arrow/util/key_value_metadata_test.cc @@ -226,6 +226,47 @@ TEST(KeyValueMetadataTest, Delete) { ASSERT_OK(metadata.DeleteMany({})); ASSERT_TRUE(metadata.Equals(KeyValueMetadata({"bb", "dd", "ee"}, {"2", "4", "5"}))); } + { + KeyValueMetadata metadata(keys, values); + + std::string expected_error_message = + "Index error: KeyValueMetadata::DeleteMany: Start index -3 out of bounds for " + "metadata of size 7"; + + ASSERT_RAISES_WITH_MESSAGE(IndexError, expected_error_message, + metadata.DeleteMany({-2, -3})); + } + + { + KeyValueMetadata metadata(keys, values); + + std::string expected_error_message = + "Index error: KeyValueMetadata::Delete: index -1 is out of bounds for metadata " + "of size 7"; + + ASSERT_RAISES_WITH_MESSAGE(IndexError, expected_error_message, + metadata.DeleteMany({-1})); + } + + { + KeyValueMetadata metadata(keys, values); + + std::string expected_error_message = + "Index error: KeyValueMetadata::DeleteMany: Stop index 8 out of bounds for " + "metadata of size 7"; + + ASSERT_RAISES_WITH_MESSAGE(IndexError, expected_error_message, + metadata.DeleteMany({0, 8})); + } + { + KeyValueMetadata metadata(keys, values); + std::string expected_error_message = + "Index error: KeyValueMetadata::DeleteMany: duplicate index 1 in indices to " + "delete"; + + ASSERT_RAISES_WITH_MESSAGE(IndexError, expected_error_message, + metadata.DeleteMany({0, 0, 5, 2})); + } } } // namespace arrow