feat(hint): H2 Phase C batch 5 — runtime error-class tier-3 hints (ADR-0053)
what/example(fix recipe)/concept for the 9 runtime error classes: foreign_key parent_side (child_side was the exemplar), unique, not_null, check, type_mismatch, not_found, already_exists, generic, invalid_value. Keyed by friendly::error_hint_class; catalogue + keys.rs registered. +1 spot test; 2496 pass / 1 ignored, clippy clean.
This commit is contained in:
+11
@@ -5922,6 +5922,17 @@ mod tests {
|
|||||||
assert!(output_contains(&app, "heart of SQL"));
|
assert!(output_contains(&app, "heart of SQL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Phase C batch 5: runtime error-class hints render ───────
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hint_renders_a_runtime_error_block() {
|
||||||
|
let mut app = App::new();
|
||||||
|
app.last_error_hint_key = Some("unique".to_string());
|
||||||
|
type_str(&mut app, "hint");
|
||||||
|
submit(&mut app);
|
||||||
|
assert!(output_contains(&app, "must be unique"));
|
||||||
|
}
|
||||||
|
|
||||||
#[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();
|
||||||
|
|||||||
@@ -234,6 +234,32 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
|
|||||||
("hint.err.foreign_key.child_side.what", &[]),
|
("hint.err.foreign_key.child_side.what", &[]),
|
||||||
("hint.err.foreign_key.child_side.example", &[]),
|
("hint.err.foreign_key.child_side.example", &[]),
|
||||||
("hint.err.foreign_key.child_side.concept", &[]),
|
("hint.err.foreign_key.child_side.concept", &[]),
|
||||||
|
// Phase C batch 5 — runtime error-class hints.
|
||||||
|
("hint.err.foreign_key.parent_side.what", &[]),
|
||||||
|
("hint.err.foreign_key.parent_side.example", &[]),
|
||||||
|
("hint.err.foreign_key.parent_side.concept", &[]),
|
||||||
|
("hint.err.unique.what", &[]),
|
||||||
|
("hint.err.unique.example", &[]),
|
||||||
|
("hint.err.unique.concept", &[]),
|
||||||
|
("hint.err.not_null.what", &[]),
|
||||||
|
("hint.err.not_null.example", &[]),
|
||||||
|
("hint.err.not_null.concept", &[]),
|
||||||
|
("hint.err.check.what", &[]),
|
||||||
|
("hint.err.check.example", &[]),
|
||||||
|
("hint.err.check.concept", &[]),
|
||||||
|
("hint.err.type_mismatch.what", &[]),
|
||||||
|
("hint.err.type_mismatch.example", &[]),
|
||||||
|
("hint.err.type_mismatch.concept", &[]),
|
||||||
|
("hint.err.not_found.what", &[]),
|
||||||
|
("hint.err.not_found.example", &[]),
|
||||||
|
("hint.err.not_found.concept", &[]),
|
||||||
|
("hint.err.already_exists.what", &[]),
|
||||||
|
("hint.err.already_exists.example", &[]),
|
||||||
|
("hint.err.already_exists.concept", &[]),
|
||||||
|
("hint.err.generic.what", &[]),
|
||||||
|
("hint.err.generic.example", &[]),
|
||||||
|
("hint.err.invalid_value.what", &[]),
|
||||||
|
("hint.err.invalid_value.example", &[]),
|
||||||
// Phase C batch 1 — app-lifecycle command hints.
|
// Phase C batch 1 — app-lifecycle command hints.
|
||||||
("hint.cmd.quit.what", &[]),
|
("hint.cmd.quit.what", &[]),
|
||||||
("hint.cmd.quit.example", &[]),
|
("hint.cmd.quit.example", &[]),
|
||||||
|
|||||||
@@ -592,11 +592,48 @@ hint:
|
|||||||
example: "explain select * from Customers where email = 'a@example.io'"
|
example: "explain select * from Customers where email = 'a@example.io'"
|
||||||
concept: "Like simple mode's `explain`, but wraps a raw SQL statement. It reveals whether an index is used, and never executes."
|
concept: "Like simple mode's `explain`, but wraps a raw SQL statement. It reveals whether an index is used, and never executes."
|
||||||
err:
|
err:
|
||||||
|
# Runtime error classes (Phase C batch 5), keyed by
|
||||||
|
# friendly::error_hint_class. `example` is a fix recipe rather than a
|
||||||
|
# runnable line; `concept` is the relational idea behind the rule.
|
||||||
foreign_key:
|
foreign_key:
|
||||||
child_side:
|
child_side:
|
||||||
what: "The value you gave for the child column doesn't match any parent row, so the foreign key has nothing to point at."
|
what: "The value you gave for the child column doesn't match any parent row, so the foreign key has nothing to point at."
|
||||||
example: "First insert the parent (insert into Customers …), then the child that references it."
|
example: "First insert the parent (insert into Customers …), then the child that references it."
|
||||||
concept: "A foreign key is a promise that every child points at a real parent, so the parent must exist first. To allow orphans on delete instead, set the relationship's `on delete` to `set null` or `cascade`."
|
concept: "A foreign key is a promise that every child points at a real parent, so the parent must exist first. To allow orphans on delete instead, set the relationship's `on delete` to `set null` or `cascade`."
|
||||||
|
parent_side:
|
||||||
|
what: "You're deleting or changing a row that other rows point at, which would orphan those children."
|
||||||
|
example: "Delete the child rows first, or set the relationship's `on delete` to `cascade` (remove them too) or `set null` (keep them, unlinked)."
|
||||||
|
concept: "A foreign key guarantees every child has a real parent, so the database won't remove a parent out from under its children unless the relationship says what should happen to them."
|
||||||
|
unique:
|
||||||
|
what: "A value you're inserting — or updating to — already exists in a column that must be unique."
|
||||||
|
example: "Pick a different value, or update the existing row instead of inserting a new one."
|
||||||
|
concept: "A unique constraint (and every primary key) forbids duplicates, so each value identifies at most one row."
|
||||||
|
not_null:
|
||||||
|
what: "You left a column empty that is required to have a value."
|
||||||
|
example: "Supply a value for the column, or give it a default so new rows fill it automatically."
|
||||||
|
concept: "A `not null` constraint means every row must have a value there — it's how you mark a fact as mandatory."
|
||||||
|
check:
|
||||||
|
what: "A value broke a `check` rule defined on the column."
|
||||||
|
example: "Use a value the rule allows — for example a positive number, or one of the permitted options."
|
||||||
|
concept: "A `check` constraint is a condition every row must satisfy, so the database enforces business rules like \"price ≥ 0\" for you."
|
||||||
|
type_mismatch:
|
||||||
|
what: "A value doesn't fit the column's type — for instance text where a number is expected."
|
||||||
|
example: "Give a value of the right type: a number for `int`/`real`, a quoted string for `text`, true/false for `bool`."
|
||||||
|
concept: "Every column has a type, and the database rejects values that don't fit, so a column's data stays consistent and comparable."
|
||||||
|
not_found:
|
||||||
|
what: "You named a table or column that doesn't exist."
|
||||||
|
example: "Check the spelling, or run `show tables` (or `show table <name>`) to see what's there."
|
||||||
|
concept: "A command can only refer to tables and columns that already exist — create them first if you need them."
|
||||||
|
already_exists:
|
||||||
|
what: "You tried to create a table, column, relationship, or index whose name is already taken."
|
||||||
|
example: "Pick a different name, or drop the existing one first if you meant to replace it."
|
||||||
|
concept: "Names must be unique within their kind so a command is never ambiguous about what it refers to."
|
||||||
|
generic:
|
||||||
|
what: "The database refused the command for the reason shown above."
|
||||||
|
example: "Read that message for the specifics, adjust the command, and try again."
|
||||||
|
invalid_value:
|
||||||
|
what: "A value or option in the command wasn't valid for where it was used."
|
||||||
|
example: "Check the value against the column's type and the command's accepted options."
|
||||||
# Invalid identifier in a schema slot (ADR-0022 stage 8e
|
# Invalid identifier in a schema slot (ADR-0022 stage 8e
|
||||||
# + the user's #5). Voice mirrors ADR-0019's "no such
|
# + the user's #5). Voice mirrors ADR-0019's "no such
|
||||||
# {kind}" wording for consistency with engine errors.
|
# {kind}" wording for consistency with engine errors.
|
||||||
|
|||||||
Reference in New Issue
Block a user