Skip to content

Commit 9d177f2

Browse files
committed
basic implement GetFieldByNameCaseInsensitive with ascii
1 parent be514fc commit 9d177f2

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

src/iceberg/type.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@
2828

2929
namespace iceberg {
3030

31+
namespace {
32+
bool StringEqualsCaseInsensitive(std::string_view lhs, std::string_view rhs) {
33+
if (lhs.size() != rhs.size()) {
34+
return false;
35+
}
36+
return std::equal(lhs.begin(), lhs.end(), rhs.begin(),
37+
[](char a, char b) { return std::tolower(a) == std::tolower(b); });
38+
}
39+
} // namespace
40+
3141
StructType::StructType(std::vector<SchemaField> fields) : fields_(std::move(fields)) {
3242
size_t index = 0;
3343
for (const auto& field : fields_) {
@@ -59,13 +69,15 @@ std::optional<std::reference_wrapper<const SchemaField>> StructType::GetFieldByI
5969
if (it == field_id_to_index_.end()) return std::nullopt;
6070
return fields_[it->second];
6171
}
72+
6273
std::optional<std::reference_wrapper<const SchemaField>> StructType::GetFieldByIndex(
6374
int32_t index) const {
6475
if (index < 0 || index >= static_cast<int32_t>(fields_.size())) {
6576
return std::nullopt;
6677
}
6778
return fields_[index];
6879
}
80+
6981
std::optional<std::reference_wrapper<const SchemaField>> StructType::GetFieldByName(
7082
std::string_view name) const {
7183
// N.B. duplicate names are not permitted (looking at the Java
@@ -77,6 +89,17 @@ std::optional<std::reference_wrapper<const SchemaField>> StructType::GetFieldByN
7789
}
7890
return std::nullopt;
7991
}
92+
93+
std::optional<std::reference_wrapper<const SchemaField>>
94+
StructType::GetFieldByNameCaseInsensitive(std::string_view name) const {
95+
for (const auto& field : fields_) {
96+
if (StringEqualsCaseInsensitive(field.name(), name)) {
97+
return std::cref(field);
98+
}
99+
}
100+
return std::nullopt;
101+
}
102+
80103
bool StructType::Equals(const Type& other) const {
81104
if (other.type_id() != TypeId::kStruct) {
82105
return false;
@@ -126,6 +149,15 @@ std::optional<std::reference_wrapper<const SchemaField>> ListType::GetFieldByNam
126149
}
127150
return std::nullopt;
128151
}
152+
153+
std::optional<std::reference_wrapper<const SchemaField>>
154+
ListType::GetFieldByNameCaseInsensitive(std::string_view name) const {
155+
if (StringEqualsCaseInsensitive(element_.name(), name)) {
156+
return std::cref(element_);
157+
}
158+
return std::nullopt;
159+
}
160+
129161
bool ListType::Equals(const Type& other) const {
130162
if (other.type_id() != TypeId::kList) {
131163
return false;
@@ -186,6 +218,17 @@ std::optional<std::reference_wrapper<const SchemaField>> MapType::GetFieldByName
186218
}
187219
return std::nullopt;
188220
}
221+
222+
std::optional<std::reference_wrapper<const SchemaField>>
223+
MapType::GetFieldByNameCaseInsensitive(std::string_view name) const {
224+
if (StringEqualsCaseInsensitive(kKeyName, name)) {
225+
return key();
226+
} else if (StringEqualsCaseInsensitive(kValueName, name)) {
227+
return value();
228+
}
229+
return std::nullopt;
230+
}
231+
189232
bool MapType::Equals(const Type& other) const {
190233
if (other.type_id() != TypeId::kMap) {
191234
return false;

src/iceberg/type.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ class ICEBERG_EXPORT NestedType : public Type {
9292
/// \note This is currently O(n) complexity.
9393
[[nodiscard]] virtual std::optional<std::reference_wrapper<const SchemaField>>
9494
GetFieldByName(std::string_view name) const = 0;
95+
96+
[[nodiscard]] virtual std::optional<std::reference_wrapper<const SchemaField>>
97+
GetFieldByNameCaseInsensitive(std::string_view name) const = 0;
9598
};
9699

97100
/// \defgroup type-nested Nested Types
@@ -115,6 +118,8 @@ class ICEBERG_EXPORT StructType : public NestedType {
115118
int32_t index) const override;
116119
std::optional<std::reference_wrapper<const SchemaField>> GetFieldByName(
117120
std::string_view name) const override;
121+
std::optional<std::reference_wrapper<const SchemaField>> GetFieldByNameCaseInsensitive(
122+
std::string_view name) const override;
118123

119124
protected:
120125
bool Equals(const Type& other) const override;
@@ -146,6 +151,8 @@ class ICEBERG_EXPORT ListType : public NestedType {
146151
int32_t index) const override;
147152
std::optional<std::reference_wrapper<const SchemaField>> GetFieldByName(
148153
std::string_view name) const override;
154+
std::optional<std::reference_wrapper<const SchemaField>> GetFieldByNameCaseInsensitive(
155+
std::string_view name) const override;
149156

150157
protected:
151158
bool Equals(const Type& other) const override;
@@ -178,6 +185,8 @@ class ICEBERG_EXPORT MapType : public NestedType {
178185
int32_t index) const override;
179186
std::optional<std::reference_wrapper<const SchemaField>> GetFieldByName(
180187
std::string_view name) const override;
188+
std::optional<std::reference_wrapper<const SchemaField>> GetFieldByNameCaseInsensitive(
189+
std::string_view name) const override;
181190

182191
protected:
183192
bool Equals(const Type& other) const override;

test/type_test.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,17 @@ TEST(TypeTest, List) {
318318
ASSERT_THAT(list.GetFieldById(5), ::testing::Optional(field));
319319
ASSERT_THAT(list.GetFieldByIndex(0), ::testing::Optional(field));
320320
ASSERT_THAT(list.GetFieldByName("element"), ::testing::Optional(field));
321+
ASSERT_THAT(list.GetFieldByNameCaseInsensitive("element"),
322+
::testing::Optional(field));
323+
ASSERT_THAT(list.GetFieldByNameCaseInsensitive("ELEMENT"),
324+
::testing::Optional(field));
321325

322326
ASSERT_EQ(std::nullopt, list.GetFieldById(0));
323327
ASSERT_EQ(std::nullopt, list.GetFieldByIndex(1));
324328
ASSERT_EQ(std::nullopt, list.GetFieldByIndex(-1));
325329
ASSERT_EQ(std::nullopt, list.GetFieldByName("foo"));
330+
ASSERT_EQ(std::nullopt, list.GetFieldByNameCaseInsensitive("foo"));
331+
ASSERT_EQ(std::nullopt, list.GetFieldByNameCaseInsensitive("FOO"));
326332
}
327333
ASSERT_THAT(
328334
[]() {
@@ -347,12 +353,15 @@ TEST(TypeTest, Map) {
347353
ASSERT_THAT(map.GetFieldByIndex(0), ::testing::Optional(key));
348354
ASSERT_THAT(map.GetFieldByIndex(1), ::testing::Optional(value));
349355
ASSERT_THAT(map.GetFieldByName("key"), ::testing::Optional(key));
356+
ASSERT_THAT(map.GetFieldByNameCaseInsensitive("kEY"), ::testing::Optional(key));
350357
ASSERT_THAT(map.GetFieldByName("value"), ::testing::Optional(value));
358+
ASSERT_THAT(map.GetFieldByName("vALUE"), ::testing::Optional(value));
351359

352360
ASSERT_EQ(std::nullopt, map.GetFieldById(0));
353361
ASSERT_EQ(std::nullopt, map.GetFieldByIndex(2));
354362
ASSERT_EQ(std::nullopt, map.GetFieldByIndex(-1));
355363
ASSERT_EQ(std::nullopt, map.GetFieldByName("element"));
364+
ASSERT_EQ(std::nullopt, map.GetFieldByName("elemENt"));
356365
}
357366
ASSERT_THAT(
358367
[]() {
@@ -386,12 +395,17 @@ TEST(TypeTest, Struct) {
386395
ASSERT_THAT(struct_.GetFieldByIndex(0), ::testing::Optional(field1));
387396
ASSERT_THAT(struct_.GetFieldByIndex(1), ::testing::Optional(field2));
388397
ASSERT_THAT(struct_.GetFieldByName("foo"), ::testing::Optional(field1));
398+
ASSERT_THAT(struct_.GetFieldByName("FOO"), ::testing::Optional(field1));
389399
ASSERT_THAT(struct_.GetFieldByName("bar"), ::testing::Optional(field2));
400+
ASSERT_THAT(struct_.GetFieldByNameCaseInsensitive("bar"),
401+
::testing::Optional(field2));
390402

391403
ASSERT_EQ(std::nullopt, struct_.GetFieldById(0));
392404
ASSERT_EQ(std::nullopt, struct_.GetFieldByIndex(2));
393405
ASSERT_EQ(std::nullopt, struct_.GetFieldByIndex(-1));
394406
ASSERT_EQ(std::nullopt, struct_.GetFieldByName("element"));
407+
ASSERT_EQ(std::nullopt, struct_.GetFieldByNameCaseInsensitive("element"));
408+
ASSERT_EQ(std::nullopt, struct_.GetFieldByNameCaseInsensitive("ELEMENT"));
395409
}
396410
ASSERT_THAT(
397411
[]() {

0 commit comments

Comments
 (0)