From dd705a4627295697b804d934c70dbd9b13acd214 Mon Sep 17 00:00:00 2001 From: hechao Date: Sun, 5 Jul 2026 18:53:03 +0800 Subject: [PATCH 1/3] docs(python): fix README fence and document current read/write APIs - Fix broken closing fence at end of Test section (5 backticks -> 3) - Add "Native Read / Write" section showing PaimonCatalog -> Table -> new_read_builder (with time travel) / new_write_builder examples - Writer and committer must come from the same WriteBuilder instance --- bindings/python/README.md | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/bindings/python/README.md b/bindings/python/README.md index 1c908bce..344977e9 100644 --- a/bindings/python/README.md +++ b/bindings/python/README.md @@ -50,6 +50,41 @@ ctx.sql("DROP TEMPORARY TABLE paimon.default.my_temp") For the full SQL reference, see the [SQL Integration docs](https://paimon.apache.org/docs/master/sql/). +### Native Read / Write + +Beyond SQL, you can use the lower-level read and write APIs directly from Python. +Time travel is supported via the `options` dict on `new_read_builder`. + +```python +from pypaimon_rust.datafusion import PaimonCatalog + +catalog = PaimonCatalog({"warehouse": "/tmp/paimon-warehouse"}) + +# Table must already exist — create it via SQL, the REST API, or another client +table = catalog.get_table("my_db.my_table") + +# Time travel: pass timestamp-millis, version, snapshot-id, or tag-name +reader = ( + table.new_read_builder({"scan.timestamp-millis": "1718208000000"}) + .with_projection(["id", "name"]) + .with_limit(100) + .new_read() +) + +# Scan → Read: plan splits first, then read batches +scan = table.new_read_builder().new_scan() +plan = scan.plan() +batches = reader.read(plan.splits()) + +# Write: build → write Arrow batches → commit +write_builder = table.new_write_builder() +writer = write_builder.new_write() +writer.write_arrow(batch) +commit_messages = writer.prepare_commit() + +write_builder.new_commit().commit(commit_messages) +``` + ## Setup Install [uv](https://docs.astral.sh/uv/getting-started/installation/): @@ -82,4 +117,4 @@ cd bindings/python ```shell make test -``````` +``` From 296eb4b7b7050de22722855a165cef7242b38f9b Mon Sep 17 00:00:00 2001 From: hechao Date: Sun, 5 Jul 2026 19:55:26 +0800 Subject: [PATCH 2/3] Revert "docs(python): fix README fence and document current read/write APIs" This reverts commit dd705a4627295697b804d934c70dbd9b13acd214. --- bindings/python/README.md | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/bindings/python/README.md b/bindings/python/README.md index 344977e9..1c908bce 100644 --- a/bindings/python/README.md +++ b/bindings/python/README.md @@ -50,41 +50,6 @@ ctx.sql("DROP TEMPORARY TABLE paimon.default.my_temp") For the full SQL reference, see the [SQL Integration docs](https://paimon.apache.org/docs/master/sql/). -### Native Read / Write - -Beyond SQL, you can use the lower-level read and write APIs directly from Python. -Time travel is supported via the `options` dict on `new_read_builder`. - -```python -from pypaimon_rust.datafusion import PaimonCatalog - -catalog = PaimonCatalog({"warehouse": "/tmp/paimon-warehouse"}) - -# Table must already exist — create it via SQL, the REST API, or another client -table = catalog.get_table("my_db.my_table") - -# Time travel: pass timestamp-millis, version, snapshot-id, or tag-name -reader = ( - table.new_read_builder({"scan.timestamp-millis": "1718208000000"}) - .with_projection(["id", "name"]) - .with_limit(100) - .new_read() -) - -# Scan → Read: plan splits first, then read batches -scan = table.new_read_builder().new_scan() -plan = scan.plan() -batches = reader.read(plan.splits()) - -# Write: build → write Arrow batches → commit -write_builder = table.new_write_builder() -writer = write_builder.new_write() -writer.write_arrow(batch) -commit_messages = writer.prepare_commit() - -write_builder.new_commit().commit(commit_messages) -``` - ## Setup Install [uv](https://docs.astral.sh/uv/getting-started/installation/): @@ -117,4 +82,4 @@ cd bindings/python ```shell make test -``` +``````` From a68205569db71bfa84de0b92acec6f783a7f2f28 Mon Sep 17 00:00:00 2001 From: hechao Date: Sun, 5 Jul 2026 20:19:10 +0800 Subject: [PATCH 3/3] docs(python): fix README fence and document current read/write APIs --- bindings/python/README.md | 53 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/bindings/python/README.md b/bindings/python/README.md index 1c908bce..ec087ad2 100644 --- a/bindings/python/README.md +++ b/bindings/python/README.md @@ -50,6 +50,57 @@ ctx.sql("DROP TEMPORARY TABLE paimon.default.my_temp") For the full SQL reference, see the [SQL Integration docs](https://paimon.apache.org/docs/master/sql/). +### Native Read / Write + +Beyond SQL, you can use the lower-level read and write APIs directly from Python. +Time travel is supported via the `options` dict on `new_read_builder`. + +```python +import pyarrow as pa +from pypaimon_rust.datafusion import SQLContext, PaimonCatalog + +WAREHOUSE = "/tmp/paimon-warehouse" + +# --- DDL/DML via DataFusion SQLContext --- +ctx = SQLContext() +ctx.register_catalog("paimon", {"warehouse": WAREHOUSE}) +ctx.sql("CREATE SCHEMA paimon.my_db") +ctx.sql("CREATE TABLE paimon.my_db.users (id INT, name STRING, PRIMARY KEY (id))") +ctx.sql("INSERT INTO paimon.my_db.users VALUES (1, 'alice'), (2, 'bob')") +catalog = PaimonCatalog({"warehouse": WAREHOUSE}) +table = catalog.get_table("my_db.users") + +# --- Read data --- +read_builder = table.new_read_builder().with_projection(["id", "name"]).with_limit(100) +scan = read_builder.new_scan() +plan = scan.plan() +batches = read_builder.new_read().read(plan.splits()) + +print(f"\nRead: {batches[0].num_rows} rows") +print(batches[0]) + +# --- Write data, from a PyArrow RecordBatch --- +batch = pa.record_batch( + [[3, 4], ["charlie", "diana"]], + schema=pa.schema([("id", pa.int32()), ("name", pa.utf8())]), +) +write_builder = table.new_write_builder() +writer = write_builder.new_write() +writer.write_arrow(batch) +commit_messages = writer.prepare_commit() +write_builder.new_commit().commit(commit_messages) + +# --- Time travel: read a past version --- +# Supported options: scan.version, scan.timestamp-millis, scan.snapshot-id, or scan.tag-name +read_builder_tt = table.new_read_builder({"scan.version": "2"}) +scan_tt = read_builder_tt.new_scan() +plan_tt = scan_tt.plan() +batches_tt = read_builder_tt.new_read().read(plan_tt.splits()) + +print(f"\nRead: {batches_tt[0].num_rows} rows") +print(batches_tt[0]) +``` + ## Setup Install [uv](https://docs.astral.sh/uv/getting-started/installation/): @@ -82,4 +133,4 @@ cd bindings/python ```shell make test -``````` +```