feat(hint): H2 Phase C batch 3 — DML tier-3 hints (ADR-0053)

Per-form hints for querying/changing data: update, delete, show
data/table/tables/relationships/indexes, seed, explain, replay
(insert was the Phase-B exemplar). hint_ids wired on UPDATE/DELETE/
SHOW/SEED/EXPLAIN/REPLAY; catalogue + keys.rs registered. +2 spot
tests (incl. multi-form SHOW disambiguation); 2493 pass / 1 ignored,
clippy clean.
This commit is contained in:
claude@clouddev1
2026-06-15 16:08:57 +00:00
parent 47a08166a4
commit 9c4d520d5c
4 changed files with 101 additions and 6 deletions
+19
View File
@@ -5882,6 +5882,25 @@ mod tests {
assert!(!output_contains(&app, "Remove a table")); assert!(!output_contains(&app, "Remove a table"));
} }
// ── Phase C batch 3: DML hints render (incl. multi-form SHOW) ──
#[test]
fn f1_on_update_renders_its_hint_block() {
let mut app = App::new();
type_str(&mut app, "update Customers set email = 'x' ");
f1(&mut app);
assert!(output_contains(&app, "Change values in the rows"));
}
#[test]
fn f1_disambiguates_show_forms() {
let mut app = App::new();
type_str(&mut app, "show relationships");
f1(&mut app);
assert!(output_contains(&app, "List all the relationships"));
assert!(!output_contains(&app, "rows stored in a table"));
}
#[test] #[test]
fn messages_command_toggles_verbosity_and_reports() { fn messages_command_toggles_verbosity_and_reports() {
let mut app = App::new(); let mut app = App::new();
+12 -6
View File
@@ -1790,7 +1790,13 @@ pub static SHOW: CommandNode = CommandNode {
shape: SHOW_SHAPE, shape: SHOW_SHAPE,
ast_builder: build_show, ast_builder: build_show,
help_id: Some("data.show"), help_id: Some("data.show"),
hint_ids: &[], hint_ids: &[
"show_data",
"show_table",
"show_tables",
"show_relationships",
"show_indexes",
],
usage_ids: &[ usage_ids: &[
"parse.usage.show_data", "parse.usage.show_data",
"parse.usage.show_table", "parse.usage.show_table",
@@ -1806,7 +1812,7 @@ pub static SEED: CommandNode = CommandNode {
shape: SEED_SHAPE, shape: SEED_SHAPE,
ast_builder: build_seed, ast_builder: build_seed,
help_id: Some("data.seed"), help_id: Some("data.seed"),
hint_ids: &[], hint_ids: &["seed"],
usage_ids: &["parse.usage.seed"], usage_ids: &["parse.usage.seed"],
}; };
@@ -1824,7 +1830,7 @@ pub static UPDATE: CommandNode = CommandNode {
shape: UPDATE_SHAPE, shape: UPDATE_SHAPE,
ast_builder: build_update, ast_builder: build_update,
help_id: Some("data.update"), help_id: Some("data.update"),
hint_ids: &[], hint_ids: &["update"],
usage_ids: &["parse.usage.update"],}; usage_ids: &["parse.usage.update"],};
pub static DELETE: CommandNode = CommandNode { pub static DELETE: CommandNode = CommandNode {
@@ -1832,7 +1838,7 @@ pub static DELETE: CommandNode = CommandNode {
shape: DELETE_SHAPE, shape: DELETE_SHAPE,
ast_builder: build_delete, ast_builder: build_delete,
help_id: Some("data.delete"), help_id: Some("data.delete"),
hint_ids: &[], hint_ids: &["delete"],
usage_ids: &["parse.usage.delete"],}; usage_ids: &["parse.usage.delete"],};
pub static REPLAY: CommandNode = CommandNode { pub static REPLAY: CommandNode = CommandNode {
@@ -1840,7 +1846,7 @@ pub static REPLAY: CommandNode = CommandNode {
shape: REPLAY_PATH, shape: REPLAY_PATH,
ast_builder: build_replay, ast_builder: build_replay,
help_id: Some("data.replay"), help_id: Some("data.replay"),
hint_ids: &[], hint_ids: &["replay"],
usage_ids: &["parse.usage.replay"],}; usage_ids: &["parse.usage.replay"],};
pub static EXPLAIN: CommandNode = CommandNode { pub static EXPLAIN: CommandNode = CommandNode {
@@ -1848,7 +1854,7 @@ pub static EXPLAIN: CommandNode = CommandNode {
shape: EXPLAIN_SHAPE, shape: EXPLAIN_SHAPE,
ast_builder: build_explain, ast_builder: build_explain,
help_id: Some("data.explain"), help_id: Some("data.explain"),
hint_ids: &[], hint_ids: &["explain"],
usage_ids: &["parse.usage.explain"],}; usage_ids: &["parse.usage.explain"],};
/// `explain` over advanced-mode SQL (ADR-0039). /// `explain` over advanced-mode SQL (ADR-0039).
+30
View File
@@ -306,6 +306,36 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
("hint.cmd.change_column.what", &[]), ("hint.cmd.change_column.what", &[]),
("hint.cmd.change_column.example", &[]), ("hint.cmd.change_column.example", &[]),
("hint.cmd.change_column.concept", &[]), ("hint.cmd.change_column.concept", &[]),
// Phase C batch 3 — DML command hints.
("hint.cmd.update.what", &[]),
("hint.cmd.update.example", &[]),
("hint.cmd.update.concept", &[]),
("hint.cmd.delete.what", &[]),
("hint.cmd.delete.example", &[]),
("hint.cmd.delete.concept", &[]),
("hint.cmd.show_data.what", &[]),
("hint.cmd.show_data.example", &[]),
("hint.cmd.show_data.concept", &[]),
("hint.cmd.show_table.what", &[]),
("hint.cmd.show_table.example", &[]),
("hint.cmd.show_table.concept", &[]),
("hint.cmd.show_tables.what", &[]),
("hint.cmd.show_tables.example", &[]),
("hint.cmd.show_relationships.what", &[]),
("hint.cmd.show_relationships.example", &[]),
("hint.cmd.show_relationships.concept", &[]),
("hint.cmd.show_indexes.what", &[]),
("hint.cmd.show_indexes.example", &[]),
("hint.cmd.show_indexes.concept", &[]),
("hint.cmd.seed.what", &[]),
("hint.cmd.seed.example", &[]),
("hint.cmd.seed.concept", &[]),
("hint.cmd.explain.what", &[]),
("hint.cmd.explain.example", &[]),
("hint.cmd.explain.concept", &[]),
("hint.cmd.replay.what", &[]),
("hint.cmd.replay.example", &[]),
("hint.cmd.replay.concept", &[]),
( (
"hint.ambient_invalid_ident", "hint.ambient_invalid_ident",
&["kind", "found"], &["kind", "found"],
+40
View File
@@ -505,6 +505,46 @@ hint:
what: "Change a column's type, converting the existing values." what: "Change a column's type, converting the existing values."
example: "change column Customers: status (int)" example: "change column Customers: status (int)"
concept: "The database converts each stored value to the new type; if a value can't convert it refuses the change, so you don't silently lose data. Flags let you force or skip the conversion." concept: "The database converts each stored value to the new type; if a value can't convert it refuses the change, so you don't silently lose data. Flags let you force or skip the conversion."
# DML — querying and changing data (Phase C batch 3).
update:
what: "Change values in the rows that match a condition."
example: "update Customers set email = 'new@example.io' where id = 1"
concept: "The `where` clause picks which rows change, and it's required — pass `--all-rows` to change the whole table on purpose — so you never update more than you meant to."
delete:
what: "Remove the rows that match a condition."
example: "delete from Orders where status = 'cancelled'"
concept: "A `where` is required (use `--all-rows` to clear the table on purpose). Rows a relationship points at may be blocked or cascade-deleted, per its `on delete` action."
show_data:
what: "Show the rows stored in a table."
example: "show data Customers"
concept: "This reads the data and never changes it. Add a `where` to show only matching rows."
show_table:
what: "Show a table's structure — its columns, types, keys, and relationships."
example: "show table Customers"
concept: "Structure, not data: the column definitions and how this table links to others. Use `show data` to see the rows themselves."
show_tables:
what: "List all the tables in the project."
example: "show tables"
show_relationships:
what: "List all the relationships between tables."
example: "show relationships"
concept: "Each relationship is a foreign-key link from a child column to a parent's key, with an `on delete` / `on update` rule."
show_indexes:
what: "List all the indexes in the project."
example: "show indexes"
concept: "Indexes speed up lookups; this shows which columns each one covers and whether it enforces uniqueness."
seed:
what: "Fill a table with generated sample rows, or fill one column on existing rows."
example: "seed Customers 50"
concept: "Seeding invents realistic-looking data so you have something to query. Pin a value with `set col = …`, choose a generator with `as`, or give a numeric range with `between`."
explain:
what: "Show how the database will run a query — without running it."
example: "explain show data Customers where email = 'a@example.io'"
concept: "The plan reveals whether the database scans the whole table or jumps straight to rows through an index — the payoff of `add index`. `explain` never executes, so it's safe even on a delete."
replay:
what: "Re-run the commands recorded in a history file."
example: "replay session.log"
concept: "Every successful command is journalled, so replaying re-applies them in order to reproduce a project's state — handy for scripting or redoing a sequence."
err: err:
foreign_key: foreign_key:
child_side: child_side: