Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ docs/SavedQuerySummary.md
docs/SavedQueryVersionInfo.md
docs/SubmitJobResponse.md
docs/TableInfo.md
docs/TableLayout.md
docs/TablePartitionKey.md
docs/TableProfileResponse.md
docs/TableSortKey.md
Expand Down Expand Up @@ -249,6 +250,7 @@ hotdata/models/saved_query_summary.py
hotdata/models/saved_query_version_info.py
hotdata/models/submit_job_response.py
hotdata/models/table_info.py
hotdata/models/table_layout.py
hotdata/models/table_partition_key.py
hotdata/models/table_profile_response.py
hotdata/models/table_sort_key.py
Expand Down Expand Up @@ -378,6 +380,7 @@ test/test_saved_query_summary.py
test/test_saved_query_version_info.py
test/test_submit_job_response.py
test/test_table_info.py
test/test_table_layout.py
test/test_table_partition_key.py
test/test_table_profile_response.py
test/test_table_sort_key.py
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- chore(loads): document table write locking and retry behavior

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Add an entry under ### Added for the new TableLayout enum and the layout field (not blocking).

The current entry only describes load locking documentation. The PR also adds public API: hotdata.TableLayout and layout on AddManagedTableDecl, AddManagedTableRequest, DatabaseDefaultTableDecl, and TableInfo. Keep a Changelog lists new features under Added. Users who read the changelog do not learn about the new field.

- feat(jobs): add ivf_rebalance_sweep job type
- chore(query): clarify write statement and dialect documentation
- chore: add 503 service unavailable response to load endpoints
Expand Down
1 change: 1 addition & 0 deletions docs/AddManagedTableDecl.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**constant_per_key** | **List[str]** | Columns whose value is determined by this table's `key`: for every uploaded row, every stored row sharing its key holds the same value of these columns. Declaring this lets a keyed mutation (`delete`, `update`, `upsert`) restrict its search for prior versions to the values the upload carries, which prunes far harder than the key alone when the key's own file statistics are weak. Omit (the default) for the unrestricted search. **Correctness-affecting, not a hint.** If the assertion is false, a mutation supersedes one version of a key and appends beside another, silently duplicating it. Declare it only where the invariant is established. | [optional]
**key** | **List[str]** | Columns that uniquely identify a row, enabling the key-based load modes (`delete`, `update`, `upsert`) on this table: those loads match rows by these columns' values. Omit (the default) to declare no key; the table can still be loaded with `replace` and `append`, but key-based modes are then rejected. | [optional]
**layout** | [**TableLayout**](TableLayout.md) | Storage layout of the table: `analytical` (the default), or `point_lookup`, which writes small data pages so the table's rows can be fetched by id cheaply, which is what a vector index's answers do; analytical scans of it read more pages. Declared when the table is created and fixed thereafter. | [optional]
**name** | **str** | |
**partition_by** | [**List[TablePartitionKey]**](TablePartitionKey.md) | Partition keys for this table, applied in order. Omit for no partitioning. Declared when the table is created and fixed thereafter. | [optional]
**sorted_by** | [**List[TableSortKey]**](TableSortKey.md) | Sort keys for this table, applied in order. Omit for no sort order. Declared when the table is created and fixed thereafter. A table with a sort order cannot be indexed: creating any index on it is refused, so leave this empty on a table you plan to search. | [optional]
Expand Down
1 change: 1 addition & 0 deletions docs/AddManagedTableRequest.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**constant_per_key** | **List[str]** | Columns whose value is determined by this table's `key`: for every uploaded row, every stored row sharing its key holds the same value of these columns. Declaring this lets a keyed mutation (`delete`, `update`, `upsert`) restrict its search for prior versions to the values the upload carries, which prunes far harder than the key alone when the key's own file statistics are weak. Omit (the default) for the unrestricted search. **Correctness-affecting, not a hint.** If the assertion is false, a mutation supersedes one version of a key and appends beside another, silently duplicating it. Declare it only where the invariant is established. | [optional]
**key** | **List[str]** | Columns that uniquely identify a row, enabling the key-based load modes (`delete`, `update`, `upsert`) on this table: those loads match rows by these columns' values. Omit (the default) to declare no key; the table can still be loaded with `replace` and `append`, but key-based modes are then rejected. | [optional]
**layout** | [**TableLayout**](TableLayout.md) | Storage layout of the table: `analytical` (the default), or `point_lookup`, which writes small data pages so the table's rows can be fetched by id cheaply, which is what a vector index's answers do; analytical scans of it read more pages. Declared when the table is created and fixed thereafter. | [optional]
**name** | **str** | |
**partition_by** | [**List[TablePartitionKey]**](TablePartitionKey.md) | Partition keys for this table, applied in order. Omit for no partitioning. Declared when the table is created and fixed thereafter. | [optional]
**sorted_by** | [**List[TableSortKey]**](TableSortKey.md) | Sort keys for this table, applied in order. Omit for no sort order. Declared when the table is created and fixed thereafter. A table with a sort order cannot be indexed: creating any index on it is refused, so leave this empty on a table you plan to search. | [optional]
Expand Down
4 changes: 2 additions & 2 deletions docs/ConnectionsApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ This endpoint does not need any parameter.

Load managed table from inline data, upload, or query result

Publish data as the new contents of a managed table from one of three sources — provide exactly one. With `data`, CSV text is sent inline in this request, up to 2 MiB; column types are detected from the data unless `columns` declares them, and a larger payload is rejected with 413 and the error code `INLINE_DATA_TOO_LARGE`, at which point the data should be uploaded and loaded by `upload_id` instead. With `upload_id`, a previously-uploaded file is published: CSV, JSON, and Parquet are supported; the format is auto-detected from the upload's `Content-Type` and file contents, or set explicitly via the `format` field. With `result_id`, a persisted query result is copied into the table, so the table keeps its data even after the result expires; a result can be loaded into any number of tables. If the target table (or its schema) has not been declared yet, it is created automatically as part of the load — declaring tables up front is optional. `mode` selects how the data is applied and accepts five values: `replace` makes the uploaded rows the table's entire contents, `append` inserts them on top of the existing data, and `delete`, `update`, and `upsert` match rows by key — removing, replacing, or inserting-or-replacing the matched rows respectively. The three key-matching modes need a key: the one the table was created with, or one given in `key` on the request. Concurrent loads against the same upload return 409. For an upload or inline data, set `async` to run the load in the background and get back a job ID to poll; add `async_after_ms` to wait briefly for it to finish before falling back to a job ID. A `result_id` load runs synchronously.
Publish data as the new contents of a managed table from one of three sources — provide exactly one. With `data`, CSV text is sent inline in this request, up to 2 MiB; column types are detected from the data unless `columns` declares them, and a larger payload is rejected with 413 and the error code `INLINE_DATA_TOO_LARGE`, at which point the data should be uploaded and loaded by `upload_id` instead. With `upload_id`, a previously-uploaded file is published: CSV, JSON, and Parquet are supported; the format is auto-detected from the upload's `Content-Type` and file contents, or set explicitly via the `format` field. With `result_id`, a persisted query result is copied into the table, so the table keeps its data even after the result expires; a result can be loaded into any number of tables. If the target table (or its schema) has not been declared yet, it is created automatically as part of the load — declaring tables up front is optional. `mode` selects how the data is applied and accepts five values: `replace` makes the uploaded rows the table's entire contents, `append` inserts them on top of the existing data, and `delete`, `update`, and `upsert` match rows by key — removing, replacing, or inserting-or-replacing the matched rows respectively. The three key-matching modes need a key: the one the table was created with, or one given in `key` on the request. Concurrent loads against the same upload return 409. For an upload or inline data, set `async` to run the load in the background and get back a job ID to poll; add `async_after_ms` to wait briefly for it to finish before falling back to a job ID. A `result_id` load runs synchronously. While background maintenance holds the table, a load waits for it to finish, for up to 60 seconds, before it starts, in every mode; with `async`, the 202 can arrive only after that wait. A load refused because another write to the table is running gets 409 with the error code `RESOURCE_LOCKED` and a `Retry-After` header.

### Example

Expand Down Expand Up @@ -809,7 +809,7 @@ Name | Type | Description | Notes
**202** | Load accepted and running in the background; poll the returned job for status and result | - |
**400** | Invalid request (bad mode, none or several of `upload_id`/`result_id`/`data`, `format` combined with `result_id`, `columns` without `data`, a non-CSV inline `format`, unparseable inline data, non-managed connection, invalid identifier, bad parquet, or the result failed to compute) | - |
**404** | Connection, upload, or result not found, or the table was deleted | - |
**409** | Upload already consumed or in flight, the result is still being computed, or the incoming data changes a column's type incompatibly (only widening to a larger compatible type can be applied automatically); the existing data is unchanged and remains queryable | - |
**409** | Upload already consumed or in flight, the result is still being computed, or the incoming data changes a column's type incompatibly (only widening to a larger compatible type can be applied automatically); the existing data is unchanged and remains queryable. Error code `RESOURCE_LOCKED`: another write to the table is running; retry after the `Retry-After` delay. | - |
**413** | Inline `data` is over the 2 MiB limit (error code `INLINE_DATA_TOO_LARGE`); upload the data and load it by `upload_id` instead | - |
**503** | The catalog is busy: no pooled catalog connection came free within the acquire window (error code `CATALOG_BUSY`). The load may already have committed data if the timeout hit after the write, so check the table, or load with an idempotency key, before retrying after the `Retry-After` delay | - |

Expand Down
1 change: 1 addition & 0 deletions docs/DatabaseDefaultTableDecl.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**constant_per_key** | **List[str]** | Columns whose value is determined by this table's `key`: for every uploaded row, every stored row sharing its key holds the same value of these columns. Declaring this lets a keyed mutation (`delete`, `update`, `upsert`) restrict its search for prior versions to the values the upload carries, which prunes far harder than the key alone when the key's own file statistics are weak. Omit (the default) for the unrestricted search. **Correctness-affecting, not a hint.** If the assertion is false, a mutation supersedes one version of a key and appends beside another, silently duplicating it. Declare it only where the invariant is established. | [optional]
**key** | **List[str]** | Columns that uniquely identify a row, enabling the key-based load modes (`delete`, `update`, `upsert`) on this table: those loads match rows by these columns' values. Omit (the default) to declare no key; the table can still be loaded with `replace` and `append`, but key-based modes are then rejected. | [optional]
**layout** | [**TableLayout**](TableLayout.md) | Storage layout of the table: `analytical` (the default), or `point_lookup`, which writes small data pages so the table's rows can be fetched by id cheaply, which is what a vector index's answers do; analytical scans of it read more pages. Declared when the table is created and fixed thereafter. | [optional]
**name** | **str** | |
**partition_by** | [**List[TablePartitionKey]**](TablePartitionKey.md) | Partition keys for this table, applied in order. Omit for no partitioning. Declared when the table is created and fixed thereafter. | [optional]
**sorted_by** | [**List[TableSortKey]**](TableSortKey.md) | Sort keys for this table, applied in order. Omit for no sort order. Declared when the table is created and fixed thereafter. A table with a sort order cannot be indexed: creating any index on it is refused, so leave this empty on a table you plan to search. | [optional]
Expand Down
4 changes: 2 additions & 2 deletions docs/DatabasesApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -1274,7 +1274,7 @@ Name | Type | Description | Notes

Load database table from inline data, upload, or query result

Publish data as the new contents of a table on the database's default catalog, from one of three sources — provide exactly one. The database-scoped equivalent of the connection-scoped managed-table load — addressed by `database_id`, so no `default_connection_id` is needed. With `data`, CSV text is sent inline in this request, up to 2 MiB; column types are detected from the data unless `columns` declares them, and a larger payload is rejected with 413 and the error code `INLINE_DATA_TOO_LARGE`, at which point the data should be uploaded and loaded by `upload_id` instead. With `upload_id`, a previously-uploaded file is published: CSV, JSON, and Parquet are supported; the format is auto-detected or set via `format`. With `result_id`, a persisted query result is copied into the table, so the table keeps its data even after the result expires. If the target table (or its schema) has not been declared yet, it is created automatically as part of the load — declaring tables up front is optional. `mode` selects how the data is applied: `replace` overwrites the table's contents, `append` inserts the new rows on top of the existing data. Concurrent loads against the same upload return 409. For an upload or inline data, set `async` to run the load in the background and get back a job ID to poll; add `async_after_ms` to wait briefly for it to finish before falling back to a job ID. A `result_id` load runs synchronously.
Publish data as the new contents of a table on the database's default catalog, from one of three sources — provide exactly one. The database-scoped equivalent of the connection-scoped managed-table load — addressed by `database_id`, so no `default_connection_id` is needed. With `data`, CSV text is sent inline in this request, up to 2 MiB; column types are detected from the data unless `columns` declares them, and a larger payload is rejected with 413 and the error code `INLINE_DATA_TOO_LARGE`, at which point the data should be uploaded and loaded by `upload_id` instead. With `upload_id`, a previously-uploaded file is published: CSV, JSON, and Parquet are supported; the format is auto-detected or set via `format`. With `result_id`, a persisted query result is copied into the table, so the table keeps its data even after the result expires. If the target table (or its schema) has not been declared yet, it is created automatically as part of the load — declaring tables up front is optional. `mode` selects how the data is applied: `replace` overwrites the table's contents, `append` inserts the new rows on top of the existing data. Concurrent loads against the same upload return 409. For an upload or inline data, set `async` to run the load in the background and get back a job ID to poll; add `async_after_ms` to wait briefly for it to finish before falling back to a job ID. A `result_id` load runs synchronously. While background maintenance holds the table, a load waits for it to finish, for up to 60 seconds, before it starts, in every mode; with `async`, the 202 can arrive only after that wait. A load refused because another write to the table is running gets 409 with the error code `RESOURCE_LOCKED` and a `Retry-After` header.

### Example

Expand Down Expand Up @@ -1364,7 +1364,7 @@ Name | Type | Description | Notes
**202** | Load accepted and running in the background; poll the returned job for status and result | - |
**400** | Invalid request (bad mode, none or several of `upload_id`/`result_id`/`data`, `format` combined with `result_id`, `columns` without `data`, a non-CSV inline `format`, unparseable inline data, invalid identifier, bad parquet, or the result failed to compute) | - |
**404** | Database, upload, or result not found, or the table was deleted | - |
**409** | Upload already consumed or in flight, the result is still being computed, or the incoming data changes a column's type incompatibly (only widening to a larger compatible type can be applied automatically); the existing data is unchanged and remains queryable | - |
**409** | Upload already consumed or in flight, the result is still being computed, or the incoming data changes a column's type incompatibly (only widening to a larger compatible type can be applied automatically); the existing data is unchanged and remains queryable. Error code `RESOURCE_LOCKED`: another write to the table is running; retry after the `Retry-After` delay. | - |
**413** | Inline `data` is over the 2 MiB limit (error code `INLINE_DATA_TOO_LARGE`); upload the data and load it by `upload_id` instead | - |
**503** | The catalog is busy: no pooled catalog connection came free within the acquire window (error code `CATALOG_BUSY`). The load may already have committed data if the timeout hit after the write, so check the table, or load with an idempotency key, before retrying after the `Retry-After` delay | - |

Expand Down
Loading
Loading