1919
2020#include " iceberg/type.h"
2121
22+ #include < algorithm>
23+ #include < cctype>
2224#include < format>
25+ #include < functional>
2326#include < iterator>
2427#include < memory>
28+ #include < optional>
29+ #include < ranges>
30+ #include < string_view>
31+ #include < iceberg/schema_field.h>
2532
2633#include " iceberg/exception.h"
2734#include " iceberg/util/formatter.h" // IWYU pragma: keep
@@ -70,12 +77,19 @@ std::optional<std::reference_wrapper<const SchemaField>> StructType::GetFieldByN
7077 std::string_view name) const {
7178 // N.B. duplicate names are not permitted (looking at the Java
7279 // implementation) so there is nothing in particular we need to do here
73- for (const auto & field : fields_) {
74- if (field.name () == name) {
75- return field;
76- }
77- }
78- return std::nullopt ;
80+ InitNameToIdMap ();
81+ auto it = field_name_to_index_.find (std::string (name));
82+ if (it == field_name_to_index_.end ()) return std::nullopt ;
83+ return fields_[it->second ];
84+ }
85+ std::optional<std::reference_wrapper<const SchemaField>> StructType::GetFieldByNameCaseInsensitive (
86+ std::string_view name) const {
87+ InitNameToIdMapCaseInsensitive ();
88+ std::string lower_name (name);
89+ std::ranges::transform (lower_name, lower_name.begin (), ::tolower);
90+ auto it = caseinsensitive_field_name_to_index_.find (lower_name);
91+ if (it == caseinsensitive_field_name_to_index_.end ()) return std::nullopt ;
92+ return fields_[it->second ];
7993}
8094bool StructType::Equals (const Type& other) const {
8195 if (other.type_id () != TypeId::kStruct ) {
@@ -84,6 +98,26 @@ bool StructType::Equals(const Type& other) const {
8498 const auto & struct_ = static_cast <const StructType&>(other);
8599 return fields_ == struct_.fields_ ;
86100}
101+ void StructType::InitNameToIdMap () const {
102+ if (!field_name_to_index_.empty ()) {
103+ return ;
104+ }
105+
106+ for (int i = 0 ; i < fields_.size (); i++) {
107+ field_name_to_index_[std::string (fields_[i].name ())] = i;
108+ }
109+ }
110+ void StructType::InitNameToIdMapCaseInsensitive () const {
111+ if (!caseinsensitive_field_name_to_index_.empty ()) {
112+ return ;
113+ }
114+
115+ for (int i = 0 ; i < fields_.size (); i++) {
116+ std::string lowercase_name (fields_[i].name ());
117+ std::ranges::transform (lowercase_name, lowercase_name.begin (), ::tolower);
118+ caseinsensitive_field_name_to_index_[lowercase_name] = i;
119+ }
120+ }
87121
88122ListType::ListType (SchemaField element) : element_(std::move(element)) {
89123 if (element_.name () != kElementName ) {
@@ -126,6 +160,15 @@ std::optional<std::reference_wrapper<const SchemaField>> ListType::GetFieldByNam
126160 }
127161 return std::nullopt ;
128162}
163+ std::optional<std::reference_wrapper<const SchemaField>> ListType::GetFieldByNameCaseInsensitive (
164+ std::string_view name) const {
165+ auto lower_name_view = name | std::views::transform (::tolower);
166+ auto lower_field_name = element_.name () | std::views::transform (::tolower);
167+ if (std::ranges::equal (lower_field_name, lower_name_view)) {
168+ return std::cref (element_);
169+ }
170+ return std::nullopt ;
171+ }
129172bool ListType::Equals (const Type& other) const {
130173 if (other.type_id () != TypeId::kList ) {
131174 return false ;
@@ -186,6 +229,18 @@ std::optional<std::reference_wrapper<const SchemaField>> MapType::GetFieldByName
186229 }
187230 return std::nullopt ;
188231}
232+ std::optional<std::reference_wrapper<const SchemaField>> MapType::GetFieldByNameCaseInsensitive (
233+ std::string_view name) const {
234+ auto lower_name_view = name | std::views::transform (::tolower);
235+ auto lower_key_view = kKeyName | std::views::transform (tolower);
236+ auto lower_value_view = kValueName | std::views::transform (tolower);
237+ if (std::ranges::equal (lower_key_view, lower_name_view)) {
238+ return key ();
239+ } else if (std::ranges::equal (lower_value_view, lower_name_view)) {
240+ return value ();
241+ }
242+ return std::nullopt ;
243+ }
189244bool MapType::Equals (const Type& other) const {
190245 if (other.type_id () != TypeId::kMap ) {
191246 return false ;
0 commit comments