Skip to content

Commit

Permalink
feat: implement drop database parser
Browse files Browse the repository at this point in the history
  • Loading branch information
WenyXu committed Mar 14, 2024
1 parent 7244140 commit e56bee4
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/frontend/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,8 @@ pub fn check_permission(
// These are executed by query engine, and will be checked there.
Statement::Query(_) | Statement::Explain(_) | Statement::Tql(_) | Statement::Delete(_) => {}
// database ops won't be checked
Statement::CreateDatabase(_) | Statement::ShowDatabases(_) => {}
Statement::CreateDatabase(_) | Statement::ShowDatabases(_) | Statement::DropDatabase(_) => {
}
// show create table and alter are not supported yet
Statement::ShowCreateTable(_) | Statement::CreateExternalTable(_) | Statement::Alter(_) => {
}
Expand Down
7 changes: 7 additions & 0 deletions src/operator/src/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ impl StatementExecutor {
let table_name = TableName::new(catalog, schema, table);
self.drop_table(table_name, stmt.drop_if_exists()).await
}
Statement::DropDatabase(_stmt) => {
//TODO(weny): implement the drop database procedure
error::NotSupportedSnafu {
feat: "Drop Database",
}
.fail()
}
Statement::TruncateTable(stmt) => {
let (catalog, schema, table) =
table_idents_to_full_name(stmt.table_name(), &query_ctx)
Expand Down
101 changes: 99 additions & 2 deletions src/sql/src/parsers/drop_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use sqlparser::tokenizer::Token;

use crate::error::{self, InvalidTableNameSnafu, Result};
use crate::parser::ParserContext;
use crate::statements::drop::DropTable;
use crate::statements::drop::{DropDatabase, DropTable};
use crate::statements::statement::Statement;

/// DROP statement parser implementation
Expand Down Expand Up @@ -59,7 +59,23 @@ impl<'a> ParserContext<'a> {
}

fn parse_drop_database(&mut self) -> Result<Statement> {
todo!()
let _ = self.parser.next_token();

let if_exists = self.parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
let database_name =
self.parser
.parse_object_name()
.with_context(|_| error::UnexpectedSnafu {
sql: self.sql,
expected: "a database name",
actual: self.peek_token_as_string(),
})?;
let database_name = Self::canonicalize_object_name(database_name);

Ok(Statement::DropDatabase(DropDatabase::new(
database_name,
if_exists,
)))
}
}

Expand Down Expand Up @@ -119,4 +135,85 @@ mod tests {
))
)
}

#[test]
pub fn test_drop_database() {
let sql = "DROP DATABASE public";
let result =
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
let mut stmts = result.unwrap();
assert_eq!(
stmts.pop().unwrap(),
Statement::DropDatabase(DropDatabase::new(
ObjectName(vec![Ident::new("public")]),
false
))
);

let sql = "DROP DATABASE IF EXISTS public";
let result =
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
let mut stmts = result.unwrap();
assert_eq!(
stmts.pop().unwrap(),
Statement::DropDatabase(DropDatabase::new(
ObjectName(vec![Ident::new("public")]),
true
))
);

let sql = "DROP DATABASE my_catalog.foo";
let result =
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
let mut stmts = result.unwrap();
assert_eq!(
stmts.pop().unwrap(),
Statement::DropDatabase(DropDatabase::new(
ObjectName(vec![Ident::new("my_catalog"), Ident::new("foo")]),
false
))
);

let sql = "DROP DATABASE MY_CATALOG.FOO";
let result =
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
let mut stmts = result.unwrap();
assert_eq!(
stmts.pop().unwrap(),
Statement::DropDatabase(DropDatabase::new(
ObjectName(vec![Ident::new("my_catalog"), Ident::new("foo")]),
false
))
);

let sql = "DROP DATABASE `My_cAtAlOg`.`fOo`";
let result =
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
let mut stmts = result.unwrap();
assert_eq!(
stmts.pop().unwrap(),
Statement::DropDatabase(DropDatabase::new(
ObjectName(vec![
Ident::with_quote('`', "My_cAtAlOg"),
Ident::with_quote('`', "fOo"),
]),
false
))
);

let sql = "DROP DATABASE `My_cAtAlOg`.foo";
let result =
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
let mut stmts = result.unwrap();
assert_eq!(
stmts.pop().unwrap(),
Statement::DropDatabase(DropDatabase::new(
ObjectName(vec![
Ident::with_quote('`', "My_cAtAlOg"),
Ident::new("foo"),
]),
false
))
);
}
}
26 changes: 26 additions & 0 deletions src/sql/src/statements/drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,29 @@ impl DropTable {
self.drop_if_exists
}
}

/// DROP DATABASE statement.
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
pub struct DropDatabase {
name: ObjectName,
/// drop table if exists
drop_if_exists: bool,
}

impl DropDatabase {
/// Creates a statement for `DROP DATABASE`
pub fn new(name: ObjectName, if_exists: bool) -> Self {
Self {
name,
drop_if_exists: if_exists,
}
}

pub fn name(&self) -> &ObjectName {
&self.name
}

pub fn drop_if_exists(&self) -> bool {
self.drop_if_exists
}
}
3 changes: 3 additions & 0 deletions src/sql/src/statements/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use datafusion_sql::parser::Statement as DfStatement;
use sqlparser::ast::Statement as SpStatement;
use sqlparser_derive::{Visit, VisitMut};

use super::drop::DropDatabase;
use super::show::ShowVariables;
use crate::error::{ConvertToDfStatementSnafu, Error};
use crate::statements::alter::AlterTable;
Expand Down Expand Up @@ -51,6 +52,8 @@ pub enum Statement {
CreateTableLike(CreateTableLike),
// DROP TABLE
DropTable(DropTable),
// DROP DATABASE
DropDatabase(DropDatabase),
// CREATE DATABASE
CreateDatabase(CreateDatabase),
/// ALTER TABLE
Expand Down

0 comments on commit e56bee4

Please sign in to comment.