use crate::ddl_ast::parse::clause::{ClauseCursor, tokenize};
use crate::ddl_ast::statement::{DatabaseStmt, NodedbStatement};
use crate::error::SqlError;
use super::alter::parse_alter_database;
use super::backup_restore::{parse_backup_database, parse_restore_database};
use super::clone::parse_clone_database;
use super::create::parse_create_database;
use super::drop_db::parse_drop_database;
use super::mirror::{parse_mirror_database, parse_show_database_mirror_status};
use super::move_tenant::parse_move_tenant;
use super::show_extras::{parse_show_database_lineage, parse_show_database_quota_or_usage};
use super::use_db::parse_use_database;
pub fn try_parse(
_upper: &str,
_parts: &[&str],
original: &str,
) -> Option<Result<NodedbStatement, SqlError>> {
let toks = tokenize(original);
let mut c = ClauseCursor::new(original, &toks, "DATABASE");
let result = if c.eat_keywords(&["CREATE", "DATABASE"]) {
parse_create_database(&mut c)
} else if c.eat_keywords(&["DROP", "DATABASE"]) {
parse_drop_database(&mut c)
} else if c.eat_keywords(&["ALTER", "DATABASE"]) {
parse_alter_database(&mut c)
} else if c.eat_keywords(&["USE", "DATABASE"]) {
parse_use_database(&mut c)
} else if c.eat_keywords(&["CLONE", "DATABASE"]) {
parse_clone_database(&mut c)
} else if c.eat_keywords(&["MIRROR", "DATABASE"]) {
parse_mirror_database(&mut c)
} else if c.eat_keywords(&["MOVE", "TENANT"]) {
parse_move_tenant(&mut c)
} else if c.eat_keywords(&["BACKUP", "DATABASE"]) {
parse_backup_database(&mut c)
} else if c.eat_keywords(&["RESTORE", "DATABASE"]) {
parse_restore_database(&mut c)
} else if c.peek_keywords(&["SHOW", "DATABASES"]) {
c.eat_keywords(&["SHOW", "DATABASES"]);
if !c.at_end() {
return None;
}
Ok(NodedbStatement::Database(DatabaseStmt::ShowDatabases))
} else if c.eat_keywords(&["SHOW", "DATABASE", "QUOTA"]) {
parse_show_database_quota_or_usage(&mut c, false)
} else if c.eat_keywords(&["SHOW", "DATABASE", "USAGE"]) {
parse_show_database_quota_or_usage(&mut c, true)
} else if c.eat_keywords(&["SHOW", "DATABASE", "LINEAGE"]) {
parse_show_database_lineage(&mut c)
} else if c.eat_keywords(&["SHOW", "DATABASE", "MIRROR", "STATUS"]) {
parse_show_database_mirror_status(&mut c)
} else {
return None;
};
Some(result)
}
pub(super) fn db_name(c: &mut ClauseCursor<'_, '_>, what: &str) -> Result<String, SqlError> {
let raw = c.raw(what)?;
Ok(raw
.strip_prefix('"')
.and_then(|r| r.strip_suffix('"'))
.map_or_else(|| raw.to_string(), |inner| inner.replace("\"\"", "\"")))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_show_databases() {
let sql = "SHOW DATABASES";
let upper = sql.to_uppercase();
let parts: Vec<&str> = sql.split_whitespace().collect();
let stmt = try_parse(&upper, &parts, sql).unwrap().unwrap();
assert_eq!(stmt, NodedbStatement::Database(DatabaseStmt::ShowDatabases));
}
}