Skip to content

Commit 4a253d8

Browse files
authored
feat(databases): add --catalog flag to databases create (#125)
* feat(databases): add --catalog flag to databases create Maps to the default_catalog field on POST /v1/databases, separating the human-readable --name from the SQL catalog alias used in queries. Also fixes config tests that failed when HOTDATA_API_KEY was set in the environment by unsetting it inside the with_temp_config_dir test helper. * fix(databases): correct expires_at doc — omitting always means no expiry * fix(databases): add default_catalog to Database struct; use catalog in all output - Add `default_catalog` field to `Database` struct so `databases show` and table commands use the correct SQL alias instead of falling back to the display name - Use default_catalog (falling back to name, then "default") in databases show sql_prefix, tables list full_name, tables load, and tables delete output - Fix --catalog arg doc: remove stale 24h expiry claim - Update README and skills/hotdata/SKILL.md to document --name as display name and --catalog as the SQL alias, with corrected examples --------- Co-authored-by: Eddie A Tejeda <669988+eddietejeda@users.noreply.github.com>
1 parent ccd0fd9 commit 4a253d8

6 files changed

Lines changed: 80 additions & 44 deletions

File tree

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,14 @@ hotdata connections create --name "my-conn" --type postgres --config '{"host":".
130130

131131
## Databases
132132

133-
Managed databases are Hotdata-owned catalogs you create and populate yourself (no remote source to sync). Query them with SQL as `database_name.schema.table` — the database name is the connection name.
133+
Managed databases are Hotdata-owned catalogs you create and populate yourself (no remote source to sync). Query them with SQL as `<catalog>.schema.table`.
134134

135135
```sh
136136
hotdata databases list [-w <id>] [-o table|json|yaml]
137-
hotdata databases create --name <name> [--table <table> ...] [--schema public] [-o table|json|yaml]
137+
hotdata databases create [--name <display_name>] [--catalog <alias>] [--table <table> ...] [--schema public] [--expires-at <duration|timestamp>] [-o table|json|yaml]
138138
hotdata databases <name_or_id> [-o table|json|yaml]
139139
hotdata databases delete <name_or_id>
140-
hotdata databases run [--database <id>] [--description <label>] [--schema public] [--table <table> ...] [--expires-at <duration|timestamp>] <cmd> [args...]
140+
hotdata databases run [--database <id>] [--name <label>] [--schema public] [--table <table> ...] [--expires-at <duration|timestamp>] <cmd> [args...]
141141
hotdata databases <id> run <cmd> [args...]
142142

143143
hotdata databases tables list <database> [--schema <name>] [-o table|json|yaml]
@@ -146,15 +146,15 @@ hotdata databases tables load <database> <table> --upload-id <id> [--schema publ
146146
hotdata databases tables delete <database> <table> [--schema public]
147147
```
148148

149-
- `create` registers a managed connection (`source_type: managed`) with no external credentials. Use `--table` to declare tables up front (required before `tables load` on the current API).
149+
- `create` registers a managed connection with no external credentials. `--name` is a human-readable display name; `--catalog` sets the SQL alias used in queries (`SELECT … FROM <catalog>.schema.table`) and must be `[a-z_][a-z0-9_]*`. Use `--table` to declare tables up front (required before `tables load` on the current API).
150150
- `tables load` uploads a **parquet** file (or uses a staged `upload_id` from `POST /v1/files`) and publishes it as the table generation (`replace` mode).
151-
- `run` mints a database-scoped JWT and execs `<cmd>` with `HOTDATA_DATABASE_TOKEN`, `HOTDATA_DATABASE_REFRESH_TOKEN`, `HOTDATA_DATABASE`, `HOTDATA_WORKSPACE`, and `HOTDATA_API_URL` injected into its environment. Pass a database id (group-positional `<id>` like `sandbox run`, or `--database <id>`) to scope an existing database; omit both to auto-create a scratch one using `--description` / `--schema` / `--table` / `--expires-at`. Useful for launching an agent or child process whose API access is restricted to a single database.
151+
- `run` mints a database-scoped JWT and execs `<cmd>` with `HOTDATA_DATABASE_TOKEN`, `HOTDATA_DATABASE_REFRESH_TOKEN`, `HOTDATA_DATABASE`, `HOTDATA_WORKSPACE`, and `HOTDATA_API_URL` injected into its environment. Pass a database id (group-positional `<id>` like `sandbox run`, or `--database <id>`) to scope an existing database; omit both to auto-create a scratch one using `--name` / `--schema` / `--table` / `--expires-at`. Useful for launching an agent or child process whose API access is restricted to a single database.
152152
- For CSV/JSON uploads without a managed database, use `hotdata datasets create` instead (`datasets.main.*`).
153153

154154
Example:
155155

156156
```sh
157-
hotdata databases create --name sales --table orders
157+
hotdata databases create --name "Sales reporting" --catalog sales --table orders
158158
hotdata databases tables load sales orders --file ./orders.parquet
159159
hotdata query "SELECT count(*) FROM sales.public.orders"
160160
```

skills/hotdata/SKILL.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -187,39 +187,39 @@ hotdata connections create \
187187

188188
```
189189
hotdata databases list [--workspace-id <workspace_id>] [--output table|json|yaml]
190-
hotdata databases create [--name <catalog_name>] [--table <table> ...] [--schema public] [--expires-at <duration|timestamp>] [--workspace-id <workspace_id>] [--output table|json|yaml]
191-
hotdata databases set <id_or_description>
192-
hotdata databases <id_or_description> [--workspace-id <workspace_id>] [--output table|json|yaml]
193-
hotdata databases delete <id_or_description> [--workspace-id <workspace_id>]
194-
hotdata databases run [--database <id>] [--name <catalog_name>] [--schema public] [--table <table> ...] [--expires-at <duration|timestamp>] [--workspace-id <workspace_id>] <cmd> [args...]
190+
hotdata databases create [--name <display_name>] [--catalog <alias>] [--table <table> ...] [--schema public] [--expires-at <duration|timestamp>] [--workspace-id <workspace_id>] [--output table|json|yaml]
191+
hotdata databases set <id_or_name>
192+
hotdata databases <id_or_name> [--workspace-id <workspace_id>] [--output table|json|yaml]
193+
hotdata databases delete <id_or_name> [--workspace-id <workspace_id>]
194+
hotdata databases run [--database <id>] [--name <label>] [--schema public] [--table <table> ...] [--expires-at <duration|timestamp>] [--workspace-id <workspace_id>] <cmd> [args...]
195195
hotdata databases <id> run <cmd> [args...]
196196
197197
# Dot-notation shorthand for load: database.table or database.schema.table
198198
hotdata databases load <database.table> [--file ./data.parquet] [--url <url>] [--upload-id <id>] [--workspace-id <workspace_id>]
199199
200-
hotdata databases tables list [--database <id_or_desc>] [--schema <name>] [--workspace-id <workspace_id>] [--output table|json|yaml]
201-
hotdata databases tables load <table> [--database <id_or_desc>] [--schema public] [--file ./data.parquet] [--url <url>] [--upload-id <id>] [--workspace-id <workspace_id>]
202-
hotdata databases tables delete <table> [--database <id_or_desc>] [--schema public] [--workspace-id <workspace_id>]
200+
hotdata databases tables list [--database <id_or_name>] [--schema <name>] [--workspace-id <workspace_id>] [--output table|json|yaml]
201+
hotdata databases tables load <table> [--database <id_or_name>] [--schema public] [--file ./data.parquet] [--url <url>] [--upload-id <id>] [--workspace-id <workspace_id>]
202+
hotdata databases tables delete <table> [--database <id_or_name>] [--schema public] [--workspace-id <workspace_id>]
203203
```
204204

205205
- `list` — all managed databases in the workspace.
206-
- `create` — creates a new managed database. `--name` is an optional catalog alias used in queries (`SELECT … FROM <name>.public.<table>`); must be `[a-z_][a-z0-9_]*`. `--expires-at` accepts relative durations (`24h`, `7d`, `90m`) or an RFC 3339 timestamp; defaults to `24h` when omitted. Repeat `--table` to declare tables up front.
207-
- `set` — saves `<id_or_description>` as the active database. Subsequent `databases tables` and `context` commands use it automatically.
208-
- `<id_or_description>` — inspect one database (id, description, expires_at).
206+
- `create` — creates a new managed 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.
207+
- `set` — saves `<id_or_name>` as the active database. Subsequent `databases tables` and `context` commands use it automatically.
208+
- `<id_or_name>` — inspect one database (id, catalog, name, expires_at).
209209
- `delete` — removes the managed database; clears the active-database config if it matched.
210210
- `load` — shorthand with dot notation (`database.table` or `database.schema.table`). Schema defaults to `public`.
211-
- `tables list` — lists tables with `TABLE` (`<database_id>.<schema>.<table>`), `SYNCED`, `LAST_SYNC`. Uses active database when `--database` is omitted.
211+
- `tables list` — lists tables with `TABLE` (`<catalog>.<schema>.<table>`), `SYNCED`, `LAST_SYNC`. Uses active database when `--database` is omitted.
212212
- `tables load` — uploads a local parquet file (`--file`), a remote parquet URL (`--url`), or a pre-staged upload (`--upload-id`) and publishes with **replace** mode.
213213
- `tables delete` — drops a table from the managed database.
214214
- `run` — mints a database-scoped JWT (via `POST /v1/auth/database`) and execs `<cmd>` with `HOTDATA_DATABASE_TOKEN`, `HOTDATA_DATABASE_REFRESH_TOKEN`, `HOTDATA_DATABASE`, `HOTDATA_WORKSPACE`, and `HOTDATA_API_URL` injected. Pass a database id as a group positional (`hotdata databases <id> run ...`, sandbox-style) or via `--database <id>`; omit both to auto-create a scratch database using `--name` / `--schema` / `--table` / `--expires-at`. Use this to launch an agent or child process whose API access is scoped to a single database. The minted JWT carries `database`, `workspaces`, `permissions:["read","write"]`, `source:"database_token"`. The session is persisted at `~/.hotdata/database_session.json` (mode `0600`); the child's exit code is propagated.
215215

216216
Example:
217217

218218
```
219-
hotdata databases create --name sales --table orders
219+
hotdata databases create --name "Sales reporting" --catalog sales --table orders
220220
hotdata databases set <returned-id>
221221
hotdata databases tables load orders --file ./orders.parquet
222-
hotdata query "SELECT count(*) FROM <database_id>.public.orders"
222+
hotdata query "SELECT count(*) FROM sales.public.orders"
223223
```
224224

225225
### List Tables and Columns

src/command.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -563,13 +563,15 @@ pub enum DatabasesCommands {
563563

564564
/// Create a new managed database
565565
Create {
566-
/// SQL catalog alias — becomes the catalog name in queries:
567-
/// SELECT … FROM <name>.public.<table>.
568-
/// Must be [a-z_][a-z0-9_]*, globally unique. When provided the
569-
/// database defaults to no expiry; omit for an anonymous 24h sandbox.
566+
/// Human-readable display name for the database (e.g. "Sales reporting").
570567
#[arg(long)]
571568
name: Option<String>,
572569

570+
/// SQL catalog alias used in queries: SELECT … FROM <catalog>.schema.table.
571+
/// Must be [a-z_][a-z0-9_]*, globally unique.
572+
#[arg(long)]
573+
catalog: Option<String>,
574+
573575
/// Default schema for bare `--table` entries (default: public).
574576
/// Use dot notation in `--table` to target a different schema directly,
575577
/// e.g. `--table raw.raw_orders` always goes into the "raw" schema.
@@ -583,8 +585,7 @@ pub enum DatabasesCommands {
583585
tables: Vec<String>,
584586

585587
/// When the database expires. Accepts a relative duration (e.g. 24h, 7d, 90m)
586-
/// or an RFC 3339 timestamp. Omitting with --name means no expiry; omitting
587-
/// without --name defaults to 24h.
588+
/// or an RFC 3339 timestamp. Omitting means no expiry.
588589
#[arg(long)]
589590
expires_at: Option<String>,
590591

src/config.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,10 @@ pub mod test_helpers {
354354
let guard = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
355355
let tmp = tempfile::tempdir().unwrap();
356356
// SAFETY: tests are serialized via ENV_LOCK mutex, so no concurrent env mutation.
357-
unsafe { std::env::set_var("HOTDATA_CONFIG_DIR", tmp.path()) };
357+
unsafe {
358+
std::env::set_var("HOTDATA_CONFIG_DIR", tmp.path());
359+
std::env::remove_var("HOTDATA_API_KEY");
360+
}
358361
(tmp, guard)
359362
}
360363
}

0 commit comments

Comments
 (0)