feat: ADR-0035 Amendment 1 — drop composite UNIQUE; friendlier drop-column + generic-error wording
F1/F2/F3 from the whole-Phase-4 /runda (handoff-42 §3):
- F3: drop an anonymous composite UNIQUE via a derived, engine-neutral
name `unique_<cols>` — recomputed live, nothing persisted, reusing the
existing `DROP CONSTRAINT <name>` grammar (no new syntax/metadata, the
§4g anonymity decision intact). A name matching more than one UNIQUE is
refused as ambiguous, never guessed. One undo step. `describe`
annotates each composite UNIQUE with its name.
- F1: dropping a column a composite UNIQUE covers is refused up-front
with the derived name + the actionable drop command (was an unhelpful
generic engine refusal).
- F2: contextless friendly_message() no longer leaks a literal `{table}`
in the generic hint (new `error.generic.hint_no_table`, selected when
no table is in context). The table-ful path is unchanged.
Docs: ADR-0035 Amendment 1 + Status + README index + plan
docs/plans/20260526-adr-0035-composite-unique-drop-f1f2f3.md.
Tests: +5 (drop-by-name, ambiguous-refused, one-undo-step, F1 guard,
F2 no-leak) + a describe-render assertion. 1922 pass / 0 fail / 0 skip;
clippy clean.
This commit is contained in:
+10
-1
@@ -160,7 +160,13 @@ pub fn render_structure(desc: &TableDescription) -> Vec<String> {
|
||||
if !desc.unique_constraints.is_empty() || !desc.check_constraints.is_empty() {
|
||||
out.push("Table constraints:".to_string());
|
||||
for cols in &desc.unique_constraints {
|
||||
out.push(format!(" unique ({})", cols.join(", ")));
|
||||
// Annotate with the derived, addressable name (ADR-0035
|
||||
// Amendment 1) so the user can `drop constraint <name>`.
|
||||
out.push(format!(
|
||||
" {}: unique ({})",
|
||||
crate::db::unique_constraint_name(cols),
|
||||
cols.join(", ")
|
||||
));
|
||||
}
|
||||
for chk in &desc.check_constraints {
|
||||
match &chk.name {
|
||||
@@ -880,6 +886,9 @@ mod tests {
|
||||
let out = render_structure(&desc).join("\n");
|
||||
assert!(out.contains("Table constraints:"), "got:\n{out}");
|
||||
assert!(out.contains("unique (a, b)"), "got:\n{out}");
|
||||
// The composite UNIQUE shows its derived, addressable name
|
||||
// (ADR-0035 Amendment 1) so the user can `drop constraint <name>`.
|
||||
assert!(out.contains("unique_a_b: unique (a, b)"), "got:\n{out}");
|
||||
assert!(out.contains("check (a < b)"), "unnamed check; got:\n{out}");
|
||||
assert!(out.contains("check a_lt_b (a <> b)"), "named check shows its name; got:\n{out}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user