diff --git a/src/iceberg/arrow/s3/arrow_s3_file_io.cc b/src/iceberg/arrow/s3/arrow_s3_file_io.cc index a7e98620e..726c120c1 100644 --- a/src/iceberg/arrow/s3/arrow_s3_file_io.cc +++ b/src/iceberg/arrow/s3/arrow_s3_file_io.cc @@ -58,10 +58,10 @@ Result> ParseOptionalBool( if (value == nullptr) { return std::nullopt; } - if (*value == "true") { + if (StringUtils::EqualsIgnoreCase(*value, "true")) { return true; } - if (*value == "false") { + if (StringUtils::EqualsIgnoreCase(*value, "false")) { return false; } return InvalidArgument(R"("{}" must be "true" or "false")", key); diff --git a/src/iceberg/test/arrow_s3_file_io_test.cc b/src/iceberg/test/arrow_s3_file_io_test.cc index 701a8f0d9..577146653 100644 --- a/src/iceberg/test/arrow_s3_file_io_test.cc +++ b/src/iceberg/test/arrow_s3_file_io_test.cc @@ -269,25 +269,25 @@ TEST_F(ArrowS3FileIOTest, EndpointScheme) { TEST_F(ArrowS3FileIOTest, SslEnabled) { auto https = ConfigureS3Options({{std::string(S3Properties::kEndpoint), "http://localhost:9000"}, - {std::string(S3Properties::kSslEnabled), "true"}}); + {std::string(S3Properties::kSslEnabled), "TRUE"}}); ASSERT_THAT(https, IsOk()); EXPECT_EQ(https->scheme, "https"); auto http = ConfigureS3Options( {{std::string(S3Properties::kEndpoint), "https://localhost:9000"}, - {std::string(S3Properties::kSslEnabled), "false"}}); + {std::string(S3Properties::kSslEnabled), "FaLsE"}}); ASSERT_THAT(http, IsOk()); EXPECT_EQ(http->scheme, "http"); } TEST_F(ArrowS3FileIOTest, PathStyleAccess) { auto virtual_addressing = - ConfigureS3Options({{std::string(S3Properties::kPathStyleAccess), "false"}}); + ConfigureS3Options({{std::string(S3Properties::kPathStyleAccess), "FALSE"}}); ASSERT_THAT(virtual_addressing, IsOk()); EXPECT_TRUE(virtual_addressing->force_virtual_addressing); auto path_style = - ConfigureS3Options({{std::string(S3Properties::kPathStyleAccess), "true"}}); + ConfigureS3Options({{std::string(S3Properties::kPathStyleAccess), "TrUe"}}); ASSERT_THAT(path_style, IsOk()); EXPECT_FALSE(path_style->force_virtual_addressing); } diff --git a/src/iceberg/test/config_test.cc b/src/iceberg/test/config_test.cc index 36aa9f30d..0bb098bad 100644 --- a/src/iceberg/test/config_test.cc +++ b/src/iceberg/test/config_test.cc @@ -126,4 +126,18 @@ TEST(ConfigTest, BasicOperations) { ASSERT_EQ(config.Get(TestConfig::kDoubleConfig), 3.14); } +TEST(ConfigTest, ParseBooleanIgnoringCase) { + auto config = TestConfig::default_properties(); + + for (const auto& value : {"true", "TRUE", "TrUe"}) { + config.mutable_configs()[TestConfig::kBoolConfig.key()] = value; + EXPECT_TRUE(config.Get(TestConfig::kBoolConfig)); + } + + for (const auto& value : {"false", "FALSE", "not-a-boolean"}) { + config.mutable_configs()[TestConfig::kBoolConfig.key()] = value; + EXPECT_FALSE(config.Get(TestConfig::kBoolConfig)); + } +} + } // namespace iceberg diff --git a/src/iceberg/util/config.h b/src/iceberg/util/config.h index ed847eb63..36e92237d 100644 --- a/src/iceberg/util/config.h +++ b/src/iceberg/util/config.h @@ -54,7 +54,7 @@ U DefaultFromString(const std::string& val) { if constexpr (std::is_same_v) { return val; } else if constexpr (std::is_same_v) { - return val == "true"; + return StringUtils::EqualsIgnoreCase(val, "true"); } else if constexpr ((std::is_signed_v && std::is_integral_v) || std::is_floating_point_v) { ICEBERG_ASSIGN_OR_THROW(auto res, StringUtils::ParseNumber(val));