sql/statements/
truncate.rs1use std::fmt::Display;
16
17use itertools::Itertools;
18use serde::Serialize;
19use sqlparser::ast::{ObjectName, Visit, VisitMut, Visitor, VisitorMut};
20
21#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
23pub struct TruncateTable {
24 table_name: ObjectName,
25 time_ranges: Vec<(sqlparser::ast::Value, sqlparser::ast::Value)>,
26}
27
28impl Visit for TruncateTable {
29 fn visit<V: Visitor>(&self, visitor: &mut V) -> ::std::ops::ControlFlow<V::Break> {
30 self.table_name.visit(visitor)?;
31 for (start, end) in &self.time_ranges {
32 start.visit(visitor)?;
33 end.visit(visitor)?;
34 }
35 ::std::ops::ControlFlow::Continue(())
36 }
37}
38
39impl VisitMut for TruncateTable {
40 fn visit<V: VisitorMut>(&mut self, visitor: &mut V) -> ::std::ops::ControlFlow<V::Break> {
41 sqlparser::ast::VisitMut::visit(&mut self.table_name, visitor)?;
42 for (start, end) in &mut self.time_ranges {
43 start.visit(visitor)?;
44 end.visit(visitor)?;
45 }
46 ::std::ops::ControlFlow::Continue(())
47 }
48}
49
50impl TruncateTable {
51 pub fn new(table_name: ObjectName) -> Self {
53 Self {
54 table_name,
55 time_ranges: Vec::new(),
56 }
57 }
58
59 pub fn new_with_ranges(
61 table_name: ObjectName,
62 time_ranges: Vec<(sqlparser::ast::Value, sqlparser::ast::Value)>,
63 ) -> Self {
64 Self {
65 table_name,
66 time_ranges,
67 }
68 }
69
70 pub fn table_name(&self) -> &ObjectName {
71 &self.table_name
72 }
73
74 pub fn time_ranges(&self) -> &[(sqlparser::ast::Value, sqlparser::ast::Value)] {
75 &self.time_ranges
76 }
77}
78
79impl Display for TruncateTable {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 let table_name = self.table_name();
82 write!(f, r#"TRUNCATE TABLE {table_name}"#)?;
83 if self.time_ranges.is_empty() {
84 return Ok(());
85 }
86
87 write!(f, " FILE RANGE ")?;
88 write!(
89 f,
90 "{}",
91 self.time_ranges
92 .iter()
93 .map(|(start, end)| format!("({}, {})", start, end))
94 .join(", ")
95 )
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use std::assert_matches::assert_matches;
102
103 use crate::dialect::GreptimeDbDialect;
104 use crate::parser::{ParseOptions, ParserContext};
105 use crate::statements::statement::Statement;
106
107 #[test]
108 fn test_display_for_tuncate_table() {
109 let sql = r"truncate table t1;";
110 let stmts: Vec<Statement> =
111 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
112 .unwrap();
113 assert_eq!(1, stmts.len());
114 assert_matches!(&stmts[0], Statement::TruncateTable { .. });
115 match &stmts[0] {
116 Statement::TruncateTable(trunc) => {
117 let new_sql = format!("\n{}", trunc);
118 assert_eq!(
119 r#"
120TRUNCATE TABLE t1"#,
121 &new_sql
122 );
123 }
124 _ => {
125 unreachable!();
126 }
127 }
128
129 let sql = r"truncate table t1 file range (1,2);";
130 let stmts: Vec<Statement> =
131 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
132 .unwrap();
133 assert_eq!(1, stmts.len());
134 assert_matches!(&stmts[0], Statement::TruncateTable { .. });
135 match &stmts[0] {
136 Statement::TruncateTable(trunc) => {
137 let new_sql = format!("\n{}", trunc);
138 assert_eq!(
139 r#"
140TRUNCATE TABLE t1 FILE RANGE (1, 2)"#,
141 &new_sql
142 );
143 }
144 _ => {
145 unreachable!();
146 }
147 }
148
149 let sql = r"truncate table t1 file range (1,2), (3,4);";
150 let stmts: Vec<Statement> =
151 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
152 .unwrap();
153 assert_eq!(1, stmts.len());
154 assert_matches!(&stmts[0], Statement::TruncateTable { .. });
155 match &stmts[0] {
156 Statement::TruncateTable(trunc) => {
157 let new_sql = format!("\n{}", trunc);
158 assert_eq!(
159 r#"
160TRUNCATE TABLE t1 FILE RANGE (1, 2), (3, 4)"#,
161 &new_sql
162 );
163 }
164 _ => {
165 unreachable!();
166 }
167 }
168 }
169}