ADR-0016 + Iter 5/6 follow-up: pretty table rendering

Replaces the placeholder pipe-and-dash output with Unicode
box-drawing tables for both data results and table-structure
listings, per ADR-0016.

* New `src/output_render.rs` module with `render_data_table`
  and `render_structure`. Hand-rolled to match the project's
  existing CSV/YAML pattern; ~300 lines.
* Header-only outer-frame border style: outer ┌─┐│└─┘ box +
  ├─┤ header underline, no per-row separators. NULL renders
  as `(null)`; cell newlines/tabs/control chars become
  `↵`/`→`/`·` as display-only substitutions.
* Type-aware column alignment: numeric types right-aligned,
  everything else left. `DataResult` gains a `column_types:
  Vec<Option<Type>>` field, populated from the existing
  metadata lookup at the two query sites in db.rs (no new
  query paths).
* Structure view shows Name | Type | Constraints columns;
  References / Referenced-by sections retain plain-text
  format, leaving room for the future relationship-rendering
  ADR.
* 18 new unit tests in output_render.rs (plus 4 insta
  snapshots for the canonical layouts). Existing assertions
  in app.rs and walking_skeleton.rs updated to match the new
  format.

Total: 426 passing, 0 failing, 0 skipped (up from 408).
Clippy clean.
This commit is contained in:
claude@clouddev1
2026-05-08 09:06:02 +00:00
parent 67d68db5f8
commit 5b5e08d852
11 changed files with 965 additions and 125 deletions
+13 -2
View File
@@ -134,12 +134,20 @@ pub enum DbError {
Io(String),
}
/// Result of a query / show-data call (schema-less display rows).
/// `None` cells render as NULL; `Some(s)` renders as the string.
/// Result of a query / show-data call.
///
/// `None` cells render as NULL; `Some(s)` renders as the
/// string. `column_types` carries the user-facing type per
/// column (per ADR-0016 §2): the renderer uses it for
/// alignment, and future work uses it for type-aware cell
/// styling. `None` only for the edge case of a
/// foreign-attached database we did not create — not
/// achievable in normal use.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DataResult {
pub table_name: String,
pub columns: Vec<String>,
pub column_types: Vec<Option<Type>>,
pub rows: Vec<Vec<Option<String>>>,
}
@@ -1970,6 +1978,7 @@ fn query_rows_by_rowid(
return Ok(DataResult {
table_name: table.to_string(),
columns: column_names,
column_types,
rows: Vec::new(),
});
}
@@ -2016,6 +2025,7 @@ fn query_rows_by_rowid(
Ok(DataResult {
table_name: table.to_string(),
columns: column_names,
column_types,
rows,
})
}
@@ -2355,6 +2365,7 @@ fn do_query_data(conn: &Connection, table: &str) -> Result<DataResult, DbError>
Ok(DataResult {
table_name: table.to_string(),
columns: column_names,
column_types,
rows,
})
}