aglinxinyuan opened a new pull request, #6545:
URL: https://github.com/apache/texera/pull/6545

   ### What changes were proposed in this PR?
   
   Follow-up to #6488, which made Iceberg local storage work on Windows without
   winutils **on the Scala/JVM side only** (`IcebergUtil` + 
`WinutilsFreeLocalFileSystem`).
   The Python UDF worker writes its output-port Iceberg storage through its 
**own**
   pyiceberg path — `core/storage/iceberg/iceberg_document.py` and 
`document_factory.py`
   call `IcebergCatalogInstance.get_instance()` → `create_postgres_catalog` 
inside the
   Python process — so #6488 does not reach it. On a Windows dev machine with a
   local-filesystem warehouse (`postgres` catalog type), that path fails two 
ways:
   
   | # | Symptom | Root cause |
   |---|---|---|
   | 1 | `ValueError: Unrecognized filesystem type in URI: c` at table creation 
| a bare drive path `C:\...` is parsed by pyiceberg as URI scheme `c` |
   | 2 | `OSError: [WinError 123] ... The filename, directory name, or volume 
label syntax is incorrect` | even a `file:///C:/...` URI is rejected by 
pyiceberg's default **pyarrow** FileIO (`/C:/...`) |
   
   Fix (in `iceberg_utils.py`, mirroring #6488's tight, self-gating approach):
   
   | Change | Detail |
   |---|---|
   | `_is_windows_local_warehouse(warehouse)` (new) | True only when the 
warehouse carries a **Windows drive letter** — bare (`C:\...`, `C:/...`) or 
`file:///C:/...`. Excludes POSIX paths, colon-stripped paths (`C/...`), and 
remote object stores (`s3://...`). |
   | `_to_file_uri(warehouse)` (new) | Normalizes a bare drive path to a 
`file:///` URI via `PureWindowsPath.as_uri()` (deterministic on every host OS); 
already-URI values pass through. |
   | `create_postgres_catalog` | When (and only when) the warehouse is 
Windows-local, register the normalized `file:///` URI and select 
`pyiceberg.io.fsspec.FsspecFileIO`, whose `LocalFileSystem` handles Windows 
drive paths. |
   | `create_rest_catalog` | Unchanged — its `warehouse_name` is a logical 
identifier resolved server-side via `S3FileIO`, not a local path (checked, 
exempt). |
   
   The gate is deliberately narrow so the fix cannot alter the cross-runtime
   warehouse convention that Linux, macOS, CI, and the Scala engine rely on: 
PyIceberg
   persists the `warehouse` value into table metadata, so a `postgres` catalog 
with a
   POSIX or remote warehouse must keep the plain-path / default-FileIO behavior
   (regression fixed in #4409). Only genuine Windows drive-letter warehouses are
   normalized.
   
   The drive path is normalized with `PureWindowsPath.as_posix()` (not 
`.as_uri()`)
   so a warehouse containing a space — e.g. `C:\Users\John Doe\...`, `C:\Program
   Files\...`, OneDrive-redirected profiles — keeps a **raw** space rather than
   `%20`; fsspec's `LocalFileSystem` does not URL-decode, so a `%20` would write
   into a literally `%20`-named directory.
   
   Scope note: on Windows the two runtimes register different warehouse strings 
into
   the shared `postgres` catalog — the Scala side its existing colon-stripped 
path
   (`C/Users/...`), the Python worker the absolute `file:///C:/...` URI. This 
is fine
   for the actual data flow here (a Python UDF's output-port table is written 
by the
   Python worker and read back by the engine/result service via the absolute 
metadata
   pointer, verified end-to-end); reconciling the Scala side's colon-stripped
   convention is out of scope for this fix and would belong with #6488's 
follow-ups.
   
   Before → after:
   
   | Environment (`postgres` catalog) | Before | After |
   |---|---|---|
   | Windows, local warehouse (`C:\...`) | worker crashes at first table create 
| works |
   | Linux / macOS / CI, local warehouse (`/tmp/...`) | works | unchanged (gate 
off) |
   | Any host, remote warehouse (`s3://...`) | works | unchanged (gate off) |
   | `rest` catalog | unaffected (`S3FileIO`) | unaffected |
   
   ### Any related issues, documentation, discussions?
   
   Follow-up to #6488 (Scala/JVM side); closes the Python-worker half of #6487.
   Preserves the cross-runtime warehouse invariant from #4409.
   
   ### How was this PR tested?
   
   - New `TestCreatePostgresCatalogWindowsLocal` in 
`test_iceberg_utils_catalog.py`
     (written first, TDD): a Windows drive-letter warehouse is normalized to a
     `file:///` URI and `FsspecFileIO` is selected; POSIX, colon-stripped, and
     remote (`s3://`) warehouses are left untouched (no FileIO override). The 
tests
     assert on the computed `SqlCatalog` props and use `PureWindowsPath`, so 
they are
     OS-independent and pass on Linux CI.
   - The pre-existing `TestCreatePostgresCatalog` tests (the #4409 plain-path
     invariant) still pass unchanged.
   - Verified end-to-end on a real Windows filesystem: a bare `C:\...` warehouse
     fed through the productionized helpers into a real catalog creates a table 
and
     round-trips rows (both failure modes above reproduced on stock `main` 
first).
   - `amber/` `ruff check` and `ruff format --check` pass on the changed files.
     (The `test_iceberg_document.py` / REST integration tests require a live
     postgres / REST catalog server and are environment-gated locally; they are
     unaffected by this change — confirmed identical pass/fail with the diff 
stashed.)
   
   ### Was this PR authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Opus 4.8 [1M context])
   


-- 
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]

Reply via email to