From ae21dc4734c908db77a456a38e05a11da9870b41 Mon Sep 17 00:00:00 2001 From: "hotdata-automation[bot]" <267177015+hotdata-automation[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 11:53:19 +0000 Subject: [PATCH] feat(databases): add default_schema field to database objects --- CHANGELOG.md | 3 +++ docs/AddManagedTableDecl.md | 1 + docs/AddManagedTableRequest.md | 1 + docs/CreateDatabaseRequest.md | 1 + docs/CreateDatabaseResponse.md | 1 + docs/DatabaseDefaultTableDecl.md | 1 + docs/DatabaseDetailResponse.md | 1 + docs/DatabaseSummary.md | 1 + src/models/add_managed_table_decl.rs | 5 ++++- src/models/add_managed_table_request.rs | 5 ++++- src/models/create_database_request.rs | 9 +++++++++ src/models/create_database_response.rs | 5 +++++ src/models/database_default_table_decl.rs | 5 ++++- src/models/database_detail_response.rs | 5 +++++ src/models/database_summary.rs | 6 +++++- 15 files changed, 46 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c17892c..e6b1f85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- feat(databases): add default_schema field to database objects ## [0.8.1] - 2026-07-09 diff --git a/docs/AddManagedTableDecl.md b/docs/AddManagedTableDecl.md index 4b0dad8..64572b4 100644 --- a/docs/AddManagedTableDecl.md +++ b/docs/AddManagedTableDecl.md @@ -4,6 +4,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**key** | Option<**Vec**> | 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] **name** | **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) diff --git a/docs/AddManagedTableRequest.md b/docs/AddManagedTableRequest.md index 4d96d01..94f858c 100644 --- a/docs/AddManagedTableRequest.md +++ b/docs/AddManagedTableRequest.md @@ -4,6 +4,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**key** | Option<**Vec**> | 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] **name** | **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) diff --git a/docs/CreateDatabaseRequest.md b/docs/CreateDatabaseRequest.md index da653fc..3d237a3 100644 --- a/docs/CreateDatabaseRequest.md +++ b/docs/CreateDatabaseRequest.md @@ -5,6 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **default_catalog** | Option<**String**> | Optional name the database's auto-created default catalog answers to inside its query scope. Must be a valid SQL identifier (`[a-z0-9_]`, not starting with a digit) and may not collide with the reserved catalog names `hotdata`, `datasets`, or `information_schema`. Defaults to `default` when omitted, so `default.main.` keeps working. | [optional] +**default_schema** | Option<**String**> | Optional schema that unqualified table names resolve to inside this database's query scope. Must be a valid SQL identifier (`[a-z0-9_]`, not starting with a digit). When omitted, a database that declares exactly one schema adopts that schema as its default; otherwise unqualified names resolve to `main`. Fully-qualified names (`..
`) are unaffected, and a per-query `default_schema` still takes precedence. | [optional] **expires_at** | Option<**String**> | When this database expires. Accepts either an RFC 3339 timestamp (e.g. `\"2026-06-01T00:00:00Z\"`) or a relative duration suffixed with `h` (hours), `m` (minutes), or `d` (days) — for example `\"24h\"`, `\"48h\"`, or `\"7d\"`. Omitted (or empty) means the database never expires. Expiry is best-effort: the database will not be deleted before `expires_at`, but cleanup may run later than the exact timestamp. | [optional] **name** | Option<**String**> | Optional free-form display label (for UIs/CLIs). Not unique. Not an identifier — databases are always addressed by `id`. Accepts the legacy `description` key as an alias so clients that predate the rename keep populating this field. | [optional] **schemas** | Option<[**Vec**](DatabaseDefaultSchemaDecl.md)> | Optional schemas/tables to declare on the database's auto-created default catalog. Tables declared here can be loaded via the standard managed-table load endpoint targeting `default_connection_id`. Omitted or empty means the default catalog starts empty. | [optional] diff --git a/docs/CreateDatabaseResponse.md b/docs/CreateDatabaseResponse.md index b0db0e3..8c879ca 100644 --- a/docs/CreateDatabaseResponse.md +++ b/docs/CreateDatabaseResponse.md @@ -6,6 +6,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **default_catalog** | **String** | Name the database's default catalog answers to inside its query scope (`default` unless overridden at create time). | **default_connection_id** | **String** | Internal id of the connection that backs this database's `default` catalog. Workspace-level connection endpoints (list, get, health, delete, cache purge) refuse to act on this id — it is exposed only for the managed-tables load endpoint (`POST /v1/connections/{id}/schemas/{s}/tables/{t}/loads`) so callers can publish parquet into tables declared at database-create time. Addressing it directly in SQL is not the recommended path — use `default` inside an `X-Database-Id` scope instead. | +**default_schema** | **String** | Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time. | **expires_at** | Option<**String**> | When this database expires. | [optional] **id** | **String** | | **name** | Option<**String**> | | [optional] diff --git a/docs/DatabaseDefaultTableDecl.md b/docs/DatabaseDefaultTableDecl.md index 45ddc93..2d18c3d 100644 --- a/docs/DatabaseDefaultTableDecl.md +++ b/docs/DatabaseDefaultTableDecl.md @@ -4,6 +4,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**key** | Option<**Vec**> | 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] **name** | **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) diff --git a/docs/DatabaseDetailResponse.md b/docs/DatabaseDetailResponse.md index 6c21585..3975402 100644 --- a/docs/DatabaseDetailResponse.md +++ b/docs/DatabaseDetailResponse.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes **created_at** | Option<**String**> | When the database was created. | [optional] **default_catalog** | **String** | Name the database's default catalog answers to inside its query scope (`default` unless overridden at create time). | **default_connection_id** | **String** | | +**default_schema** | **String** | Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time. | **expires_at** | Option<**String**> | When this database expires. | [optional] **id** | **String** | | **name** | Option<**String**> | | [optional] diff --git a/docs/DatabaseSummary.md b/docs/DatabaseSummary.md index 22eecb4..39a98a6 100644 --- a/docs/DatabaseSummary.md +++ b/docs/DatabaseSummary.md @@ -6,6 +6,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **created_at** | Option<**String**> | When the database was created. | [optional] **default_catalog** | **String** | Name the database's default catalog answers to inside its query scope. | +**default_schema** | **String** | Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time. | **expires_at** | Option<**String**> | | [optional] **id** | **String** | | **name** | Option<**String**> | | [optional] diff --git a/src/models/add_managed_table_decl.rs b/src/models/add_managed_table_decl.rs index cf8507c..80badb1 100644 --- a/src/models/add_managed_table_decl.rs +++ b/src/models/add_managed_table_decl.rs @@ -14,6 +14,9 @@ use serde::{Deserialize, Serialize}; /// AddManagedTableDecl : One table declaration inside an add-schema request body. #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct AddManagedTableDecl { + /// 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. + #[serde(rename = "key", skip_serializing_if = "Option::is_none")] + pub key: Option>, #[serde(rename = "name")] pub name: String, } @@ -21,6 +24,6 @@ pub struct AddManagedTableDecl { impl AddManagedTableDecl { /// One table declaration inside an add-schema request body. pub fn new(name: String) -> AddManagedTableDecl { - AddManagedTableDecl { name } + AddManagedTableDecl { key: None, name } } } diff --git a/src/models/add_managed_table_request.rs b/src/models/add_managed_table_request.rs index ac990e1..b11e759 100644 --- a/src/models/add_managed_table_request.rs +++ b/src/models/add_managed_table_request.rs @@ -14,6 +14,9 @@ use serde::{Deserialize, Serialize}; /// AddManagedTableRequest : Request body for adding a table to an existing schema: `POST /v1/connections/{id}/schemas/{schema}/tables` and `POST /v1/databases/{id}/schemas/{schema}/tables`. #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct AddManagedTableRequest { + /// 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. + #[serde(rename = "key", skip_serializing_if = "Option::is_none")] + pub key: Option>, #[serde(rename = "name")] pub name: String, } @@ -21,6 +24,6 @@ pub struct AddManagedTableRequest { impl AddManagedTableRequest { /// Request body for adding a table to an existing schema: `POST /v1/connections/{id}/schemas/{schema}/tables` and `POST /v1/databases/{id}/schemas/{schema}/tables`. pub fn new(name: String) -> AddManagedTableRequest { - AddManagedTableRequest { name } + AddManagedTableRequest { key: None, name } } } diff --git a/src/models/create_database_request.rs b/src/models/create_database_request.rs index d9822f5..39e98a6 100644 --- a/src/models/create_database_request.rs +++ b/src/models/create_database_request.rs @@ -22,6 +22,14 @@ pub struct CreateDatabaseRequest { skip_serializing_if = "Option::is_none" )] pub default_catalog: Option>, + /// Optional schema that unqualified table names resolve to inside this database's query scope. Must be a valid SQL identifier (`[a-z0-9_]`, not starting with a digit). When omitted, a database that declares exactly one schema adopts that schema as its default; otherwise unqualified names resolve to `main`. Fully-qualified names (`..
`) are unaffected, and a per-query `default_schema` still takes precedence. + #[serde( + rename = "default_schema", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub default_schema: Option>, /// When this database expires. Accepts either an RFC 3339 timestamp (e.g. `\"2026-06-01T00:00:00Z\"`) or a relative duration suffixed with `h` (hours), `m` (minutes), or `d` (days) — for example `\"24h\"`, `\"48h\"`, or `\"7d\"`. Omitted (or empty) means the database never expires. Expiry is best-effort: the database will not be deleted before `expires_at`, but cleanup may run later than the exact timestamp. #[serde( rename = "expires_at", @@ -48,6 +56,7 @@ impl CreateDatabaseRequest { pub fn new() -> CreateDatabaseRequest { CreateDatabaseRequest { default_catalog: None, + default_schema: None, expires_at: None, name: None, schemas: None, diff --git a/src/models/create_database_response.rs b/src/models/create_database_response.rs index 52c788d..44c9ef8 100644 --- a/src/models/create_database_response.rs +++ b/src/models/create_database_response.rs @@ -20,6 +20,9 @@ pub struct CreateDatabaseResponse { /// Internal id of the connection that backs this database's `default` catalog. Workspace-level connection endpoints (list, get, health, delete, cache purge) refuse to act on this id — it is exposed only for the managed-tables load endpoint (`POST /v1/connections/{id}/schemas/{s}/tables/{t}/loads`) so callers can publish parquet into tables declared at database-create time. Addressing it directly in SQL is not the recommended path — use `default` inside an `X-Database-Id` scope instead. #[serde(rename = "default_connection_id")] pub default_connection_id: String, + /// Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time. + #[serde(rename = "default_schema")] + pub default_schema: String, /// When this database expires. #[serde( rename = "expires_at", @@ -44,11 +47,13 @@ impl CreateDatabaseResponse { pub fn new( default_catalog: String, default_connection_id: String, + default_schema: String, id: String, ) -> CreateDatabaseResponse { CreateDatabaseResponse { default_catalog, default_connection_id, + default_schema, expires_at: None, id, name: None, diff --git a/src/models/database_default_table_decl.rs b/src/models/database_default_table_decl.rs index c7a51db..a677fd5 100644 --- a/src/models/database_default_table_decl.rs +++ b/src/models/database_default_table_decl.rs @@ -14,6 +14,9 @@ use serde::{Deserialize, Serialize}; /// DatabaseDefaultTableDecl : One table declaration inside a default-catalog schema, supplied at database-create time. #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct DatabaseDefaultTableDecl { + /// 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. + #[serde(rename = "key", skip_serializing_if = "Option::is_none")] + pub key: Option>, #[serde(rename = "name")] pub name: String, } @@ -21,6 +24,6 @@ pub struct DatabaseDefaultTableDecl { impl DatabaseDefaultTableDecl { /// One table declaration inside a default-catalog schema, supplied at database-create time. pub fn new(name: String) -> DatabaseDefaultTableDecl { - DatabaseDefaultTableDecl { name } + DatabaseDefaultTableDecl { key: None, name } } } diff --git a/src/models/database_detail_response.rs b/src/models/database_detail_response.rs index 9a6eb44..9e3c91d 100644 --- a/src/models/database_detail_response.rs +++ b/src/models/database_detail_response.rs @@ -29,6 +29,9 @@ pub struct DatabaseDetailResponse { pub default_catalog: String, #[serde(rename = "default_connection_id")] pub default_connection_id: String, + /// Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time. + #[serde(rename = "default_schema")] + pub default_schema: String, /// When this database expires. #[serde( rename = "expires_at", @@ -54,6 +57,7 @@ impl DatabaseDetailResponse { attachments: Vec, default_catalog: String, default_connection_id: String, + default_schema: String, id: String, ) -> DatabaseDetailResponse { DatabaseDetailResponse { @@ -61,6 +65,7 @@ impl DatabaseDetailResponse { created_at: None, default_catalog, default_connection_id, + default_schema, expires_at: None, id, name: None, diff --git a/src/models/database_summary.rs b/src/models/database_summary.rs index 938479c..536dabf 100644 --- a/src/models/database_summary.rs +++ b/src/models/database_summary.rs @@ -25,6 +25,9 @@ pub struct DatabaseSummary { /// Name the database's default catalog answers to inside its query scope. #[serde(rename = "default_catalog")] pub default_catalog: String, + /// Schema that unqualified table names resolve to inside this database's query scope. `main` unless the database declares a single schema or a `default_schema` was set at create time. + #[serde(rename = "default_schema")] + pub default_schema: String, #[serde( rename = "expires_at", default, @@ -45,10 +48,11 @@ pub struct DatabaseSummary { impl DatabaseSummary { /// Summary item in GET /databases - pub fn new(default_catalog: String, id: String) -> DatabaseSummary { + pub fn new(default_catalog: String, default_schema: String, id: String) -> DatabaseSummary { DatabaseSummary { created_at: None, default_catalog, + default_schema, expires_at: None, id, name: None,