Create a Table
Create a named Table from Arrow batches and publish it in one Catalog commit.
Turn rows that your application produced, such as a day of camera frames in Arrow batches, into a Table that your team can read. The SDK uploads the files straight to your Project's storage and then publishes the new Table in one commit. Until that commit lands, nobody sees a partial Table.
Before you start
- A Project
demo, and permission to create Tables in it. - A client that can write, from the Python, Rust or TypeScript SDK.
- Rows as Arrow data: a pyarrow
Table,RecordBatchorRecordBatchReaderin Python,RecordBatchvalues in Rust, whose Arrow types the Rust SDK re-exports asspiral::arrow_arrayandspiral::arrow_schema, or an Arrow JS table in TypeScript.
Create the Table
Pin the branch, write the Table's first version, stage it under a name, and publish:
project = client.project("demo")
main = project.branch("main")
table = project.write_table(frames)
commit = main.commit()
commit.create_table("frames", table)
try:
head = commit.publish()
print(f"created version {table.version_id} in commit {head.commit_id}")
except (BranchMoved, PublishConflict):
print("not published: main changed or `frames` exists")write_table uploads the rows and registers the first Table version, which
has no name yet. create_table stages the name, and the version is not visible
until publish binds it. If publishing reports that the branch moved or that
the name conflicts (BranchMoved or PublishConflict in Python,
PublishError::BranchMoved or PublishError::Conflict in Rust), nothing is
published. After BranchMoved, pin the branch again and stage the
same Table in a new commit; its rows do not depend on the head, so you do not
write them again. The files of a version that you never publish stay in
storage, but no published version references them.
In Python, write_table accepts a pyarrow Table, RecordBatch or
RecordBatchReader. In Rust it accepts a RecordBatch, a Vec<RecordBatch>,
a schema with a Vec<RecordBatch>, or a boxed RecordBatchReader, and an
empty input needs an explicit schema. The SDK reads the input batch by batch.
The name is one path segment at the Project root, such as frames. The SDK
cannot create a Table under a nested path such as robots/frames, and it
rejects a name that is already staged in the same commit. If the branch
already binds the name, publishing reports a conflict.
Create several Tables in one commit
Stage more than one create_table call, or mix creates with appends, before
you call publish. The commit publishes all of them together:
project = client.project("demo")
main = project.branch("main")
appended = main.table("frames").append(frames)
created = project.write_table(labels)
commit = main.commit("Add labels")
commit.update_table(appended)
commit.create_table("labels", created)
try:
print(f"committed {commit.publish().commit_id}")
except (BranchMoved, PublishConflict):
print("main moved; nothing was published")A commit can change each Table once.
Verify the result
Open a Table session on main and read the new Table. See
Read rows. In Studio, select Refresh
resources to show the new Table in the sidebar.
Troubleshooting
| Result | Cause and action |
|---|---|
BranchMoved (Python), PublishError::BranchMoved (Rust) | Another writer moved the branch after you pinned it. Pin the branch again and stage the same Table in a new commit. |
PublishConflict (Python), PublishError::Conflict (Rust) | The branch already binds the name. Choose another name, or open the existing Table. |
PublishOutcomeUnknown (Python), PublishError::Unknown (Rust) | The publish response was lost. Recover the frozen commit in the error; in Rust, after ? it is Error::OutcomeUnknown, which does not carry the commit. See Write rows. |
Error::RegistrationUnknown (Rust) | The files were uploaded, but the response that registers the new version was lost. Pass the receipt in the error to client.register_prepared instead of uploading again. |
no write backend selected | The client is read-only. Configure a write backend or the embedded runtime. |
Without the SDK
The Tables HTTP API allocates Table storage and registers versions whose files a data plane already wrote. It does not accept rows. Use the Python, Rust or TypeScript SDK to write rows.