goel-skd commented on code in PR #760:
URL: https://github.com/apache/iceberg-cpp/pull/760#discussion_r3464471911
##########
src/iceberg/util/string_util.h:
##########
@@ -41,22 +40,24 @@ concept FromChars = requires(const char* p, T& v) {
std::from_chars(p, p, v); };
class ICEBERG_EXPORT StringUtils {
public:
- // NOTE: These convert ASCII letters only; all other bytes, including
non-ASCII
- // (multibyte UTF-8) bytes, are passed through unchanged.
- // See https://github.com/apache/iceberg-cpp/issues/613.
- static std::string ToLower(std::string_view str) {
- return str | std::ranges::views::transform(ToLowerAscii) |
- std::ranges::to<std::string>();
- }
-
+ /// \brief Lower-case a UTF-8 string using Unicode simple case mapping.
+ ///
+ /// Mirrors Iceberg Java's case-insensitive handling, which lower-cases
names with
+ /// toLowerCase(Locale.ROOT). Invalid UTF-8 input is returned unchanged.
+ /// See https://github.com/apache/iceberg-cpp/issues/613.
+ static std::string ToLower(std::string_view str);
+
+ /// \brief Upper-case ASCII letters; non-ASCII (multibyte UTF-8) bytes pass
through
+ /// unchanged.
+ ///
+ /// Unlike ToLower this is ASCII-only, since upper-casing is not used for
name matching.
static std::string ToUpper(std::string_view str) {
return str | std::ranges::views::transform(ToUpperAscii) |
std::ranges::to<std::string>();
}
static bool EqualsIgnoreCase(std::string_view lhs, std::string_view rhs) {
- return std::ranges::equal(
- lhs, rhs, [](char lc, char rc) { return ToLowerAscii(lc) ==
ToLowerAscii(rc); });
+ return ToLower(lhs) == ToLower(rhs);
Review Comment:
Checked the callers, they're all short ASCII on cold paths (metrics mode,
`"true"`, a couple UUIDs, a header name), nothing per row. Short strings stay
in SSO so `ToLower` doesn't allocate, and the UUID compare runs once per
commit, so I believe there isn't a measurable regression here.
Iceberg Java does the same thing: case-insensitive lookup just lowercases
the query and hits a map
([`Schema.caseInsensitiveFindField`](https://github.com/apache/iceberg/blob/main/api/src/main/java/org/apache/iceberg/Schema.java#L405-L407)),
and that map is built by lowercasing every field name once
([`TypeUtil.indexByLowerCaseName`](https://github.com/apache/iceberg/blob/main/api/src/main/java/org/apache/iceberg/types/TypeUtil.java#L209-L228)).
No streaming `equalsIgnoreCase` anywhere; the speed comes from caching the
lowercased keys, which we already do in `schema.cc`/`type.cc`. So the hot path
is covered and `EqualsIgnoreCase` is just the cold fallback.
Streaming is also trickier than it looks since you can't early-out on
length: simple lowercasing can change byte length (`İ` → `i` goes 2 bytes to
1).
I suggest we keep this as is and revisit if a hot-path caller comes up.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]