From ede2d206a251ba818afe3d3a682226d080c23483 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Fri, 28 Nov 2025 22:46:57 +0100 Subject: [PATCH 1/2] Case-insensitive index access * fix the Binding node always using #_Table_ instead of _Label_ for custom index colums * use case-insensitive comparison for looking up index columns in soa::Table and arrow::Table, as the custom-declared index columns may have inconsistent capitalization in their names --- Framework/Core/include/Framework/ASoA.h | 12 ++++++++-- Framework/Core/src/ArrowTableSlicingCache.cxx | 24 ++++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index a30363605af36..43079a4634e97 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1376,7 +1376,15 @@ static constexpr std::string getLabelFromType() template static constexpr auto hasColumnForKey(framework::pack, std::string const& key) { - return ((C::inherited_t::mLabel == key) || ...); + auto caseInsensitiveCompare = [](const std::string_view& str1, const std::string& str2) { + return std::ranges::equal( + str1, str2, + [](char c1, char c2) { + return std::tolower(static_cast(c1)) == + std::tolower(static_cast(c2)); + }); + }; + return (caseInsensitiveCompare(C::inherited_t::mLabel, key) || ...); } template @@ -2866,7 +2874,7 @@ consteval auto getIndexTargets() o2::soa::Binding getCurrentRaw() const { return mBinding; } \ o2::soa::Binding mBinding; \ }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" #_Table_ _Suffix_, _Name_##Id::hash, o2::framework::expressions::selectArrowType<_Type_>() } + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" _Label_ _Suffix_, _Name_##Id::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Table_, _Suffix_) DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, #_Table_, _Suffix_) #define DECLARE_SOA_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, _Name_##s, "") diff --git a/Framework/Core/src/ArrowTableSlicingCache.cxx b/Framework/Core/src/ArrowTableSlicingCache.cxx index 373c98516bb09..72ced958c510c 100644 --- a/Framework/Core/src/ArrowTableSlicingCache.cxx +++ b/Framework/Core/src/ArrowTableSlicingCache.cxx @@ -19,6 +19,24 @@ namespace o2::framework { +namespace { +std::shared_ptr GetColumnByNameCI(std::shared_ptr const& table, std::string const& key) +{ + auto const& fields = table->schema()->fields(); + auto target = std::find_if(fields.begin(), fields.end(), [&key](std::shared_ptr const& field){ + return [](std::string_view const& s1, std::string_view const& s2){ + return std::ranges::equal( + s1, s2, + [](char c1, char c2){ + return std::tolower(static_cast(c1)) == std::tolower(static_cast(c2)); + } + ); + }(field->name(), key); + }); + return table->column(std::distance(fields.begin(), target)); +} +} + void updatePairList(Cache& list, std::string const& binding, std::string const& key, bool enabled = true) { auto locate = std::find_if(list.begin(), list.end(), [&binding, &key](auto const& entry) { return (entry.binding == binding) && (entry.key == key); }); @@ -99,7 +117,7 @@ arrow::Status ArrowTableSlicingCache::updateCacheEntry(int pos, std::shared_ptr< validateOrder(bindingsKeys[pos], table); int maxValue = -1; - auto column = table->GetColumnByName(k); + auto column = GetColumnByNameCI(table, k); // starting from the end, find the first positive value, in a sorted column it is the largest index for (auto iChunk = column->num_chunks() - 1; iChunk >= 0; --iChunk) { @@ -155,7 +173,7 @@ arrow::Status ArrowTableSlicingCache::updateCacheEntryUnsorted(int pos, const st if (!e) { throw runtime_error_f("Disabled unsorted cache %s/%s update requested", b.c_str(), k.c_str()); } - auto column = table->GetColumnByName(k); + auto column = GetColumnByNameCI(table, k); auto row = 0; for (auto iChunk = 0; iChunk < column->num_chunks(); ++iChunk) { auto chunk = static_cast>(column->chunk(iChunk)->data()); @@ -252,7 +270,7 @@ SliceInfoUnsortedPtr ArrowTableSlicingCache::getCacheUnsortedForPos(int pos) con void ArrowTableSlicingCache::validateOrder(Entry const& bindingKey, const std::shared_ptr& input) { auto const& [target, key, enabled] = bindingKey; - auto column = input->GetColumnByName(key); + auto column = o2::framework::GetColumnByNameCI(input, key); auto array0 = static_cast>(column->chunk(0)->data()); int32_t prev = 0; int32_t cur = array0.Value(0); From 028836e111e268fda1ba20aa6d783d90ca1014c2 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 28 Nov 2025 21:52:32 +0000 Subject: [PATCH 2/2] Please consider the following formatting changes --- Framework/Core/src/ArrowTableSlicingCache.cxx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Framework/Core/src/ArrowTableSlicingCache.cxx b/Framework/Core/src/ArrowTableSlicingCache.cxx index 72ced958c510c..75b4bbfac701d 100644 --- a/Framework/Core/src/ArrowTableSlicingCache.cxx +++ b/Framework/Core/src/ArrowTableSlicingCache.cxx @@ -19,23 +19,23 @@ namespace o2::framework { -namespace { +namespace +{ std::shared_ptr GetColumnByNameCI(std::shared_ptr const& table, std::string const& key) { auto const& fields = table->schema()->fields(); - auto target = std::find_if(fields.begin(), fields.end(), [&key](std::shared_ptr const& field){ - return [](std::string_view const& s1, std::string_view const& s2){ + auto target = std::find_if(fields.begin(), fields.end(), [&key](std::shared_ptr const& field) { + return [](std::string_view const& s1, std::string_view const& s2) { return std::ranges::equal( s1, s2, - [](char c1, char c2){ + [](char c1, char c2) { return std::tolower(static_cast(c1)) == std::tolower(static_cast(c2)); - } - ); + }); }(field->name(), key); }); return table->column(std::distance(fields.begin(), target)); } -} +} // namespace void updatePairList(Cache& list, std::string const& binding, std::string const& key, bool enabled = true) {