yihua opened a new issue, #858:
URL: https://github.com/apache/hudi-rs/issues/858

   ### Feature Description
   
   #666 added a native write path to `hudi-core`: `Table::create`, `append`, 
`upsert`, `update`, `delete`, `delete_keys`, `overwrite`, and 
`dynamic_partition_overwrite`, with the metadata table and record-level index 
maintained on every commit. The Python package still exposes only the read 
APIs, so `pip install hudi` cannot create or mutate a table.
   
   Expose the write path through the PyO3 binding:
   
   ```python
   import pyarrow as pa
   from hudi import HudiTable
   
   table = HudiTable.create(
       "/tmp/trips",
       record_key="id",
       partition_by="city",
       ordering_field="ts",
       table_type="cow",      # or "mor"
   )
   table.append(pa.table({"id": ["t1", "t2"], "city": ["sf", "sf"], "ts": [1, 
1], "fare": [30.0, 45.0]}))
   
   result = table.upsert(pa.table({"id": ["t2", "t3"], "city": ["sf", "nyc"], 
"ts": [2, 2], "fare": [50.0, 15.0]}))
   print(result.instant, result.num_updates, result.num_inserts)
   
   table.update("city = 'nyc'", {"fare": 99.0})
   table.delete("id IN ('t1')")
   table.delete_keys(["t2"])
   table.overwrite(...)
   table.dynamic_partition_overwrite(...)
   ```
   
   Proposed surface:
   
   - `HudiTable.create(base_uri, *, record_key, partition_by=None, 
ordering_field=None, table_type="cow", table_name=None, record_index=None, 
metadata=None, options=None, storage_options=None, ...)`, a static method 
wrapping `TableCreateBuilder`. Only arguments the caller passes are forwarded, 
so the Rust defaults (table version 9, metadata table and record index on) stay 
the defaults.
   - Write verbs on `HudiTable`: `append(data)`, `upsert(data, 
update_columns=None)`, `update(filter, set)`, `delete(filter)`, 
`delete_keys(keys)`, `overwrite(data)`, `dynamic_partition_overwrite(data)`.
   - `HudiWriteResult` with `instant`, `num_writes`, `num_updates`, 
`num_inserts`, `num_deletes`.
   - `data` accepts `pyarrow.Table`, `pyarrow.RecordBatch`, 
`pyarrow.RecordBatchReader`, a list of record batches, and any object 
implementing `__arrow_c_stream__` (Polars, pandas 2.2+), converted once in Rust 
through `arrow::pyarrow`. `Utf8View` and `LargeUtf8` columns (what Polars and 
pandas export) are cast to `Utf8` on the way in, since the writer requires 
`Utf8` keys.
   - `update(filter, set)` takes a `dict` of column to scalar, or a one-row 
batch.
   - `delete_keys` takes record keys as `str` or `(record_key, partition_path)` 
tuples.
   - `hudi.write_hudi(base_uri, data, mode="append" | "upsert" | "overwrite", 
record_key=..., ...)` as a convenience that creates the table on first write.
   - Every verb releases the GIL and maps `CoreError` to a Python exception; no 
panic reaches Python.
   
   Acceptance:
   
   - `.pyi` stubs and docstrings; `make check` green (ruff, mypy --strict, 
clippy)
   - `python/tests/test_table_write.py` covering each verb, each input type, 
COW and MOR, and the error paths
   - README "Writing Tables" shows the Python call next to each Rust call
   
   ### Additional context
   
   The C++ binding is tracked separately. The DataFusion provider stays 
read-only for now.
   


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