Skip to content

Commit d51a4c1

Browse files
committed
feat(databases): page 'databases list' with --limit/--cursor
Show one capped page + a 'use --cursor <next>' hint (matching tables/queries list) instead of draining the whole workspace into memory. Name/catalog resolution and the whole-workspace indexes-list scan still drain every page internally (list_all_databases).
1 parent 0785c5c commit d51a4c1

2 files changed

Lines changed: 47 additions & 6 deletions

File tree

‎src/commands/databases.rs‎

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ use std::path::Path;
88
pub enum DatabasesCommands {
99
/// List managed databases in the workspace
1010
List {
11+
/// Maximum number of databases to return
12+
#[arg(long)]
13+
limit: Option<u32>,
14+
15+
/// Pagination cursor from a previous response
16+
#[arg(long)]
17+
cursor: Option<String>,
18+
1119
/// Output format
1220
#[arg(long = "output", short = 'o', default_value = "table", value_parser = ["table", "json", "yaml"])]
1321
output: String,
@@ -917,10 +925,29 @@ fn collect_tables(
917925
(out, false, None)
918926
}
919927

920-
pub fn list(workspace_id: &str, format: &str) {
928+
pub fn list(workspace_id: &str, format: &str, limit: Option<u32>, cursor: Option<&str>) {
921929
let api = Api::new(Some(workspace_id));
922-
let mut databases = list_database_summaries(&api).unwrap_or_else(|e| e.exit());
923-
databases.sort_by(|a, b| a.created_at.cmp(&b.created_at));
930+
// One page, user-paginated (like `tables list` / `queries list`). Name/
931+
// catalog resolution and the whole-workspace `indexes list` scan still see
932+
// every database — they drain all pages internally via list_all_databases;
933+
// only this display command pages.
934+
let resp = block_with_wakeup(
935+
&api,
936+
"Loading databases...",
937+
api.client()
938+
.databases()
939+
.list(limit.map(|l| l as i32), cursor),
940+
)
941+
.unwrap_or_else(|e| e.exit());
942+
let has_more = resp.has_more.flatten().unwrap_or(false);
943+
let next_cursor = resp.next_cursor.clone().flatten();
944+
// Server returns newest-first; keep that order so the cursor continuation is
945+
// coherent (no client re-sort across pages).
946+
let databases: Vec<DatabaseSummary> = resp
947+
.databases
948+
.into_iter()
949+
.map(DatabaseSummary::from)
950+
.collect();
924951

925952
match format {
926953
"json" => println!("{}", serde_json::to_string_pretty(&databases).unwrap()),
@@ -959,6 +986,18 @@ pub fn list(workspace_id: &str, format: &str) {
959986
}
960987
_ => unreachable!(),
961988
}
989+
990+
if has_more {
991+
use crossterm::style::Stylize;
992+
eprintln!(
993+
"{}",
994+
format!(
995+
"More results available. Use --cursor {} to fetch the next page.",
996+
next_cursor.as_deref().unwrap_or("")
997+
)
998+
.dark_grey()
999+
);
1000+
}
9621001
}
9631002

9641003
pub fn get(workspace_id: &str, id_or_name: &str, format: &str) {

‎src/main.rs‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,11 @@ fn main() {
257257
databases::get(&workspace_id, &name_or_id, &output);
258258
} else {
259259
match command {
260-
Some(DatabasesCommands::List { output }) => {
261-
databases::list(&workspace_id, &output)
262-
}
260+
Some(DatabasesCommands::List {
261+
output,
262+
limit,
263+
cursor,
264+
}) => databases::list(&workspace_id, &output, limit, cursor.as_deref()),
263265
Some(DatabasesCommands::Show { name_or_id, output }) => {
264266
databases::get(&workspace_id, &name_or_id, &output)
265267
}

0 commit comments

Comments
 (0)