@@ -419,6 +419,52 @@ Result<S3Options> S3Options::FromUri(const std::string& uri_string,
419419 return FromUri (uri, out_path);
420420}
421421
422+ namespace {
423+
424+ Result<std::string> GetStringOption (const std::string& key, const std::any& value) {
425+ // TODO: Validate this is necessary with tests.
426+ if (const auto * s = std::any_cast<std::string>(&value)) {
427+ return *s;
428+ }
429+ return Status::Invalid (" S3 filesystem option '" , key, " ' must be a std::string" );
430+ }
431+ } // namespace
432+
433+ Result<S3Options> S3Options::FromUriAndOptions (
434+ const ::arrow::util::Uri& uri,
435+ const FileSystemFactoryOptions& options, std::string* out_path) {
436+ std::optional<std::string> access_key, secret_key, session_token;
437+ for (const auto & [key, value] : options) {
438+ if (key == " access_key" ) {
439+ ARROW_ASSIGN_OR_RAISE (access_key, GetStringOption (key, value));
440+ } else if (key == " secret_key" ) {
441+ ARROW_ASSIGN_OR_RAISE (secret_key, GetStringOption (key, value));
442+ } else if (key == " session_token" ) {
443+ ARROW_ASSIGN_OR_RAISE (session_token, GetStringOption (key, value));
444+ } else {
445+ return Status::Invalid (" Unexpected option for S3 filesystem: '" , key, " '" );
446+ }
447+ }
448+
449+ if (access_key.has_value () != secret_key.has_value ()) {
450+ return Status::Invalid (
451+ " Both 'access_key' and 'secret_key' must be provided together" );
452+ }
453+ ARROW_ASSIGN_OR_RAISE (auto s3_options, FromUri (uri, out_path));
454+ if (access_key.has_value ()) {
455+ s3_options.ConfigureAccessKey (*access_key, *secret_key, session_token.value_or (" " ));
456+ }
457+ return s3_options;
458+ }
459+
460+ Result<S3Options> S3Options::FromUriAndOptions (
461+ const std::string& uri_string,
462+ const FileSystemFactoryOptions& options, std::string* out_path) {
463+ Uri uri;
464+ RETURN_NOT_OK (uri.Parse (uri_string));
465+ return FromUriAndOptions (uri, options, out_path);
466+ }
467+
422468bool S3Options::Equals (const S3Options& other) const {
423469 const int64_t default_metadata_size = default_metadata ? default_metadata->size () : 0 ;
424470 const bool default_metadata_equals =
@@ -3606,13 +3652,14 @@ auto kS3FileSystemModule = ARROW_REGISTER_FILESYSTEM(
36063652 [](const arrow::util::Uri& uri, const FileSystemFactoryOptions& options,
36073653 const io::IOContext& io_context,
36083654 std::string* out_path) -> Result<std::shared_ptr<fs::FileSystem>> {
3609- if (!options.empty ()) {
3655+ /* if (!options.empty()) {
36103656 return Status::NotImplemented(
36113657 "S3 filesystem factory options are not supported yet, got: ", options.size(),
36123658 " option(s)");
3613- }
3659+ }*/
36143660 RETURN_NOT_OK (EnsureS3Initialized ());
3615- ARROW_ASSIGN_OR_RAISE (auto s3_options, S3Options::FromUri (uri, out_path));
3661+ ARROW_ASSIGN_OR_RAISE (auto s3_options,
3662+ S3Options::FromUriAndOptions (uri, options, out_path));
36163663 return S3FileSystem::Make (s3_options, io_context);
36173664 },
36183665 [] { DCHECK_OK (EnsureS3Finalized ()); });
0 commit comments