Skip to content

Commit 919970d

Browse files
committed
Add managed databases CLI for parquet table loads.
Introduce `hotdata databases` as the UX for managed connections: create catalogs, declare tables, load parquet uploads, and query via `name.schema.table`. Includes unit and integration tests plus README docs.
1 parent 14aeaa6 commit 919970d

5 files changed

Lines changed: 1157 additions & 3 deletions

File tree

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ API key priority (lowest to highest): config file → `HOTDATA_API_KEY` env var
6565
| `auth` | `login`, `status`, `logout` | `login` or bare `auth` opens browser login; `status` / `logout` manage the saved profile |
6666
| `workspaces` | `list`, `set` | Manage workspaces |
6767
| `connections` | `list`, `create`, `refresh`, `new` | Manage connections |
68+
| `databases` | `list`, `create`, `delete`, `tables` | Managed databases (create and load tables via parquet) |
6869
| `tables` | `list` | List tables and columns |
6970
| `datasets` | `list`, `create`, `update` | Manage uploaded datasets |
7071
| `context` | `list`, `show`, `pull`, `push` | Workspace Markdown context (e.g. data model `DATAMODEL`) via the context API |
@@ -127,6 +128,34 @@ hotdata connections create list <type_name> --format json
127128
hotdata connections create --name "my-conn" --type postgres --config '{"host":"...","port":5432,...}'
128129
```
129130

131+
## Databases
132+
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.
134+
135+
```sh
136+
hotdata databases list [-w <id>] [-o table|json|yaml]
137+
hotdata databases create --name <name> [--table <table> ...] [--schema public] [-o table|json|yaml]
138+
hotdata databases <name_or_id> [-o table|json|yaml]
139+
hotdata databases delete <name_or_id>
140+
141+
hotdata databases tables list <database> [--schema <name>] [-o table|json|yaml]
142+
hotdata databases tables load <database> <table> --file ./data.parquet [--schema public]
143+
hotdata databases tables load <database> <table> --upload-id <id> [--schema public]
144+
hotdata databases tables delete <database> <table> [--schema public]
145+
```
146+
147+
- `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).
148+
- `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).
149+
- For CSV/JSON uploads without a managed database, use `hotdata datasets create` instead (`datasets.main.*`).
150+
151+
Example:
152+
153+
```sh
154+
hotdata databases create --name sales --table orders
155+
hotdata databases tables load sales orders --file ./orders.parquet
156+
hotdata query "SELECT count(*) FROM sales.public.orders"
157+
```
158+
130159
## Tables
131160

132161
```sh

src/command.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,23 @@ pub enum Commands {
6969
command: Option<ConnectionsCommands>,
7070
},
7171

72+
/// Managed databases you create and populate with tables (parquet uploads)
73+
Databases {
74+
/// Database name or connection ID (omit to use a subcommand)
75+
name_or_id: Option<String>,
76+
77+
/// Workspace ID (defaults to first workspace from login)
78+
#[arg(long, short = 'w', global = true)]
79+
workspace_id: Option<String>,
80+
81+
/// Output format
82+
#[arg(long = "output", short = 'o', default_value = "table", value_parser = ["table", "json", "yaml"])]
83+
output: String,
84+
85+
#[command(subcommand)]
86+
command: Option<DatabasesCommands>,
87+
},
88+
7289
/// Manage tables in a workspace
7390
Tables {
7491
#[command(subcommand)]
@@ -515,6 +532,98 @@ pub enum ConnectionsCreateCommands {
515532
},
516533
}
517534

535+
#[derive(Subcommand)]
536+
pub enum DatabasesCommands {
537+
/// List managed databases in the workspace
538+
List {
539+
/// Output format
540+
#[arg(long = "output", short = 'o', default_value = "table", value_parser = ["table", "json", "yaml"])]
541+
output: String,
542+
},
543+
544+
/// Create a new managed database
545+
Create {
546+
/// Database name (used as the connection name in SQL: `name.schema.table`)
547+
#[arg(long)]
548+
name: String,
549+
550+
/// Schema for tables declared at create time (default: public)
551+
#[arg(long, default_value = "public")]
552+
schema: String,
553+
554+
/// Table to declare up front (repeatable). Required before load on current API.
555+
#[arg(long = "table")]
556+
tables: Vec<String>,
557+
558+
/// Output format
559+
#[arg(long = "output", short = 'o', default_value = "table", value_parser = ["table", "json", "yaml"])]
560+
output: String,
561+
},
562+
563+
/// Delete a managed database and its tables
564+
Delete {
565+
/// Database name or connection ID
566+
name_or_id: String,
567+
},
568+
569+
/// Manage tables inside a managed database
570+
Tables {
571+
#[command(subcommand)]
572+
command: DatabaseTablesCommands,
573+
},
574+
}
575+
576+
#[derive(Subcommand)]
577+
pub enum DatabaseTablesCommands {
578+
/// List tables in a managed database
579+
List {
580+
/// Database name or connection ID
581+
database: String,
582+
583+
/// Filter by schema name
584+
#[arg(long)]
585+
schema: Option<String>,
586+
587+
/// Output format
588+
#[arg(long = "output", short = 'o', default_value = "table", value_parser = ["table", "json", "yaml"])]
589+
output: String,
590+
},
591+
592+
/// Load a parquet file into a table (creates or replaces the table)
593+
Load {
594+
/// Database name or connection ID
595+
database: String,
596+
597+
/// Table name
598+
table: String,
599+
600+
/// Schema name (default: public)
601+
#[arg(long, default_value = "public")]
602+
schema: String,
603+
604+
/// Path to a local parquet file to upload and load
605+
#[arg(long, conflicts_with = "upload_id")]
606+
file: Option<String>,
607+
608+
/// Use a previously staged upload ID from `POST /v1/files` instead of uploading
609+
#[arg(long)]
610+
upload_id: Option<String>,
611+
},
612+
613+
/// Delete a table from a managed database
614+
Delete {
615+
/// Database name or connection ID
616+
database: String,
617+
618+
/// Table name
619+
table: String,
620+
621+
/// Schema name (default: public)
622+
#[arg(long, default_value = "public")]
623+
schema: String,
624+
},
625+
}
626+
518627
#[derive(Subcommand)]
519628
pub enum ConnectionsCommands {
520629
/// Interactively create a new connection

0 commit comments

Comments
 (0)