nodedb_sql/planner/index_ddl/
drop.rs1use crate::types::DropIndexPlan;
6use sqlparser::ast;
7
8use crate::SqlPlan;
9use crate::error::{Result, SqlError};
10use crate::parser::normalize::normalize_object_name_checked;
11
12pub fn plan_drop_index(stmt: &ast::Statement) -> Result<SqlPlan> {
18 let ast::Statement::Drop {
19 object_type: ast::ObjectType::Index,
20 names,
21 if_exists,
22 table,
23 ..
24 } = stmt
25 else {
26 return Err(SqlError::Parse {
27 detail: "DROP INDEX: unexpected statement shape".into(),
28 });
29 };
30
31 let name = names.first().ok_or_else(|| SqlError::Parse {
32 detail: "DROP INDEX: an index name is required".into(),
33 })?;
34 let index_name = normalize_object_name_checked(name)?;
35 if index_name.is_empty() {
36 return Err(SqlError::Parse {
37 detail: "DROP INDEX: empty index name".into(),
38 });
39 }
40
41 let collection = match table.as_ref() {
42 Some(t) => Some(normalize_object_name_checked(t)?),
43 None => None,
44 };
45
46 Ok(SqlPlan::DropIndex(DropIndexPlan {
47 index_name,
48 collection,
49 if_exists: *if_exists,
50 }))
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use crate::parser::statement::parse_sql;
57
58 fn plan(sql: &str) -> Result<SqlPlan> {
59 let stmts = parse_sql(sql).expect("parse");
60 plan_drop_index(&stmts[0])
61 }
62
63 #[test]
64 fn basic_drop() {
65 let SqlPlan::DropIndex(DropIndexPlan {
66 index_name,
67 collection,
68 if_exists,
69 }) = plan("DROP INDEX idx_users_email").unwrap()
70 else {
71 panic!("expected DropIndex");
72 };
73 assert_eq!(index_name, "idx_users_email");
74 assert!(collection.is_none());
75 assert!(!if_exists);
76 }
77
78 #[test]
79 fn if_exists_honored() {
80 let SqlPlan::DropIndex(DropIndexPlan { if_exists, .. }) =
81 plan("DROP INDEX IF EXISTS idx").unwrap()
82 else {
83 panic!("expected DropIndex");
84 };
85 assert!(if_exists);
86 }
87
88 #[test]
89 fn schema_qualified_name_rejected() {
90 let err = plan("DROP INDEX public.idx").unwrap_err();
91 assert!(matches!(err, SqlError::Unsupported { .. }), "{err:?}");
92 }
93}