feat: ADR-0035 4g — ALTER TABLE add/drop constraint + add FK
ALTER TABLE <T> ADD [CONSTRAINT <name>] (CHECK | UNIQUE | FOREIGN KEY)
and DROP CONSTRAINT <name>. ADD = table-CHECK + composite UNIQUE + FK
(ADD PRIMARY KEY and a named UNIQUE refused — composite UNIQUE is
anonymous in our model). Each ADD reuses a low-level path with a dry-run
guard (table-CHECK/UNIQUE rebuild; FK -> add_relationship, bare
REFERENCES -> parent single PK). DROP CONSTRAINT resolves the name to a
named table-CHECK then a child-side FK, else refuses. One undo step each.
Named table-CHECKs round-trip: a nullable `name` column on
__rdbms_playground_table_checks (rebuild-only arrival; a named add on a
pre-4g project is refused with a "rebuild first" hint) plus a project.yaml
check_constraints {expr, name} extension (bare-string form still reads).
The internal-__rdbms_* guard was folded into do_add_constraint /
do_add_relationship, completing that guard class.
Grammar: the action Choice keeps one branch per verb (add/drop/rename/
alter) with an inner Choice fanning out on the distinct second keyword,
since the walker's Choice does not backtrack between same-led branches.
Tests: 7 Tier-1 parse + 2 yaml round-trip + 1 internal-guard + 9 Tier-3
e2e. Help/usage refreshed; ADR-0035 §13 4g + README + requirements.md in
lockstep.
This commit is contained in:
@@ -739,6 +739,35 @@ pub enum AlterTableAction {
|
||||
/// force flag; static-refused / incompatible still refuse). One undo
|
||||
/// step (the executor's rebuild). ADR-0035 §4f.
|
||||
AlterColumnType { column: String, ty: Type },
|
||||
/// `ADD [CONSTRAINT <name>] (CHECK (…) | UNIQUE (…) | FOREIGN KEY
|
||||
/// (…) REFERENCES …)` — a table-level constraint (ADR-0035 §4g). The
|
||||
/// `name` is the `CONSTRAINT <name>` prefix (the FK carries its own
|
||||
/// `SqlForeignKey::name`, set from this prefix at build time). CHECK
|
||||
/// and FOREIGN KEY may be named; UNIQUE may not (composite UNIQUE is
|
||||
/// anonymous in our model — §4g). Boxed: the FK payload is sizeable
|
||||
/// (`clippy::large_enum_variant`).
|
||||
AddTableConstraint {
|
||||
name: Option<String>,
|
||||
constraint: Box<TableConstraint>,
|
||||
},
|
||||
/// `DROP CONSTRAINT <name>` — drops a named table-level CHECK or a
|
||||
/// named FK (relationship), resolved by name (ADR-0035 §4g).
|
||||
DropConstraint { name: String },
|
||||
}
|
||||
|
||||
/// A table-level constraint added via `ALTER TABLE … ADD [CONSTRAINT
|
||||
/// <name>] …` (ADR-0035 §4g).
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum TableConstraint {
|
||||
/// `CHECK (<expr>)` — the expression as **raw SQL text** (the
|
||||
/// `sql_expr` grammar is validate-only; the builder captures the
|
||||
/// matched span — the 4a.2 / 4e mechanism).
|
||||
Check { expr_sql: String },
|
||||
/// `UNIQUE (<col>, …)` — a composite UNIQUE constraint.
|
||||
Unique { columns: Vec<String> },
|
||||
/// `FOREIGN KEY (<col>) REFERENCES <P>[(<col>)] [ON …]` — reuses the
|
||||
/// 4b `SqlForeignKey` shape; decomposed to `add_relationship`.
|
||||
ForeignKey(SqlForeignKey),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for IndexSelector {
|
||||
|
||||
Reference in New Issue
Block a user