feat: compound-PK foreign-key references — grammar + tests (ADR-0043)
Multi-column FK parsing on both surfaces: DSL from P.(a, b) to C.(x, y) (parenthesized endpoint; single bare form unchanged) and SQL FOREIGN KEY (a, b) REFERENCES P(x, y) incl. bare-reference auto-expand. consume_fk_reference + the table-level/ALTER FK parsers collect column lists; the from P. completion now offers ( (snapshots updated). 12 integration tests in tests/it/compound_fk.rs cover parse (both surfaces), engine-enforced FK, arity + partial-PK + per-pair-type-mismatch refusal, --create-fk per-column, save->rebuild round-trip, undo (one step), and single-column preservation. Mark T3 [x]; ADR-0043 implemented.
This commit is contained in:
@@ -182,7 +182,15 @@ const FK_PARENT_COLUMN: Node = Node::Ident {
|
||||
writes_cte_name: false,
|
||||
writes_projection_alias: false,
|
||||
};
|
||||
static FK_PARENT_COL_NODES: &[Node] = &[Node::Punct('('), FK_PARENT_COLUMN, Node::Punct(')')];
|
||||
// `( a [, b]* )` — a compound FK references multiple parent columns
|
||||
// (ADR-0043). The `Repeated` separator handles the commas; a
|
||||
// single-column FK is the one-element case.
|
||||
const FK_PARENT_COL_LIST: Node = Node::Repeated {
|
||||
inner: &FK_PARENT_COLUMN,
|
||||
separator: Some(&Node::Punct(',')),
|
||||
min: 1,
|
||||
};
|
||||
static FK_PARENT_COL_NODES: &[Node] = &[Node::Punct('('), FK_PARENT_COL_LIST, Node::Punct(')')];
|
||||
const FK_PARENT_COL_OPT: Node = Node::Optional(&Node::Seq(FK_PARENT_COL_NODES));
|
||||
|
||||
// `REFERENCES <parent> [ ( <col> ) ] [on delete/update …]` — the inline
|
||||
@@ -333,6 +341,13 @@ const FK_CHILD_COLUMN: Node = Node::Ident {
|
||||
writes_cte_name: false,
|
||||
writes_projection_alias: false,
|
||||
};
|
||||
// `( a [, b]* )` — a compound FK lists multiple child columns
|
||||
// (ADR-0043); single-column is the one-element case.
|
||||
const FK_CHILD_COL_LIST: Node = Node::Repeated {
|
||||
inner: &FK_CHILD_COLUMN,
|
||||
separator: Some(&Node::Punct(',')),
|
||||
min: 1,
|
||||
};
|
||||
const FK_NAME: Node = Node::Ident {
|
||||
source: IdentSource::NewName,
|
||||
role: "fk_name",
|
||||
@@ -354,7 +369,7 @@ static FOREIGN_KEY_BODY_NODES: &[Node] = &[
|
||||
Node::Word(Word::keyword("foreign")),
|
||||
Node::Word(Word::keyword("key")),
|
||||
Node::Punct('('),
|
||||
FK_CHILD_COLUMN,
|
||||
FK_CHILD_COL_LIST,
|
||||
Node::Punct(')'),
|
||||
Node::Word(Word::keyword("references")),
|
||||
FK_PARENT_TABLE,
|
||||
@@ -374,7 +389,7 @@ static TABLE_FK_NAMED_NODES: &[Node] = &[
|
||||
Node::Word(Word::keyword("foreign")),
|
||||
Node::Word(Word::keyword("key")),
|
||||
Node::Punct('('),
|
||||
FK_CHILD_COLUMN,
|
||||
FK_CHILD_COL_LIST,
|
||||
Node::Punct(')'),
|
||||
Node::Word(Word::keyword("references")),
|
||||
FK_PARENT_TABLE,
|
||||
|
||||
Reference in New Issue
Block a user