1use std::fmt::Display;
16
17use datafusion_sql::parser::Statement as DfStatement;
18use serde::Serialize;
19use sqlparser::ast::Statement as SpStatement;
20use sqlparser_derive::{Visit, VisitMut};
21
22use crate::error::{ConvertToDfStatementSnafu, Error};
23use crate::statements::admin::Admin;
24use crate::statements::alter::{AlterDatabase, AlterTable};
25use crate::statements::copy::Copy;
26use crate::statements::create::{
27 CreateDatabase, CreateExternalTable, CreateFlow, CreateTable, CreateTableLike, CreateView,
28};
29use crate::statements::cursor::{CloseCursor, DeclareCursor, FetchCursor};
30use crate::statements::delete::Delete;
31use crate::statements::describe::DescribeTable;
32use crate::statements::drop::{DropDatabase, DropFlow, DropTable, DropView};
33use crate::statements::explain::Explain;
34use crate::statements::insert::Insert;
35use crate::statements::kill::Kill;
36use crate::statements::query::Query;
37use crate::statements::set_variables::SetVariables;
38use crate::statements::show::{
39 ShowColumns, ShowCreateDatabase, ShowCreateFlow, ShowCreateTable, ShowCreateView,
40 ShowDatabases, ShowFlows, ShowIndex, ShowKind, ShowProcessList, ShowRegion, ShowSearchPath,
41 ShowStatus, ShowTableStatus, ShowTables, ShowVariables, ShowViews,
42};
43use crate::statements::tql::Tql;
44use crate::statements::truncate::TruncateTable;
45
46#[allow(clippy::large_enum_variant)]
48#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
49pub enum Statement {
50 Query(Box<Query>),
52 Insert(Box<Insert>),
54 Delete(Box<Delete>),
56 CreateTable(CreateTable),
58 CreateExternalTable(CreateExternalTable),
60 CreateTableLike(CreateTableLike),
62 CreateFlow(CreateFlow),
64 CreateView(CreateView),
66 #[cfg(feature = "enterprise")]
68 CreateTrigger(crate::statements::create::trigger::CreateTrigger),
69 DropTable(DropTable),
71 DropDatabase(DropDatabase),
73 DropFlow(DropFlow),
75 #[cfg(feature = "enterprise")]
77 DropTrigger(crate::statements::drop::trigger::DropTrigger),
78 DropView(DropView),
80 CreateDatabase(CreateDatabase),
82 AlterTable(AlterTable),
84 AlterDatabase(AlterDatabase),
86 #[cfg(feature = "enterprise")]
88 AlterTrigger(crate::statements::alter::trigger::AlterTrigger),
89 ShowDatabases(ShowDatabases),
91 ShowTables(ShowTables),
93 ShowTableStatus(ShowTableStatus),
95 ShowColumns(ShowColumns),
97 ShowCharset(ShowKind),
99 ShowCollation(ShowKind),
101 ShowIndex(ShowIndex),
103 ShowRegion(ShowRegion),
105 ShowCreateDatabase(ShowCreateDatabase),
107 ShowCreateTable(ShowCreateTable),
109 ShowCreateFlow(ShowCreateFlow),
111 ShowFlows(ShowFlows),
113 #[cfg(feature = "enterprise")]
115 ShowTriggers(crate::statements::show::trigger::ShowTriggers),
116 ShowCreateView(ShowCreateView),
118 ShowStatus(ShowStatus),
120 ShowSearchPath(ShowSearchPath),
122 ShowViews(ShowViews),
124 DescribeTable(DescribeTable),
126 Explain(Box<Explain>),
128 Copy(Copy),
130 Tql(Tql),
132 TruncateTable(TruncateTable),
134 SetVariables(SetVariables),
136 ShowVariables(ShowVariables),
138 Use(String),
140 Admin(Admin),
142 DeclareCursor(DeclareCursor),
144 FetchCursor(FetchCursor),
146 CloseCursor(CloseCursor),
148 Kill(Kill),
150 ShowProcesslist(ShowProcessList),
152}
153
154impl Statement {
155 pub fn is_readonly(&self) -> bool {
156 match self {
157 Statement::Query(_)
159 | Statement::ShowDatabases(_)
160 | Statement::ShowTables(_)
161 | Statement::ShowTableStatus(_)
162 | Statement::ShowColumns(_)
163 | Statement::ShowCharset(_)
164 | Statement::ShowCollation(_)
165 | Statement::ShowIndex(_)
166 | Statement::ShowRegion(_)
167 | Statement::ShowCreateDatabase(_)
168 | Statement::ShowCreateTable(_)
169 | Statement::ShowCreateFlow(_)
170 | Statement::ShowFlows(_)
171 | Statement::ShowCreateView(_)
172 | Statement::ShowStatus(_)
173 | Statement::ShowSearchPath(_)
174 | Statement::ShowViews(_)
175 | Statement::DescribeTable(_)
176 | Statement::Explain(_)
177 | Statement::ShowVariables(_)
178 | Statement::ShowProcesslist(_)
179 | Statement::FetchCursor(_)
180 | Statement::Tql(_) => true,
181
182 #[cfg(feature = "enterprise")]
183 Statement::ShowTriggers(_) => true,
184
185 Statement::Insert(_)
187 | Statement::Delete(_)
188 | Statement::CreateTable(_)
189 | Statement::CreateExternalTable(_)
190 | Statement::CreateTableLike(_)
191 | Statement::CreateFlow(_)
192 | Statement::CreateView(_)
193 | Statement::DropTable(_)
194 | Statement::DropDatabase(_)
195 | Statement::DropFlow(_)
196 | Statement::DropView(_)
197 | Statement::CreateDatabase(_)
198 | Statement::AlterTable(_)
199 | Statement::AlterDatabase(_)
200 | Statement::Copy(_)
201 | Statement::TruncateTable(_)
202 | Statement::SetVariables(_)
203 | Statement::Use(_)
204 | Statement::DeclareCursor(_)
205 | Statement::CloseCursor(_)
206 | Statement::Kill(_)
207 | Statement::Admin(_) => false,
208
209 #[cfg(feature = "enterprise")]
210 Statement::AlterTrigger(_) => false,
211
212 #[cfg(feature = "enterprise")]
213 Statement::CreateTrigger(_) | Statement::DropTrigger(_) => false,
214 }
215 }
216}
217
218impl Display for Statement {
219 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
220 match self {
221 Statement::Query(s) => s.inner.fmt(f),
222 Statement::Insert(s) => s.inner.fmt(f),
223 Statement::Delete(s) => s.inner.fmt(f),
224 Statement::CreateTable(s) => s.fmt(f),
225 Statement::CreateExternalTable(s) => s.fmt(f),
226 Statement::CreateTableLike(s) => s.fmt(f),
227 Statement::CreateFlow(s) => s.fmt(f),
228 #[cfg(feature = "enterprise")]
229 Statement::CreateTrigger(s) => s.fmt(f),
230 Statement::DropFlow(s) => s.fmt(f),
231 #[cfg(feature = "enterprise")]
232 Statement::DropTrigger(s) => s.fmt(f),
233 Statement::DropTable(s) => s.fmt(f),
234 Statement::DropDatabase(s) => s.fmt(f),
235 Statement::DropView(s) => s.fmt(f),
236 Statement::CreateDatabase(s) => s.fmt(f),
237 Statement::AlterTable(s) => s.fmt(f),
238 Statement::AlterDatabase(s) => s.fmt(f),
239 #[cfg(feature = "enterprise")]
240 Statement::AlterTrigger(s) => s.fmt(f),
241 Statement::ShowDatabases(s) => s.fmt(f),
242 Statement::ShowTables(s) => s.fmt(f),
243 Statement::ShowTableStatus(s) => s.fmt(f),
244 Statement::ShowColumns(s) => s.fmt(f),
245 Statement::ShowIndex(s) => s.fmt(f),
246 Statement::ShowRegion(s) => s.fmt(f),
247 Statement::ShowCreateTable(s) => s.fmt(f),
248 Statement::ShowCreateFlow(s) => s.fmt(f),
249 Statement::ShowFlows(s) => s.fmt(f),
250 #[cfg(feature = "enterprise")]
251 Statement::ShowTriggers(s) => s.fmt(f),
252 Statement::ShowCreateDatabase(s) => s.fmt(f),
253 Statement::ShowCreateView(s) => s.fmt(f),
254 Statement::ShowViews(s) => s.fmt(f),
255 Statement::ShowStatus(s) => s.fmt(f),
256 Statement::ShowSearchPath(s) => s.fmt(f),
257 Statement::DescribeTable(s) => s.fmt(f),
258 Statement::Explain(s) => s.fmt(f),
259 Statement::Copy(s) => s.fmt(f),
260 Statement::Tql(s) => s.fmt(f),
261 Statement::TruncateTable(s) => s.fmt(f),
262 Statement::SetVariables(s) => s.fmt(f),
263 Statement::ShowVariables(s) => s.fmt(f),
264 Statement::ShowCharset(kind) => {
265 write!(f, "SHOW CHARSET {kind}")
266 }
267 Statement::ShowCollation(kind) => {
268 write!(f, "SHOW COLLATION {kind}")
269 }
270 Statement::CreateView(s) => s.fmt(f),
271 Statement::Use(s) => s.fmt(f),
272 Statement::Admin(admin) => admin.fmt(f),
273 Statement::DeclareCursor(s) => s.fmt(f),
274 Statement::FetchCursor(s) => s.fmt(f),
275 Statement::CloseCursor(s) => s.fmt(f),
276 Statement::Kill(k) => k.fmt(f),
277 Statement::ShowProcesslist(s) => s.fmt(f),
278 }
279 }
280}
281
282#[derive(Debug, Clone, PartialEq, Eq)]
286pub struct Hint {
287 pub error_code: Option<u16>,
288 pub comment: String,
289 pub prefix: String,
290}
291
292impl TryFrom<&Statement> for DfStatement {
293 type Error = Error;
294
295 fn try_from(s: &Statement) -> Result<Self, Self::Error> {
296 let s = match s {
297 Statement::Query(query) => SpStatement::Query(Box::new(query.inner.clone())),
298 Statement::Explain(explain) => explain.inner.clone(),
299 Statement::Insert(insert) => insert.inner.clone(),
300 Statement::Delete(delete) => delete.inner.clone(),
301 _ => {
302 return ConvertToDfStatementSnafu {
303 statement: format!("{s:?}"),
304 }
305 .fail();
306 }
307 };
308 Ok(DfStatement::Statement(Box::new(s.into())))
309 }
310}