ServicesTables

Create a Table

Create a named Table from Arrow batches and publish it in one Catalog commit.

Available

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, RecordBatch or RecordBatchReader in Python, RecordBatch values in Rust, whose Arrow types the Rust SDK re-exports as spiral::arrow_array and spiral::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

ResultCause 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 selectedThe 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.

Found a problem? Edit this page or report an issue.

On this page