mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-05-19 06:20:38 +00:00
feat: implement truncate table parser (#1932)
* feat: truncate parser * chore: keyword TABLE as optional
This commit is contained in:
@@ -645,6 +645,9 @@ pub fn check_permission(
|
||||
Statement::Copy(sql::statements::copy::Copy::CopyDatabase(stmt)) => {
|
||||
validate_param(&stmt.database_name, query_ctx)?
|
||||
}
|
||||
Statement::TruncateTable(stmt) => {
|
||||
validate_param(stmt.table_name(), query_ctx)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ impl StatementExecutor {
|
||||
| Statement::CreateExternalTable(_)
|
||||
| Statement::Alter(_)
|
||||
| Statement::DropTable(_)
|
||||
| Statement::TruncateTable(_)
|
||||
| Statement::ShowCreateTable(_) => self
|
||||
.sql_stmt_executor
|
||||
.execute_sql(stmt, query_ctx)
|
||||
|
||||
@@ -127,6 +127,8 @@ impl<'a> ParserContext<'a> {
|
||||
|
||||
Keyword::COPY => self.parse_copy(),
|
||||
|
||||
Keyword::TRUNCATE => self.parse_truncate(),
|
||||
|
||||
Keyword::NoKeyword
|
||||
if w.value.to_uppercase() == tql_parser::TQL && w.quote_style.is_none() =>
|
||||
{
|
||||
|
||||
@@ -19,3 +19,4 @@ pub(crate) mod delete_parser;
|
||||
pub(crate) mod insert_parser;
|
||||
pub(crate) mod query_parser;
|
||||
pub(crate) mod tql_parser;
|
||||
pub(crate) mod truncate_parser;
|
||||
|
||||
139
src/sql/src/parsers/truncate_parser.rs
Normal file
139
src/sql/src/parsers/truncate_parser.rs
Normal file
@@ -0,0 +1,139 @@
|
||||
// Copyright 2023 Greptime Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use snafu::{ensure, ResultExt};
|
||||
use sqlparser::keywords::Keyword;
|
||||
|
||||
use crate::error::{self, InvalidTableNameSnafu, Result};
|
||||
use crate::parser::ParserContext;
|
||||
use crate::statements::statement::Statement;
|
||||
use crate::statements::truncate::TruncateTable;
|
||||
|
||||
/// TRUNCATE [TABLE] table_name;
|
||||
impl<'a> ParserContext<'a> {
|
||||
pub(crate) fn parse_truncate(&mut self) -> Result<Statement> {
|
||||
let _ = self.parser.next_token();
|
||||
let _ = self.parser.parse_keyword(Keyword::TABLE);
|
||||
|
||||
let table_ident =
|
||||
self.parser
|
||||
.parse_object_name()
|
||||
.with_context(|_| error::UnexpectedSnafu {
|
||||
sql: self.sql,
|
||||
expected: "a table name",
|
||||
actual: self.peek_token_as_string(),
|
||||
})?;
|
||||
|
||||
ensure!(
|
||||
!table_ident.0.is_empty(),
|
||||
InvalidTableNameSnafu {
|
||||
name: table_ident.to_string()
|
||||
}
|
||||
);
|
||||
|
||||
Ok(Statement::TruncateTable(TruncateTable::new(table_ident)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use sqlparser::ast::{Ident, ObjectName};
|
||||
|
||||
use super::*;
|
||||
use crate::dialect::GreptimeDbDialect;
|
||||
|
||||
#[test]
|
||||
pub fn test_parse_truncate() {
|
||||
let sql = "TRUNCATE foo";
|
||||
let mut stmts = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}).unwrap();
|
||||
assert_eq!(
|
||||
stmts.pop().unwrap(),
|
||||
Statement::TruncateTable(TruncateTable::new(ObjectName(vec![Ident::new("foo")])))
|
||||
);
|
||||
|
||||
let sql = "TRUNCATE TABLE foo";
|
||||
let mut stmts = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}).unwrap();
|
||||
assert_eq!(
|
||||
stmts.pop().unwrap(),
|
||||
Statement::TruncateTable(TruncateTable::new(ObjectName(vec![Ident::new("foo")])))
|
||||
);
|
||||
|
||||
let sql = "TRUNCATE TABLE my_schema.foo";
|
||||
let mut stmts = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}).unwrap();
|
||||
assert_eq!(
|
||||
stmts.pop().unwrap(),
|
||||
Statement::TruncateTable(TruncateTable::new(ObjectName(vec![
|
||||
Ident::new("my_schema"),
|
||||
Ident::new("foo")
|
||||
])))
|
||||
);
|
||||
|
||||
let sql = "TRUNCATE my_schema.foo";
|
||||
let mut stmts = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}).unwrap();
|
||||
assert_eq!(
|
||||
stmts.pop().unwrap(),
|
||||
Statement::TruncateTable(TruncateTable::new(ObjectName(vec![
|
||||
Ident::new("my_schema"),
|
||||
Ident::new("foo")
|
||||
])))
|
||||
);
|
||||
|
||||
let sql = "TRUNCATE TABLE my_catalog.my_schema.foo";
|
||||
let mut stmts = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}).unwrap();
|
||||
assert_eq!(
|
||||
stmts.pop().unwrap(),
|
||||
Statement::TruncateTable(TruncateTable::new(ObjectName(vec![
|
||||
Ident::new("my_catalog"),
|
||||
Ident::new("my_schema"),
|
||||
Ident::new("foo")
|
||||
])))
|
||||
);
|
||||
|
||||
let sql = "TRUNCATE drop";
|
||||
let mut stmts = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}).unwrap();
|
||||
assert_eq!(
|
||||
stmts.pop().unwrap(),
|
||||
Statement::TruncateTable(TruncateTable::new(ObjectName(vec![Ident::new("drop")])))
|
||||
);
|
||||
|
||||
let sql = "TRUNCATE `drop`";
|
||||
let mut stmts = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}).unwrap();
|
||||
assert_eq!(
|
||||
stmts.pop().unwrap(),
|
||||
Statement::TruncateTable(TruncateTable::new(ObjectName(vec![Ident::with_quote(
|
||||
'`', "drop"
|
||||
),])))
|
||||
);
|
||||
|
||||
let sql = "TRUNCATE \"drop\"";
|
||||
let mut stmts = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}).unwrap();
|
||||
assert_eq!(
|
||||
stmts.pop().unwrap(),
|
||||
Statement::TruncateTable(TruncateTable::new(ObjectName(vec![Ident::with_quote(
|
||||
'"', "drop"
|
||||
),])))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_parse_invalid_truncate() {
|
||||
let sql = "TRUNCATE SCHEMA foo";
|
||||
let result = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {});
|
||||
assert!(result.is_err(), "result is: {result:?}");
|
||||
|
||||
let sql = "TRUNCATE";
|
||||
let result = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {});
|
||||
assert!(result.is_err(), "result is: {result:?}");
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ pub mod query;
|
||||
pub mod show;
|
||||
pub mod statement;
|
||||
pub mod tql;
|
||||
pub mod truncate;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ use crate::statements::insert::Insert;
|
||||
use crate::statements::query::Query;
|
||||
use crate::statements::show::{ShowCreateTable, ShowDatabases, ShowTables};
|
||||
use crate::statements::tql::Tql;
|
||||
use crate::statements::truncate::TruncateTable;
|
||||
|
||||
/// Tokens parsed by `DFParser` are converted into these values.
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
@@ -61,6 +62,8 @@ pub enum Statement {
|
||||
// COPY
|
||||
Copy(crate::statements::copy::Copy),
|
||||
Tql(Tql),
|
||||
// TRUNCATE TABLE
|
||||
TruncateTable(TruncateTable),
|
||||
}
|
||||
|
||||
/// Comment hints from SQL.
|
||||
|
||||
32
src/sql/src/statements/truncate.rs
Normal file
32
src/sql/src/statements/truncate.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2023 Greptime Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use sqlparser::ast::ObjectName;
|
||||
|
||||
/// TRUNCATE TABLE statement.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TruncateTable {
|
||||
table_name: ObjectName,
|
||||
}
|
||||
|
||||
impl TruncateTable {
|
||||
/// Creates a statement for `TRUNCATE TABLE`
|
||||
pub fn new(table_name: ObjectName) -> Self {
|
||||
Self { table_name }
|
||||
}
|
||||
|
||||
pub fn table_name(&self) -> &ObjectName {
|
||||
&self.table_name
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user