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:
@@ -7110,6 +7110,7 @@ fn resolve_fk_parent_columns(
|
||||
parent_pk: &[String],
|
||||
explicit: Option<&[String]>,
|
||||
child_arity: usize,
|
||||
inline: bool,
|
||||
) -> Result<Vec<String>, DbError> {
|
||||
if child_arity == 0 {
|
||||
return Err(DbError::Unsupported(
|
||||
@@ -7142,6 +7143,20 @@ fn resolve_fk_parent_columns(
|
||||
}
|
||||
};
|
||||
if parent_columns.len() != child_arity {
|
||||
// An inline column-level FK (`<col> REFERENCES …`) can only carry
|
||||
// the one column it sits on, so it can never satisfy a compound
|
||||
// key — point the user at the table-level form rather than the
|
||||
// generic arity message (ADR-0043 D4).
|
||||
if inline && parent_columns.len() > 1 {
|
||||
return Err(DbError::Unsupported(format!(
|
||||
"an inline column reference can only name one column, but \
|
||||
`{parent_table}`'s key has {n}. Use the table-level form \
|
||||
instead: `FOREIGN KEY (<columns>) REFERENCES \
|
||||
{parent_table} ({pk})`.",
|
||||
n = parent_columns.len(),
|
||||
pk = parent_columns.join(", "),
|
||||
)));
|
||||
}
|
||||
return Err(DbError::Unsupported(format!(
|
||||
"{child_arity} foreign-key column(s) on the child side, but \
|
||||
`{parent_table}`'s key has {n}. A foreign key references every \
|
||||
@@ -7210,6 +7225,7 @@ fn resolve_create_table_fks(
|
||||
&parent_pk,
|
||||
fk.parent_columns.as_deref(),
|
||||
fk.child_columns.len(),
|
||||
fk.inline,
|
||||
)?;
|
||||
|
||||
// Each child column must be one of the columns being defined,
|
||||
@@ -7295,6 +7311,7 @@ fn do_add_relationship(
|
||||
&parent_schema.primary_key,
|
||||
Some(parent_columns),
|
||||
child_columns.len(),
|
||||
false, // DSL `add relationship` is never an inline column FK
|
||||
)?;
|
||||
|
||||
// 2. Read child schema; refuse missing columns unless --create-fk.
|
||||
@@ -7824,6 +7841,7 @@ fn do_alter_add_foreign_key(
|
||||
&parent_pk,
|
||||
fk.parent_columns.as_deref(),
|
||||
fk.child_columns.len(),
|
||||
fk.inline, // false for `ALTER … ADD FOREIGN KEY` (table-level)
|
||||
)?;
|
||||
// Every child column must already exist for `ALTER … ADD FOREIGN
|
||||
// KEY` — there is no SQL spelling to auto-create one (`--create-fk`
|
||||
|
||||
Reference in New Issue
Block a user