Indexes: add index / drop index, persistence, display (ADR-0025)
Implement ADR-0025 — indexes as a DSL DDL feature. - Grammar: `add index [as <name>] on <T> (<cols>)`, `drop index <name>` / `drop index on <T> (<cols>)`, plus a `--cascade` flag on `drop column`. - db.rs: index operations over the engine's native index catalog (no metadata table). The rebuild-table primitive now captures and recreates indexes, so `change column` and the relationship operations no longer silently drop them. - `drop column` refuses an indexed column unless `--cascade`, which drops the covering indexes and reports each. - Persistence: additive `indexes:` list in `project.yaml` (version unchanged); round-trips through rebuild/export/import. - Display: an `Indexes:` section in the structure view and a nested tables/indexes items panel (S2). Reconciles requirements.md (C3 index portion, S2 satisfied) and CLAUDE.md. 1038 tests passing (+31), clippy clean.
This commit is contained in:
+81
-1
@@ -235,6 +235,7 @@ fn format_expectation(e: &crate::dsl::walker::outcome::Expectation) -> String {
|
||||
IdentSource::Tables => "table name".to_string(),
|
||||
IdentSource::Columns => "column name".to_string(),
|
||||
IdentSource::Relationships => "relationship name".to_string(),
|
||||
IdentSource::Indexes => "index name".to_string(),
|
||||
IdentSource::Types => "type".to_string(),
|
||||
IdentSource::NewName | IdentSource::Free => "identifier".to_string(),
|
||||
},
|
||||
@@ -316,7 +317,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::dsl::action::ReferentialAction;
|
||||
use crate::dsl::command::{
|
||||
ChangeColumnMode, ColumnSpec, RelationshipSelector, RowFilter,
|
||||
ChangeColumnMode, ColumnSpec, IndexSelector, RelationshipSelector, RowFilter,
|
||||
};
|
||||
use crate::dsl::types::Type;
|
||||
use crate::dsl::value::Value;
|
||||
@@ -471,6 +472,7 @@ mod tests {
|
||||
Command::DropColumn {
|
||||
table: "Customers".to_string(),
|
||||
column: "Email".to_string(),
|
||||
cascade: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -482,6 +484,7 @@ mod tests {
|
||||
Command::DropColumn {
|
||||
table: "Customers".to_string(),
|
||||
column: "Email".to_string(),
|
||||
cascade: false,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -489,6 +492,7 @@ mod tests {
|
||||
Command::DropColumn {
|
||||
table: "Customers".to_string(),
|
||||
column: "Email".to_string(),
|
||||
cascade: false,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -496,6 +500,7 @@ mod tests {
|
||||
Command::DropColumn {
|
||||
table: "Customers".to_string(),
|
||||
column: "Email".to_string(),
|
||||
cascade: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1156,6 +1161,81 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// --- add index / drop index (ADR-0025) ---
|
||||
|
||||
#[test]
|
||||
fn add_index_named() {
|
||||
assert_eq!(
|
||||
ok("add index as idx_email on Customers (Email)"),
|
||||
Command::AddIndex {
|
||||
name: Some("idx_email".to_string()),
|
||||
table: "Customers".to_string(),
|
||||
columns: vec!["Email".to_string()],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_index_unnamed() {
|
||||
assert_eq!(
|
||||
ok("add index on Customers (Email)"),
|
||||
Command::AddIndex {
|
||||
name: None,
|
||||
table: "Customers".to_string(),
|
||||
columns: vec!["Email".to_string()],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_index_composite_columns() {
|
||||
assert_eq!(
|
||||
ok("add index on Orders (CustId, Date)"),
|
||||
Command::AddIndex {
|
||||
name: None,
|
||||
table: "Orders".to_string(),
|
||||
columns: vec!["CustId".to_string(), "Date".to_string()],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drop_index_by_name() {
|
||||
assert_eq!(
|
||||
ok("drop index idx_email"),
|
||||
Command::DropIndex {
|
||||
selector: IndexSelector::Named {
|
||||
name: "idx_email".to_string(),
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drop_index_by_columns() {
|
||||
assert_eq!(
|
||||
ok("drop index on Customers (Email)"),
|
||||
Command::DropIndex {
|
||||
selector: IndexSelector::Columns {
|
||||
table: "Customers".to_string(),
|
||||
columns: vec!["Email".to_string()],
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drop_column_cascade_flag() {
|
||||
assert_eq!(
|
||||
ok("drop column Customers: Email --cascade"),
|
||||
Command::DropColumn {
|
||||
table: "Customers".to_string(),
|
||||
column: "Email".to_string(),
|
||||
cascade: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn identifier_allows_underscores_and_digits_after_start() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user