fix(fk): inline FK referencing a compound PK points at the table-level form

ADR-0043 D4 residual: an inline column-level FK (`<col> REFERENCES P(a,b)`)
is single-column by construction, so referencing a parent's compound PK
gave the generic arity error ("1 foreign-key column(s) on the child side,
but `P`'s key has 2..."). It now points the user at the table-level form:
"an inline column reference can only name one column ... Use the table-level
form instead: FOREIGN KEY (<columns>) REFERENCES P (a, b)".

- Adds `inline: bool` to SqlForeignKey, set by the grammar's single shared
  builder consume_fk_reference (true for the inline path, false for the
  table-level and ALTER paths).
- resolve_fk_parent_columns takes `inline` and tailors the arity-mismatch
  message when an inline FK meets a compound key.

Tests: parse-layer (inline=true / table-level=false) + end-to-end worker
refusal wording. 2209 pass / 0 fail / 1 ignored. Clippy clean.
This commit is contained in:
claude@clouddev1
2026-06-10 11:49:33 +00:00
parent 0a7612efe2
commit 6985a43f31
7 changed files with 104 additions and 3 deletions
+10
View File
@@ -1004,6 +1004,16 @@ mod builder_tests {
assert_eq!(fk.parent_columns, Some(vec!["id".to_string()]));
assert_eq!(fk.on_delete, ReferentialAction::NoAction);
assert_eq!(fk.on_update, ReferentialAction::NoAction);
assert!(fk.inline, "a column-level `references` is an inline FK (ADR-0043 D4)");
}
#[test]
fn table_level_fk_is_not_inline() {
// The table-level `FOREIGN KEY (...)` form is not inline, so it can
// carry a multi-column reference and never triggers the inline
// "use the table-level form" hint (ADR-0043 D4).
let fks = parse_sct_fks("create table t (id int, pid int, foreign key (pid) references parent(id))");
assert!(!fks[0].inline, "table-level FOREIGN KEY is not inline");
}
#[test]