Skip to content

Commit 1868e57

Browse files
feat(databases): record why a fork was taken
Add `databases fork --description <text>`, backed by the fork description added in runtimedb #1420. - The description is sent as given. The server trims it, treats blank as absent, and checks length and control characters. - `fork` and `databases <id>` print the full text on its own line. `lineage` rows show the first line, cut at 60 characters. `-o json`/`yaml` carry the full text. - Lineage moves the description one generation down with `snapshot_id` and `forked_at`, since an ancestor entry describes the fork taken from it.
1 parent 70033de commit 1868e57

4 files changed

Lines changed: 155 additions & 25 deletions

File tree

‎skills/hotdata/SKILL.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ Returns workspaces with `public_id`, `name`, `active`, `favorite`, `provision_st
101101
hotdata databases list [--workspace-id <workspace_id>] [--output table|json|yaml]
102102
hotdata databases count [--workspace-id <workspace_id>] [--output table|json|yaml]
103103
hotdata databases create [--name <display_name>] [--catalog <alias>] [--table <table> ...] [--schema public] [--expires-at <duration|timestamp>] [--workspace-id <workspace_id>] [--output table|json|yaml]
104-
hotdata databases fork [<id>] [--name <display_name>] [--expires-at <duration|timestamp>] [--workspace-id <workspace_id>] [--output table|json|yaml]
104+
hotdata databases fork [<id>] [--name <display_name>] [--expires-at <duration|timestamp>] [--description <text>] [--workspace-id <workspace_id>] [--output table|json|yaml]
105105
hotdata databases lineage [<id>] [--forks-limit <n>] [--workspace-id <workspace_id>] [--output table|json|yaml]
106106
hotdata databases use <id>
107107
hotdata databases unset
@@ -126,8 +126,8 @@ hotdata databases tables remove <table> [--database <id>] [--schema public] [--w
126126
- `list` — all instant databases in the workspace. Active database is marked with `*` under the DEFAULT column; CREATED shows when each database was made.
127127
- `count` — the total number of instant databases in the workspace, across **all** pages (`list` shows one page). Prints a bare integer by default so it drops straight into scripts (`$(hotdata databases count)`); `--output json|yaml` render `{"count": N}` / `count: N`.
128128
- `create` — creates a new instant database. `--name` is an optional human-readable display name. `--catalog` sets the SQL alias used in queries (`SELECT … FROM <catalog>.schema.table`); must be `[a-z_][a-z0-9_]*`. `--expires-at` accepts relative durations (`24h`, `7d`, `90m`) or an RFC 3339 timestamp; omitting means no expiry. Repeat `--table` to declare tables up front.
129-
- `fork` — creates a new instant database that is an independent deep copy of an existing one (same schemas, tables, and data); the source is left unchanged and the two diverge freely afterwards. The source defaults to the active database; pass the database `<id>` to fork another. `--name` defaults to `<source>-fork` (so the two stay distinguishable in `list`); `--expires-at` accepts a relative duration or RFC 3339 timestamp, and when omitted a still-future source expiry is carried over. The fork becomes the active database on success. The fork answers to the **same catalog alias** as its source inside its own scope; catalogs attached to the source are **re-attached** to the fork, but indexes are **not** carried over. Only databases created with the current (DuckLake) storage engine can be forked — older parquet-backed databases return an error. The fork's output (and its `databases <id>` view) records **`forked_from`** provenance: source id, the source's name at fork time, the copied snapshot, and when.
130-
- `lineage` — renders a database's **whole fork family tree**, walked from the root down (defaults to the active database; one lineage request per database, fine for the small families forks produce in practice): every reachable generation, with the queried database marked `← this database`. Lineage is a historical record, not a live link — the databases stay independent, and a **deleted** generation stays in the chain (marked `deleted`), though its own fork list can't be enumerated: such branches end with `⋯ forks unknown`. Forks made before the server recorded lineage carry none. `--forks-limit <n>` pages each database's direct-fork list (server clamps to 1–100); a truncated branch closes with `⋯ N more`. `-o json`/`yaml` return `{database_id, root_id, tree}` with a recursive `tree` node.
129+
- `fork` — creates a new instant database that is an independent deep copy of an existing one (same schemas, tables, and data); the source is left unchanged and the two diverge freely afterwards. The source defaults to the active database; pass the database `<id>` to fork another. `--name` defaults to `<source>-fork` (so the two stay distinguishable in `list`); `--expires-at` accepts a relative duration or RFC 3339 timestamp, and when omitted a still-future source expiry is carried over. `--description` records why the fork was taken (for example `"what-if on Q3 pricing"`); it can be set only at fork time. The fork becomes the active database on success. The fork answers to the **same catalog alias** as its source inside its own scope; catalogs attached to the source are **re-attached** to the fork, but indexes are **not** carried over. Only databases created with the current (DuckLake) storage engine can be forked — older parquet-backed databases return an error. The fork's output (and its `databases <id>` view) records **`forked_from`** provenance: source id, the source's name at fork time, the copied snapshot, when, and the description if one was given.
130+
- `lineage` — renders a database's **whole fork family tree**, walked from the root down (defaults to the active database; one lineage request per database, fine for the small families forks produce in practice): every reachable generation, with the queried database marked `← this database`. A fork taken with `--description` shows the first line of it on its row; `-o json`/`yaml` carry the full text. Lineage is a historical record, not a live link — the databases stay independent, and a **deleted** generation stays in the chain (marked `deleted`), though its own fork list can't be enumerated: such branches end with `⋯ forks unknown`. Forks made before the server recorded lineage carry none. `--forks-limit <n>` pages each database's direct-fork list (server clamps to 1–100); a truncated branch closes with `⋯ N more`. `-o json`/`yaml` return `{database_id, root_id, tree}` with a recursive `tree` node.
131131
- `use` — saves the database **id** as the active database. Subsequent `databases tables` and `databases context` commands use it automatically. Note that a successful `fork` also updates this: the fork becomes the active database.
132132
- `unset` — clears the active database from config.
133133
- `show <id>` / `<id>` — inspect one database (returns id, catalog, name, expires_at, attached databases; a fork also shows its `forked_from` record).

‎skills/hotdata/references/WORKFLOWS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ Before destructive experimentation (bulk replaces, schema rework, testing a load
161161
```bash
162162
hotdata databases list # note the source database id (dbid...)
163163
hotdata databases use <source_id> # source to protect (`use` takes an id)
164-
hotdata databases fork --expires-at 24h # deep copy; becomes the active database — note the fork id it prints
164+
hotdata databases fork --expires-at 24h --description "test risky.parquet load" # deep copy; becomes the active database — note the fork id it prints
165165
hotdata databases load --catalog sales --table orders --file ./risky.parquet # hits the fork
166166
```
167167

0 commit comments

Comments
 (0)