Skip to content

fix: correct URI-vs-path handling in PlanFiles() for Java-written file: paths#818

Open
yadavay-amzn wants to merge 4 commits into
apache:mainfrom
yadavay-amzn:fix-341-planfiles-path
Open

fix: correct URI-vs-path handling in PlanFiles() for Java-written file: paths#818
yadavay-amzn wants to merge 4 commits into
apache:mainfrom
yadavay-amzn:fix-341-planfiles-path

Conversation

@yadavay-amzn

Copy link
Copy Markdown

What

Fixes #341. PlanFiles() (via ResolvePath() / DetectBuiltinFileIO()) mis-handled file: locations written by Java Iceberg in the short form file:/C:/warehouse/... (fewer than three slashes): the value was not recognized as a URI and failed to resolve, so planning broke on Windows-style paths.

How

  • Detect the URI scheme per RFC 3986 (a valid scheme token followed by :) instead of searching for ://.
  • Normalize authority-less file: forms (file:/path, file:/C:/...) to the canonical file:/// form before handing them to Arrow's PathFromUri.
  • Authority-bearing URIs (file://host/path, s3://bucket/...) and bare local paths pass through unchanged.

Tests

Regression tests added in arrow_io_test.cc and rest_file_io_test.cc covering the Java file:/C:/... form, the canonical file:/// form, and file://host/path pass-through. Build 788/788, tests 18/18 green.


This contribution was authored with assistance from Claude Opus 4.8, in line with the Iceberg guidelines for AI-assisted contributions (https://iceberg.apache.org/contribute/#guidelines-for-ai-assisted-contributions). All changes were reviewed and tested by the author.

WZhuo

This comment was marked as duplicate.

Comment thread src/iceberg/arrow/arrow_io.cc Outdated
Comment on lines +493 to +503
auto colon_pos = file_location.find(':');
bool is_uri =
colon_pos != std::string::npos && colon_pos > 1 &&
std::isalpha(static_cast<unsigned char>(file_location[0])) &&
std::all_of(file_location.begin(),
file_location.begin() + static_cast<std::ptrdiff_t>(colon_pos),
[](char c) {
return std::isalpha(static_cast<unsigned char>(c)) ||
std::isdigit(static_cast<unsigned char>(c)) || c == '+' ||
c == '-' || c == '.';
});

@WZhuo WZhuo Jul 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RFC 3986 URI scheme detection logic here is duplicated verbatim in rest_file_io.cc DetectBuiltinFileIO. Consider extracting a shared bool IsUriScheme(std::string_view) helper into e.g. iceberg/util/uri.h. If the duplication is intentional to keep the rest_file_io layer independent, a comment at each site noting the duplication would suffice.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call - extracted the RFC 3986 scheme detection into a shared header-only helper IsUriScheme(std::string_view) in src/iceberg/util/uri.h, and both ResolvePath() here and DetectBuiltinFileIO() in rest_file_io.cc now call it, so the logic is no longer duplicated.

Comment on lines +59 to +68
auto colon_pos = location.find(':');
bool is_uri =
colon_pos != std::string_view::npos && colon_pos > 1 &&
std::isalpha(static_cast<unsigned char>(location[0])) &&
std::all_of(location.begin(),
location.begin() + static_cast<std::ptrdiff_t>(colon_pos), [](char c) {
return std::isalpha(static_cast<unsigned char>(c)) ||
std::isdigit(static_cast<unsigned char>(c)) || c == '+' ||
c == '-' || c == '.';
});

@WZhuo WZhuo Jul 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This RFC 3986 scheme detection is the same logic as in arrow_io.cc ArrowFileSystemFileIO::ResolvePath. See the comment there about extracting a shared helper.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - this and the arrow_io.cc site now both call the shared IsUriScheme() helper in src/iceberg/util/uri.h; the duplicated detection block is removed.

return file_location; // Bare local path (Unix or Windows drive letter)
}

auto colon_pos = file_location.find(':');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we have two calls to find. That's probably acceptable, but we could also add an output parameter to return colon_pos. Not a strong opinion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failed to plan files: Invalid: Expected a local filesystem path, got a URI in PlanFiles() call in demo_example.cc

3 participants