feat: V5 show tables / relationships / indexes list commands
Add the list-all show family as one Command::ShowList { kind }
variant. A read-only worker show_list formats count-headed lists
(reusing do_list_tables / read_all_relationships /
read_table_indexes, so it never drifts from the items panel);
internal __rdbms_* tables excluded. Help + parse-usage entries
added; 10 integration tests in tests/it/show_list.rs.
Mark V5 [x]. Split the singular show relationship/index <name>
detail forms (the [<name>] half) into a new tracked V5a [ ] item
rather than leaving them as an untracked footnote.
This commit is contained in:
@@ -554,6 +554,14 @@ enum Request {
|
||||
ListTables {
|
||||
reply: oneshot::Sender<Result<Vec<String>, DbError>>,
|
||||
},
|
||||
/// List every item of a schema kind (tables / relationships /
|
||||
/// indexes) as pre-formatted display lines for the `show
|
||||
/// <kind>` commands (V5). Read-only; formats in the worker
|
||||
/// from the same helpers the items panel and describe view use.
|
||||
ShowList {
|
||||
kind: crate::dsl::command::ShowListKind,
|
||||
reply: oneshot::Sender<Result<Vec<String>, DbError>>,
|
||||
},
|
||||
DescribeTable {
|
||||
name: String,
|
||||
source: Option<String>,
|
||||
@@ -1317,6 +1325,17 @@ impl Database {
|
||||
recv.await.map_err(|_| DbError::WorkerGone)?
|
||||
}
|
||||
|
||||
/// Pre-formatted display lines for `show tables` /
|
||||
/// `show relationships` / `show indexes` (V5). Read-only.
|
||||
pub async fn show_list(
|
||||
&self,
|
||||
kind: crate::dsl::command::ShowListKind,
|
||||
) -> Result<Vec<String>, DbError> {
|
||||
let (reply, recv) = oneshot::channel();
|
||||
self.send(Request::ShowList { kind, reply }).await?;
|
||||
recv.await.map_err(|_| DbError::WorkerGone)?
|
||||
}
|
||||
|
||||
pub async fn describe_table(
|
||||
&self,
|
||||
name: String,
|
||||
@@ -2245,6 +2264,9 @@ fn handle_request(
|
||||
Request::ListTables { reply } => {
|
||||
let _ = reply.send(do_list_tables(conn));
|
||||
}
|
||||
Request::ShowList { kind, reply } => {
|
||||
let _ = reply.send(do_show_list(conn, kind));
|
||||
}
|
||||
Request::DescribeTable {
|
||||
name,
|
||||
source,
|
||||
@@ -5834,6 +5856,79 @@ fn do_list_tables(conn: &Connection) -> Result<Vec<String>, DbError> {
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Pre-formatted display lines for the `show <kind>` list commands
|
||||
/// (V5). A count header followed by one indented item per line, or a
|
||||
/// single friendly "none yet" line for an empty collection. Reuses
|
||||
/// the same helpers the items panel / describe view read from, so the
|
||||
/// list never drifts from those views. Engine-neutral wording per the
|
||||
/// ADR-0002 user-facing posture.
|
||||
fn do_show_list(
|
||||
conn: &Connection,
|
||||
kind: crate::dsl::command::ShowListKind,
|
||||
) -> Result<Vec<String>, DbError> {
|
||||
use crate::dsl::command::ShowListKind;
|
||||
let mut lines = Vec::new();
|
||||
match kind {
|
||||
ShowListKind::Tables => {
|
||||
let tables = do_list_tables(conn)?;
|
||||
if tables.is_empty() {
|
||||
lines.push("No tables in this project yet.".to_string());
|
||||
} else {
|
||||
lines.push(format!("Tables ({}):", tables.len()));
|
||||
for name in tables {
|
||||
lines.push(format!(" {name}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
ShowListKind::Relationships => {
|
||||
let rels = read_all_relationships(conn)?;
|
||||
if rels.is_empty() {
|
||||
lines.push("No relationships in this project yet.".to_string());
|
||||
} else {
|
||||
lines.push(format!("Relationships ({}):", rels.len()));
|
||||
for r in rels {
|
||||
let mut line = format!(
|
||||
" {}: {}.{} → {}.{}",
|
||||
r.name, r.parent_table, r.parent_column, r.child_table, r.child_column
|
||||
);
|
||||
if r.on_delete != ReferentialAction::default_action() {
|
||||
line.push_str(&format!(" on delete {}", r.on_delete.keyword()));
|
||||
}
|
||||
if r.on_update != ReferentialAction::default_action() {
|
||||
line.push_str(&format!(" on update {}", r.on_update.keyword()));
|
||||
}
|
||||
lines.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
ShowListKind::Indexes => {
|
||||
// Each table's user-created indexes (origin "c"), the
|
||||
// same set the items panel shows. Ordered by table, then
|
||||
// by index name (read_table_indexes orders by name).
|
||||
let tables = do_list_tables(conn)?;
|
||||
let mut entries: Vec<String> = Vec::new();
|
||||
for table in &tables {
|
||||
for ix in read_table_indexes(conn, table)? {
|
||||
let unique = if ix.unique { " [unique]" } else { "" };
|
||||
entries.push(format!(
|
||||
" {}.{} ({}){unique}",
|
||||
table,
|
||||
ix.name,
|
||||
ix.columns.join(", ")
|
||||
));
|
||||
}
|
||||
}
|
||||
if entries.is_empty() {
|
||||
lines.push("No indexes in this project yet.".to_string());
|
||||
} else {
|
||||
lines.push(format!("Indexes ({}):", entries.len()));
|
||||
lines.extend(entries);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(lines)
|
||||
}
|
||||
|
||||
/// Internal full schema of a table, sufficient to regenerate
|
||||
/// its `CREATE TABLE` statement during the rebuild dance.
|
||||
#[derive(Debug, Clone)]
|
||||
|
||||
Reference in New Issue
Block a user