From 1314450f6e22cb74175dc4387bd50d15ae70b4b2 Mon Sep 17 00:00:00 2001 From: "hotdata-automation[bot]" <267177015+hotdata-automation[bot]@users.noreply.github.com> Date: Wed, 23 Sep 2026 10:39:49 +0000 Subject: [PATCH] feat(databases): add description field to fork lineage --- CHANGELOG.md | 1 + docs/DatabasesApi.md | 2 +- docs/ForkDatabaseRequest.md | 1 + docs/ForkedFromInfo.md | 1 + docs/LineageAncestorInfo.md | 1 + docs/LineageForkInfo.md | 1 + src/apis/databases_api.rs | 2 +- src/models/fork_database_request.rs | 9 +++++++++ src/models/forked_from_info.rs | 9 +++++++++ src/models/lineage_ancestor_info.rs | 9 +++++++++ src/models/lineage_fork_info.rs | 9 +++++++++ 11 files changed, 43 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e8e3ce..ff3c922 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- feat(databases): add description field to fork lineage - chore(databases): simplify fork error description ## [0.18.1] - 2026-09-18 diff --git a/docs/DatabasesApi.md b/docs/DatabasesApi.md index cd3148a..8efd84e 100644 --- a/docs/DatabasesApi.md +++ b/docs/DatabasesApi.md @@ -303,7 +303,7 @@ Name | Type | Description | Required | Notes > models::CreateDatabaseResponse fork_database(database_id, fork_database_request) Fork database -Create a new database that is an independent fork of an existing one. The fork has its own default catalog and contains the same schemas, tables, and data as the source; the source is left unchanged. External catalogs attached to the source are re-attached to the fork. Optional `name` sets the fork's display label; when omitted, the fork takes the source's label followed by a short suffix derived from the fork's own ID, so the two stay distinguishable. Optional `expires_at` sets when the fork expires — accepts an RFC 3339 timestamp or a relative duration suffixed with `h` (hours), `m` (minutes), or `d` (days), e.g. `24h`, `90m`, `7d`. When omitted, a still-future expiry on the source is carried over; otherwise the fork never expires. Any indexes on the source's tables are not carried over. A fork adds no stored bytes at first, because it starts out sharing the source's storage. Routine maintenance can later rewrite a shared table into the fork's own storage, and the fork is billed for that copy from then on. Whether and when that happens depends on the table, so a fork that is only read can keep sharing indefinitely. +Create a new database that is an independent fork of an existing one. The fork has its own default catalog and contains the same schemas, tables, and data as the source; the source is left unchanged. External catalogs attached to the source are re-attached to the fork. Optional `description` records why the fork is being taken; it is returned with the fork's `forked_from` and in the lineage of both databases. Optional `name` sets the fork's display label; when omitted, the fork takes the source's label followed by a short suffix derived from the fork's own ID, so the two stay distinguishable. Optional `expires_at` sets when the fork expires — accepts an RFC 3339 timestamp or a relative duration suffixed with `h` (hours), `m` (minutes), or `d` (days), e.g. `24h`, `90m`, `7d`. When omitted, a still-future expiry on the source is carried over; otherwise the fork never expires. Any indexes on the source's tables are not carried over. A fork adds no stored bytes at first, because it starts out sharing the source's storage. Routine maintenance can later rewrite a shared table into the fork's own storage, and the fork is billed for that copy from then on. Whether and when that happens depends on the table, so a fork that is only read can keep sharing indefinitely. ### Parameters diff --git a/docs/ForkDatabaseRequest.md b/docs/ForkDatabaseRequest.md index 0b1b556..0446708 100644 --- a/docs/ForkDatabaseRequest.md +++ b/docs/ForkDatabaseRequest.md @@ -4,6 +4,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**description** | Option<**String**> | Optional note saying why the fork is being taken — for example \"backfill test before the March migration\". It is kept with the record of the fork and returned wherever that record appears: `forked_from` on the fork, and the fork's entry in both databases' lineage. Surrounding whitespace is trimmed, and an empty value is treated as absent. At most 4096 bytes; line breaks and tabs are allowed, other control characters are not. | [optional] **expires_at** | Option<**String**> | When the fork 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\"` or `\"7d\"`. When omitted, a still-future expiry on the source is carried over; otherwise the fork never expires. | [optional] **name** | Option<**String**> | Optional display label for the fork. When omitted, the fork takes the source's label followed by a short suffix derived from the fork's own ID, so the two stay distinguishable. A source with no usable label of its own gives a fork named from that ID alone. | [optional] diff --git a/docs/ForkedFromInfo.md b/docs/ForkedFromInfo.md index 7f7bbd1..918dd85 100644 --- a/docs/ForkedFromInfo.md +++ b/docs/ForkedFromInfo.md @@ -5,6 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **database_id** | **String** | ID of the database that was forked. The database may since have been deleted — the record outlives it — so this is not guaranteed to resolve. | +**description** | Option<**String**> | Why the fork was taken, as given when it was created. Absent when none was given. | [optional] **forked_at** | Option<**String**> | When the fork was taken. | [optional] **name** | Option<**String**> | Display label the source carried when the fork was taken, kept so a deleted source still reads as more than an ID. | [optional] **snapshot_id** | Option<**i64**> | Marks the version of the source that this fork copied — its table set and their contents as of that moment. It is a point in time rather than a per-database revision count, so two forks of a source that did not change still report different values, and the numbers are not a way to tell whether a source has changed. Absent only on forks taken before the version was recorded. | [optional] diff --git a/docs/LineageAncestorInfo.md b/docs/LineageAncestorInfo.md index 969f3ac..37aff93 100644 --- a/docs/LineageAncestorInfo.md +++ b/docs/LineageAncestorInfo.md @@ -5,6 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **database_id** | **String** | | +**description** | Option<**String**> | Why the next database down the chain was forked from it, as given at the time. Absent when none was given. | [optional] **exists** | **bool** | False once the ancestor has been deleted. Its place in the chain is kept either way, and the ancestry continues past it. | **forked_at** | Option<**String**> | When the next database down the chain was forked from it. | [optional] **name** | Option<**String**> | The ancestor's current label, or the one captured at fork time when it no longer exists. | [optional] diff --git a/docs/LineageForkInfo.md b/docs/LineageForkInfo.md index 94d47a3..28128f0 100644 --- a/docs/LineageForkInfo.md +++ b/docs/LineageForkInfo.md @@ -5,6 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **database_id** | **String** | | +**description** | Option<**String**> | Why the fork was taken, as given when it was created. Absent when none was given. | [optional] **exists** | **bool** | False once the fork has been deleted. The record of it is kept either way, so a source can still account for everything taken from it. | **forked_at** | Option<**String**> | When the fork was taken. | [optional] **name** | Option<**String**> | Absent once the fork has been deleted — only the record of it remains. | [optional] diff --git a/src/apis/databases_api.rs b/src/apis/databases_api.rs index 75c8d7b..6c7e8ff 100644 --- a/src/apis/databases_api.rs +++ b/src/apis/databases_api.rs @@ -754,7 +754,7 @@ pub async fn detach_database_catalog( } } -/// Create a new database that is an independent fork of an existing one. The fork has its own default catalog and contains the same schemas, tables, and data as the source; the source is left unchanged. External catalogs attached to the source are re-attached to the fork. Optional `name` sets the fork's display label; when omitted, the fork takes the source's label followed by a short suffix derived from the fork's own ID, so the two stay distinguishable. Optional `expires_at` sets when the fork expires — accepts an RFC 3339 timestamp or a relative duration suffixed with `h` (hours), `m` (minutes), or `d` (days), e.g. `24h`, `90m`, `7d`. When omitted, a still-future expiry on the source is carried over; otherwise the fork never expires. Any indexes on the source's tables are not carried over. A fork adds no stored bytes at first, because it starts out sharing the source's storage. Routine maintenance can later rewrite a shared table into the fork's own storage, and the fork is billed for that copy from then on. Whether and when that happens depends on the table, so a fork that is only read can keep sharing indefinitely. +/// Create a new database that is an independent fork of an existing one. The fork has its own default catalog and contains the same schemas, tables, and data as the source; the source is left unchanged. External catalogs attached to the source are re-attached to the fork. Optional `description` records why the fork is being taken; it is returned with the fork's `forked_from` and in the lineage of both databases. Optional `name` sets the fork's display label; when omitted, the fork takes the source's label followed by a short suffix derived from the fork's own ID, so the two stay distinguishable. Optional `expires_at` sets when the fork expires — accepts an RFC 3339 timestamp or a relative duration suffixed with `h` (hours), `m` (minutes), or `d` (days), e.g. `24h`, `90m`, `7d`. When omitted, a still-future expiry on the source is carried over; otherwise the fork never expires. Any indexes on the source's tables are not carried over. A fork adds no stored bytes at first, because it starts out sharing the source's storage. Routine maintenance can later rewrite a shared table into the fork's own storage, and the fork is billed for that copy from then on. Whether and when that happens depends on the table, so a fork that is only read can keep sharing indefinitely. pub async fn fork_database( configuration: &configuration::Configuration, database_id: &str, diff --git a/src/models/fork_database_request.rs b/src/models/fork_database_request.rs index 6e39b0e..5e9742c 100644 --- a/src/models/fork_database_request.rs +++ b/src/models/fork_database_request.rs @@ -14,6 +14,14 @@ use serde::{Deserialize, Serialize}; /// ForkDatabaseRequest : Request body for POST /databases/{database_id}/fork #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct ForkDatabaseRequest { + /// Optional note saying why the fork is being taken — for example \"backfill test before the March migration\". It is kept with the record of the fork and returned wherever that record appears: `forked_from` on the fork, and the fork's entry in both databases' lineage. Surrounding whitespace is trimmed, and an empty value is treated as absent. At most 4096 bytes; line breaks and tabs are allowed, other control characters are not. + #[serde( + rename = "description", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub description: Option>, /// When the fork 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\"` or `\"7d\"`. When omitted, a still-future expiry on the source is carried over; otherwise the fork never expires. #[serde( rename = "expires_at", @@ -36,6 +44,7 @@ impl ForkDatabaseRequest { /// Request body for POST /databases/{database_id}/fork pub fn new() -> ForkDatabaseRequest { ForkDatabaseRequest { + description: None, expires_at: None, name: None, } diff --git a/src/models/forked_from_info.rs b/src/models/forked_from_info.rs index a73cfd6..762ca5d 100644 --- a/src/models/forked_from_info.rs +++ b/src/models/forked_from_info.rs @@ -17,6 +17,14 @@ pub struct ForkedFromInfo { /// ID of the database that was forked. The database may since have been deleted — the record outlives it — so this is not guaranteed to resolve. #[serde(rename = "database_id")] pub database_id: String, + /// Why the fork was taken, as given when it was created. Absent when none was given. + #[serde( + rename = "description", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub description: Option>, /// When the fork was taken. #[serde( rename = "forked_at", @@ -48,6 +56,7 @@ impl ForkedFromInfo { pub fn new(database_id: String) -> ForkedFromInfo { ForkedFromInfo { database_id, + description: None, forked_at: None, name: None, snapshot_id: None, diff --git a/src/models/lineage_ancestor_info.rs b/src/models/lineage_ancestor_info.rs index 8f12185..bd04669 100644 --- a/src/models/lineage_ancestor_info.rs +++ b/src/models/lineage_ancestor_info.rs @@ -16,6 +16,14 @@ use serde::{Deserialize, Serialize}; pub struct LineageAncestorInfo { #[serde(rename = "database_id")] pub database_id: String, + /// Why the next database down the chain was forked from it, as given at the time. Absent when none was given. + #[serde( + rename = "description", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub description: Option>, /// False once the ancestor has been deleted. Its place in the chain is kept either way, and the ancestry continues past it. #[serde(rename = "exists")] pub exists: bool, @@ -50,6 +58,7 @@ impl LineageAncestorInfo { pub fn new(database_id: String, exists: bool) -> LineageAncestorInfo { LineageAncestorInfo { database_id, + description: None, exists, forked_at: None, name: None, diff --git a/src/models/lineage_fork_info.rs b/src/models/lineage_fork_info.rs index 1afb323..2285d28 100644 --- a/src/models/lineage_fork_info.rs +++ b/src/models/lineage_fork_info.rs @@ -16,6 +16,14 @@ use serde::{Deserialize, Serialize}; pub struct LineageForkInfo { #[serde(rename = "database_id")] pub database_id: String, + /// Why the fork was taken, as given when it was created. Absent when none was given. + #[serde( + rename = "description", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub description: Option>, /// False once the fork has been deleted. The record of it is kept either way, so a source can still account for everything taken from it. #[serde(rename = "exists")] pub exists: bool, @@ -50,6 +58,7 @@ impl LineageForkInfo { pub fn new(database_id: String, exists: bool) -> LineageForkInfo { LineageForkInfo { database_id, + description: None, exists, forked_at: None, name: None,