Skip to content
Open
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
4 changes: 4 additions & 0 deletions .openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ docs/ListWorkspacesResponse.md
docs/LoadManagedTableRequest.md
docs/LoadManagedTableResponse.md
docs/ManagedSchemaResponse.md
docs/ManagedTableConstantPerKeyResponse.md
docs/ManagedTableResponse.md
docs/MintUploadPartsRequest.md
docs/MintUploadPartsResponse.md
Expand All @@ -115,6 +116,7 @@ docs/TemporalProfileDetail.md
docs/TextProfileDetail.md
docs/UpdateEmbeddingProviderRequest.md
docs/UpdateEmbeddingProviderResponse.md
docs/UpdateManagedTableRequest.md
docs/UpdateSavedQueryRequest.md
docs/UploadSessionResponse.md
docs/UploadsApi.md
Expand Down Expand Up @@ -224,6 +226,7 @@ src/models/list_workspaces_response.rs
src/models/load_managed_table_request.rs
src/models/load_managed_table_response.rs
src/models/managed_schema_response.rs
src/models/managed_table_constant_per_key_response.rs
src/models/managed_table_response.rs
src/models/mint_upload_parts_request.rs
src/models/mint_upload_parts_response.rs
Expand All @@ -247,6 +250,7 @@ src/models/temporal_profile_detail.rs
src/models/text_profile_detail.rs
src/models/update_embedding_provider_request.rs
src/models/update_embedding_provider_response.rs
src/models/update_managed_table_request.rs
src/models/update_saved_query_request.rs
src/models/upload_session_response.rs
src/models/upsert_database_context_request.rs
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- feat(tables): add constant-per-key configuration support

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Record the breaking removal of key_determines. Add a ### Removed entry marked **Breaking:**, matching the 0.15.0 entries at CHANGELOG.md lines 41-57.

Release 0.15.0 shipped key_determines on the managed-table declaration models (CHANGELOG.md line 29). This regen renames that field to constant_per_key, adds a required constant_per_key field to TableInfo, and adds a parameter to TableInfo::new. All three changes break downstream compilation.

Failure scenario: a maintainer reads the current note, sees an added feature only, and runs ./scripts/release.sh prepare patch. Version 0.15.1 reaches crates.io. A consumer that sets decl.key_determines = Some(cols) upgrades inside the 0.15 range and fails to compile. No changelog entry explains the break. A crates.io publish is immutable, so the release cannot be corrected in place.


## [0.15.0] - 2026-09-02

Expand Down
2 changes: 1 addition & 1 deletion docs/AddManagedTableDecl.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**constant_per_key** | Option<**Vec<String>**> | 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** | Option<**Vec<String>**> | 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]
**key_determines** | Option<**Vec<String>**> | 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]
**name** | **String** | |
**partition_by** | Option<[**Vec<models::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** | Option<[**Vec<models::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. | [optional]
Expand Down
2 changes: 1 addition & 1 deletion docs/AddManagedTableRequest.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**constant_per_key** | Option<**Vec<String>**> | 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** | Option<**Vec<String>**> | 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]
**key_determines** | Option<**Vec<String>**> | 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]
**name** | **String** | |
**partition_by** | Option<[**Vec<models::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** | Option<[**Vec<models::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. | [optional]
Expand Down
34 changes: 34 additions & 0 deletions docs/ConnectionsApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Method | HTTP request | Description
[**get_table_profile**](ConnectionsApi.md#get_table_profile) | **GET** /v1/connections/{connection_id}/tables/{schema}/{table}/profile | Get table profile
[**list_connections**](ConnectionsApi.md#list_connections) | **GET** /v1/connections | List connections
[**load_managed_table**](ConnectionsApi.md#load_managed_table) | **POST** /v1/connections/{connection_id}/schemas/{schema}/tables/{table}/loads | Load managed table from inline data, upload, or query result
[**set_managed_table_constant_per_key**](ConnectionsApi.md#set_managed_table_constant_per_key) | **PUT** /v1/connections/{connection_id}/schemas/{schema}/tables/{table}/constant-per-key | Declare which columns are constant per key



Expand Down Expand Up @@ -292,3 +293,36 @@ Name | Type | Description | Required | Notes

[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)


## set_managed_table_constant_per_key

> models::ManagedTableConstantPerKeyResponse set_managed_table_constant_per_key(connection_id, schema, table, update_managed_table_request)
Declare which columns are constant per key

Replace the columns a table declares constant for a given key: for every row, any other row sharing its key holds the same value of these columns. Declaring this lets a keyed mutation (`delete`, `update`, `upsert`) narrow 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 do not discriminate. Unlike `partition_by` and `sorted_by`, this is NOT fixed when the table is created. It changes only which files a mutation opens, never how rows are written, so nothing stored becomes wrong when it changes and a populated table can adopt it with no rewrite. It takes effect on the next load. Send an empty array to revoke it, restoring the unrestricted search — this is the way to undo a declaration that turns out to be false. **This is correctness-affecting, not a hint.** If the assertion is false, a keyed mutation supersedes one version of a key and appends beside another, silently duplicating it, and the pruning conceals its own evidence because the file holding the missed row is never opened. Declare it only where the invariant is established.

### Parameters


Name | Type | Description | Required | Notes
------------- | ------------- | ------------- | ------------- | -------------
**connection_id** | **String** | Connection ID | [required] |
**schema** | **String** | Schema name | [required] |
**table** | **String** | Table name | [required] |
**update_managed_table_request** | [**UpdateManagedTableRequest**](UpdateManagedTableRequest.md) | | [required] |

### Return type

[**models::ManagedTableConstantPerKeyResponse**](ManagedTableConstantPerKeyResponse.md)

### Authorization

[WorkspaceId](../README.md#WorkspaceId), [BearerAuth](../README.md#BearerAuth)

### HTTP request headers

- **Content-Type**: application/json
- **Accept**: application/json

[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

2 changes: 1 addition & 1 deletion docs/DatabaseDefaultTableDecl.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**constant_per_key** | Option<**Vec<String>**> | 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** | Option<**Vec<String>**> | 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]
**key_determines** | Option<**Vec<String>**> | 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]
**name** | **String** | |
**partition_by** | Option<[**Vec<models::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** | Option<[**Vec<models::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. | [optional]
Expand Down
34 changes: 34 additions & 0 deletions docs/DatabasesApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Method | HTTP request | Description
[**list_databases**](DatabasesApi.md#list_databases) | **GET** /v1/databases | List databases
[**load_database_table**](DatabasesApi.md#load_database_table) | **POST** /v1/databases/{database_id}/schemas/{schema}/tables/{table}/loads | Load database table from inline data, upload, or query result
[**lookup_database_by_name**](DatabasesApi.md#lookup_database_by_name) | **GET** /v1/databases/by-name | Look up a database by name
[**set_database_table_constant_per_key**](DatabasesApi.md#set_database_table_constant_per_key) | **PUT** /v1/databases/{database_id}/schemas/{schema}/tables/{table}/constant-per-key | Declare which columns are constant per key



Expand Down Expand Up @@ -514,3 +515,36 @@ Name | Type | Description | Required | Notes

[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)


## set_database_table_constant_per_key

> models::ManagedTableConstantPerKeyResponse set_database_table_constant_per_key(database_id, schema, table, update_managed_table_request)
Declare which columns are constant per key

Replace the columns a table declares constant for a given key: for every row, any other row sharing its key holds the same value of these columns. Declaring this lets a keyed mutation (`delete`, `update`, `upsert`) narrow its search for prior versions to the values the upload carries. Unlike `partition_by` and `sorted_by`, this is NOT fixed when the table is created — it changes only which files a mutation opens, never how rows are written — so a populated table can adopt it with no rewrite, taking effect on the next load. Send an empty array to revoke it. **Correctness-affecting, not a hint.** If the assertion is false, a keyed mutation supersedes one version of a key and appends beside another, silently duplicating it. Declare it only where the invariant is established.

### Parameters


Name | Type | Description | Required | Notes
------------- | ------------- | ------------- | ------------- | -------------
**database_id** | **String** | Database ID | [required] |
**schema** | **String** | Schema name | [required] |
**table** | **String** | Table name | [required] |
**update_managed_table_request** | [**UpdateManagedTableRequest**](UpdateManagedTableRequest.md) | | [required] |

### Return type

[**models::ManagedTableConstantPerKeyResponse**](ManagedTableConstantPerKeyResponse.md)

### Authorization

[WorkspaceId](../README.md#WorkspaceId), [BearerAuth](../README.md#BearerAuth)

### HTTP request headers

- **Content-Type**: application/json
- **Accept**: application/json

[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

1 change: 1 addition & 0 deletions docs/JobType.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
| ResultRetention | result_retention |
| DucklakeCompaction | ducklake_compaction |
| DucklakeTableCompaction | ducklake_table_compaction |
| TableConstantsUpdate | table_constants_update |


[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
Expand Down
14 changes: 14 additions & 0 deletions docs/ManagedTableConstantPerKeyResponse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# ManagedTableConstantPerKeyResponse

## Properties

Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**connection_id** | **String** | |
**constant_per_key** | **Vec<String>** | The columns now declared constant per key. Empty means no declaration, i.e. the unrestricted search. |
**schema** | **String** | |
**table** | **String** | |

[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)


1 change: 1 addition & 0 deletions docs/TableInfo.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**columns** | Option<[**Vec<models::ColumnInfo>**](ColumnInfo.md)> | | [optional]
**connection** | **String** | |
**constant_per_key** | **Vec<String>** | Columns the table declares constant for a given key: for every row, any other row sharing its key holds the same value of these columns. Declaring this lets a keyed mutation narrow its search for prior versions to the values the upload carries. Empty when none is declared, which is the unrestricted search. Unlike `partition_by` and `sorted_by` this is NOT fixed at creation — it changes only which files a mutation opens, never how rows are written — so read it here rather than assuming a declaration took effect. |
**last_sync** | Option<**String**> | | [optional]
**partition_by** | [**Vec<models::TablePartitionKey>**](TablePartitionKey.md) | The table's partition keys, in the order they were declared when the table was created. Empty when the table is not partitioned. A table's storage layout is fixed when the table is created and cannot be changed afterwards, so this is how to confirm a table really was created with the layout that was asked for. The field is always present: an empty array means \"no partitioning declared\", which is not the same as a response that omits the field entirely. Reported for tables in a Hotdata instant database, which are the only ones whose layout is declared here. A table discovered from an external connection always reports an empty array — its layout belongs to the upstream system, so an empty array there means \"not known from here\", not \"confirmed unpartitioned\". |
**schema** | **String** | |
Expand Down
11 changes: 11 additions & 0 deletions docs/UpdateManagedTableRequest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# UpdateManagedTableRequest

## Properties

Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**constant_per_key** | Option<**Vec<String>**> | Columns whose value is the same for every row sharing this table's key. Send `[]` to revoke the declaration, which restores the unrestricted search on the next load — this is the kill switch if a declaration turns out to be false. **Correctness-affecting, not a hint.** If the assertion is false, a keyed mutation supersedes one version of a key and appends beside another, silently duplicating it. | [optional]

[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)


Loading
Loading