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:
+8
@@ -14,6 +14,10 @@ Assessment {
|
||||
text: "column",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "index",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "1:n",
|
||||
kind: Keyword,
|
||||
@@ -34,6 +38,10 @@ Assessment {
|
||||
text: "column",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "index",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "1:n",
|
||||
kind: Keyword,
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
source: tests/typing_surface/index_ops.rs
|
||||
description: "input=\"add index on \" cursor=13"
|
||||
expression: "& a"
|
||||
---
|
||||
Assessment {
|
||||
input: "add index on ",
|
||||
cursor: 13,
|
||||
state: IncompleteAtEof,
|
||||
hint: Some(
|
||||
Candidates {
|
||||
items: [
|
||||
Candidate {
|
||||
text: "Customers",
|
||||
kind: Identifier,
|
||||
},
|
||||
Candidate {
|
||||
text: "Orders",
|
||||
kind: Identifier,
|
||||
},
|
||||
],
|
||||
selected: None,
|
||||
},
|
||||
),
|
||||
completion: Some(
|
||||
Completion {
|
||||
replaced_range: (
|
||||
13,
|
||||
13,
|
||||
),
|
||||
partial_prefix: "",
|
||||
candidates: [
|
||||
Candidate {
|
||||
text: "Customers",
|
||||
kind: Identifier,
|
||||
},
|
||||
Candidate {
|
||||
text: "Orders",
|
||||
kind: Identifier,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
parse_result: Err(
|
||||
"Invalid(at_eof)",
|
||||
),
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
---
|
||||
source: tests/typing_surface/index_ops.rs
|
||||
description: "input=\"add index on Orders (\" cursor=21"
|
||||
expression: "& a"
|
||||
---
|
||||
Assessment {
|
||||
input: "add index on Orders (",
|
||||
cursor: 21,
|
||||
state: IncompleteAtEof,
|
||||
hint: Some(
|
||||
Candidates {
|
||||
items: [
|
||||
Candidate {
|
||||
text: "CustId",
|
||||
kind: Identifier,
|
||||
},
|
||||
Candidate {
|
||||
text: "OrderId",
|
||||
kind: Identifier,
|
||||
},
|
||||
Candidate {
|
||||
text: "Total",
|
||||
kind: Identifier,
|
||||
},
|
||||
],
|
||||
selected: None,
|
||||
},
|
||||
),
|
||||
completion: Some(
|
||||
Completion {
|
||||
replaced_range: (
|
||||
21,
|
||||
21,
|
||||
),
|
||||
partial_prefix: "",
|
||||
candidates: [
|
||||
Candidate {
|
||||
text: "CustId",
|
||||
kind: Identifier,
|
||||
},
|
||||
Candidate {
|
||||
text: "OrderId",
|
||||
kind: Identifier,
|
||||
},
|
||||
Candidate {
|
||||
text: "Total",
|
||||
kind: Identifier,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
parse_result: Err(
|
||||
"Invalid(at_eof)",
|
||||
),
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
---
|
||||
source: tests/typing_surface/index_ops.rs
|
||||
description: "input=\"add \" cursor=4"
|
||||
expression: "& a"
|
||||
---
|
||||
Assessment {
|
||||
input: "add ",
|
||||
cursor: 4,
|
||||
state: IncompleteAtEof,
|
||||
hint: Some(
|
||||
Candidates {
|
||||
items: [
|
||||
Candidate {
|
||||
text: "column",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "index",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "1:n",
|
||||
kind: Keyword,
|
||||
},
|
||||
],
|
||||
selected: None,
|
||||
},
|
||||
),
|
||||
completion: Some(
|
||||
Completion {
|
||||
replaced_range: (
|
||||
4,
|
||||
4,
|
||||
),
|
||||
partial_prefix: "",
|
||||
candidates: [
|
||||
Candidate {
|
||||
text: "column",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "index",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "1:n",
|
||||
kind: Keyword,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
parse_result: Err(
|
||||
"Invalid(at_eof)",
|
||||
),
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
---
|
||||
source: tests/typing_surface/index_ops.rs
|
||||
description: "input=\"drop \" cursor=5"
|
||||
expression: "& a"
|
||||
---
|
||||
Assessment {
|
||||
input: "drop ",
|
||||
cursor: 5,
|
||||
state: IncompleteAtEof,
|
||||
hint: Some(
|
||||
Candidates {
|
||||
items: [
|
||||
Candidate {
|
||||
text: "column",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "relationship",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "table",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "index",
|
||||
kind: Keyword,
|
||||
},
|
||||
],
|
||||
selected: None,
|
||||
},
|
||||
),
|
||||
completion: Some(
|
||||
Completion {
|
||||
replaced_range: (
|
||||
5,
|
||||
5,
|
||||
),
|
||||
partial_prefix: "",
|
||||
candidates: [
|
||||
Candidate {
|
||||
text: "column",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "relationship",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "table",
|
||||
kind: Keyword,
|
||||
},
|
||||
Candidate {
|
||||
text: "index",
|
||||
kind: Keyword,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
parse_result: Err(
|
||||
"Invalid(at_eof)",
|
||||
),
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
---
|
||||
source: tests/typing_surface/index_ops.rs
|
||||
description: "input=\"add index as ord_cust on Orders (CustId)\" cursor=40"
|
||||
expression: "& a"
|
||||
---
|
||||
Assessment {
|
||||
input: "add index as ord_cust on Orders (CustId)",
|
||||
cursor: 40,
|
||||
state: Valid,
|
||||
hint: Some(
|
||||
Prose(
|
||||
"Submit with Enter",
|
||||
),
|
||||
),
|
||||
completion: None,
|
||||
parse_result: Ok(
|
||||
"AddIndex",
|
||||
),
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
---
|
||||
source: tests/typing_surface/index_ops.rs
|
||||
description: "input=\"add index on Orders (CustId)\" cursor=28"
|
||||
expression: "& a"
|
||||
---
|
||||
Assessment {
|
||||
input: "add index on Orders (CustId)",
|
||||
cursor: 28,
|
||||
state: Valid,
|
||||
hint: Some(
|
||||
Prose(
|
||||
"Submit with Enter",
|
||||
),
|
||||
),
|
||||
completion: None,
|
||||
parse_result: Ok(
|
||||
"AddIndex",
|
||||
),
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
---
|
||||
source: tests/typing_surface/index_ops.rs
|
||||
description: "input=\"drop index on Orders (CustId)\" cursor=29"
|
||||
expression: "& a"
|
||||
---
|
||||
Assessment {
|
||||
input: "drop index on Orders (CustId)",
|
||||
cursor: 29,
|
||||
state: Valid,
|
||||
hint: Some(
|
||||
Prose(
|
||||
"Submit with Enter",
|
||||
),
|
||||
),
|
||||
completion: None,
|
||||
parse_result: Ok(
|
||||
"DropIndex",
|
||||
),
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
---
|
||||
source: tests/typing_surface/index_ops.rs
|
||||
description: "input=\"drop index some_idx\" cursor=19"
|
||||
expression: "& a"
|
||||
---
|
||||
Assessment {
|
||||
input: "drop index some_idx",
|
||||
cursor: 19,
|
||||
state: Valid,
|
||||
hint: Some(
|
||||
Prose(
|
||||
"No such identifier: `some_idx`",
|
||||
),
|
||||
),
|
||||
completion: None,
|
||||
parse_result: Ok(
|
||||
"DropIndex",
|
||||
),
|
||||
}
|
||||
Reference in New Issue
Block a user