Skip to main content

sql/statements/
statement.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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::comment::Comment;
26use crate::statements::copy::Copy;
27use crate::statements::create::{
28    CreateDatabase, CreateExternalTable, CreateFlow, CreateTable, CreateTableLike, CreateView,
29};
30use crate::statements::cursor::{CloseCursor, DeclareCursor, FetchCursor};
31use crate::statements::delete::Delete;
32use crate::statements::describe::DescribeTable;
33#[cfg(feature = "enterprise")]
34use crate::statements::drop::UndropTable;
35use crate::statements::drop::{DropDatabase, DropFlow, DropTable, DropView};
36use crate::statements::explain::ExplainStatement;
37use crate::statements::insert::Insert;
38use crate::statements::kill::Kill;
39use crate::statements::query::Query;
40use crate::statements::set_variables::SetVariables;
41use crate::statements::show::{
42    ShowColumns, ShowCreateDatabase, ShowCreateFlow, ShowCreateTable, ShowCreateView,
43    ShowDatabases, ShowFlowStatus, ShowFlows, ShowIndex, ShowKind, ShowProcessList, ShowRegion,
44    ShowSearchPath, ShowStatus, ShowTableStatus, ShowTables, ShowVariables, ShowViews,
45};
46use crate::statements::tql::Tql;
47use crate::statements::truncate::TruncateTable;
48
49/// Tokens parsed by `DFParser` are converted into these values.
50#[allow(clippy::large_enum_variant)]
51#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
52pub enum Statement {
53    // Query
54    Query(Box<Query>),
55    // Insert
56    Insert(Box<Insert>),
57    // Delete
58    Delete(Box<Delete>),
59    /// CREATE TABLE
60    CreateTable(CreateTable),
61    // CREATE EXTERNAL TABLE
62    CreateExternalTable(CreateExternalTable),
63    // CREATE TABLE ... LIKE
64    CreateTableLike(CreateTableLike),
65    // CREATE FLOW
66    CreateFlow(CreateFlow),
67    // CREATE VIEW ... AS
68    CreateView(CreateView),
69    // CREATE TRIGGER
70    #[cfg(feature = "enterprise")]
71    CreateTrigger(crate::statements::create::trigger::CreateTrigger),
72    // DROP TABLE
73    DropTable(DropTable),
74    // UNDROP TABLE
75    #[cfg(feature = "enterprise")]
76    UndropTable(UndropTable),
77    // DROP DATABASE
78    DropDatabase(DropDatabase),
79    // DROP FLOW
80    DropFlow(DropFlow),
81    // DROP Trigger
82    #[cfg(feature = "enterprise")]
83    DropTrigger(crate::statements::drop::trigger::DropTrigger),
84    // DROP View
85    DropView(DropView),
86    // CREATE DATABASE
87    CreateDatabase(CreateDatabase),
88    /// ALTER TABLE
89    AlterTable(AlterTable),
90    /// ALTER DATABASE
91    AlterDatabase(AlterDatabase),
92    /// ALTER TRIGGER
93    #[cfg(feature = "enterprise")]
94    AlterTrigger(crate::statements::alter::trigger::AlterTrigger),
95    // Databases.
96    ShowDatabases(ShowDatabases),
97    // SHOW TABLES
98    ShowTables(ShowTables),
99    // SHOW TABLE STATUS
100    ShowTableStatus(ShowTableStatus),
101    // SHOW COLUMNS
102    ShowColumns(ShowColumns),
103    // SHOW CHARSET or SHOW CHARACTER SET
104    ShowCharset(ShowKind),
105    // SHOW COLLATION
106    ShowCollation(ShowKind),
107    // SHOW INDEX
108    ShowIndex(ShowIndex),
109    // SHOW REGION
110    ShowRegion(ShowRegion),
111    // SHOW CREATE DATABASE
112    ShowCreateDatabase(ShowCreateDatabase),
113    // SHOW CREATE TABLE
114    ShowCreateTable(ShowCreateTable),
115    // SHOW CREATE FLOW
116    ShowCreateFlow(ShowCreateFlow),
117    #[cfg(feature = "enterprise")]
118    ShowCreateTrigger(crate::statements::show::trigger::ShowCreateTrigger),
119    /// SHOW FLOWS
120    ShowFlows(ShowFlows),
121    /// SHOW FLOW STATUS
122    ShowFlowStatus(ShowFlowStatus),
123    // SHOW TRIGGERS
124    #[cfg(feature = "enterprise")]
125    ShowTriggers(crate::statements::show::trigger::ShowTriggers),
126    // SHOW CREATE VIEW
127    ShowCreateView(ShowCreateView),
128    // SHOW STATUS
129    ShowStatus(ShowStatus),
130    // SHOW SEARCH_PATH
131    ShowSearchPath(ShowSearchPath),
132    // SHOW VIEWS
133    ShowViews(ShowViews),
134    // DESCRIBE TABLE
135    DescribeTable(DescribeTable),
136    // EXPLAIN QUERY
137    Explain(Box<ExplainStatement>),
138    // COPY
139    Copy(Copy),
140    // Telemetry Query Language
141    Tql(Tql),
142    // TRUNCATE TABLE
143    TruncateTable(TruncateTable),
144    // SET VARIABLES
145    SetVariables(SetVariables),
146    // SHOW VARIABLES
147    ShowVariables(ShowVariables),
148    // COMMENT ON
149    Comment(Comment),
150    // USE
151    Use(String),
152    // Admin statement(extension)
153    Admin(Admin),
154    // DECLARE ... CURSOR FOR ...
155    DeclareCursor(DeclareCursor),
156    // FETCH ... FROM ...
157    FetchCursor(FetchCursor),
158    // CLOSE
159    CloseCursor(CloseCursor),
160    // KILL <process>
161    Kill(Kill),
162    // SHOW PROCESSLIST
163    ShowProcesslist(ShowProcessList),
164}
165
166impl Statement {
167    pub fn is_readonly(&self) -> bool {
168        match self {
169            // Read-only operations
170            Statement::Query(_)
171            | Statement::ShowDatabases(_)
172            | Statement::ShowTables(_)
173            | Statement::ShowTableStatus(_)
174            | Statement::ShowColumns(_)
175            | Statement::ShowCharset(_)
176            | Statement::ShowCollation(_)
177            | Statement::ShowIndex(_)
178            | Statement::ShowRegion(_)
179            | Statement::ShowCreateDatabase(_)
180            | Statement::ShowCreateTable(_)
181            | Statement::ShowCreateFlow(_)
182            | Statement::ShowFlows(_)
183            | Statement::ShowFlowStatus(_)
184            | Statement::ShowCreateView(_)
185            | Statement::ShowStatus(_)
186            | Statement::ShowSearchPath(_)
187            | Statement::ShowViews(_)
188            | Statement::DescribeTable(_)
189            | Statement::ShowVariables(_)
190            | Statement::ShowProcesslist(_)
191            | Statement::FetchCursor(_)
192            | Statement::Tql(_) => true,
193
194            #[cfg(feature = "enterprise")]
195            Statement::ShowCreateTrigger(_) => true,
196            #[cfg(feature = "enterprise")]
197            Statement::ShowTriggers(_) => true,
198
199            Statement::Explain(explain) => !explain.analyze || explain.statement.is_readonly(),
200
201            // Write operations
202            Statement::Insert(_)
203            | Statement::Delete(_)
204            | Statement::CreateTable(_)
205            | Statement::CreateExternalTable(_)
206            | Statement::CreateTableLike(_)
207            | Statement::CreateFlow(_)
208            | Statement::CreateView(_)
209            | Statement::DropTable(_)
210            | Statement::DropDatabase(_)
211            | Statement::DropFlow(_)
212            | Statement::DropView(_)
213            | Statement::CreateDatabase(_)
214            | Statement::AlterTable(_)
215            | Statement::AlterDatabase(_)
216            | Statement::Copy(_)
217            | Statement::TruncateTable(_)
218            | Statement::SetVariables(_)
219            | Statement::Comment(_)
220            | Statement::Use(_)
221            | Statement::DeclareCursor(_)
222            | Statement::CloseCursor(_)
223            | Statement::Kill(_)
224            | Statement::Admin(_) => false,
225
226            #[cfg(feature = "enterprise")]
227            Statement::UndropTable(_) => false,
228
229            #[cfg(feature = "enterprise")]
230            Statement::AlterTrigger(_) => false,
231
232            #[cfg(feature = "enterprise")]
233            Statement::CreateTrigger(_) | Statement::DropTrigger(_) => false,
234        }
235    }
236}
237
238impl Display for Statement {
239    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
240        match self {
241            Statement::Query(s) => s.inner.fmt(f),
242            Statement::Insert(s) => s.inner.fmt(f),
243            Statement::Delete(s) => s.inner.fmt(f),
244            Statement::CreateTable(s) => s.fmt(f),
245            Statement::CreateExternalTable(s) => s.fmt(f),
246            Statement::CreateTableLike(s) => s.fmt(f),
247            Statement::CreateFlow(s) => s.fmt(f),
248            #[cfg(feature = "enterprise")]
249            Statement::CreateTrigger(s) => s.fmt(f),
250            Statement::DropFlow(s) => s.fmt(f),
251            #[cfg(feature = "enterprise")]
252            Statement::DropTrigger(s) => s.fmt(f),
253            Statement::DropTable(s) => s.fmt(f),
254            #[cfg(feature = "enterprise")]
255            Statement::UndropTable(s) => s.fmt(f),
256            Statement::DropDatabase(s) => s.fmt(f),
257            Statement::DropView(s) => s.fmt(f),
258            Statement::CreateDatabase(s) => s.fmt(f),
259            Statement::AlterTable(s) => s.fmt(f),
260            Statement::AlterDatabase(s) => s.fmt(f),
261            #[cfg(feature = "enterprise")]
262            Statement::AlterTrigger(s) => s.fmt(f),
263            Statement::ShowDatabases(s) => s.fmt(f),
264            Statement::ShowTables(s) => s.fmt(f),
265            Statement::ShowTableStatus(s) => s.fmt(f),
266            Statement::ShowColumns(s) => s.fmt(f),
267            Statement::ShowIndex(s) => s.fmt(f),
268            Statement::ShowRegion(s) => s.fmt(f),
269            Statement::ShowCreateTable(s) => s.fmt(f),
270            Statement::ShowCreateFlow(s) => s.fmt(f),
271            #[cfg(feature = "enterprise")]
272            Statement::ShowCreateTrigger(s) => s.fmt(f),
273            Statement::ShowFlows(s) => s.fmt(f),
274            Statement::ShowFlowStatus(s) => s.fmt(f),
275            #[cfg(feature = "enterprise")]
276            Statement::ShowTriggers(s) => s.fmt(f),
277            Statement::ShowCreateDatabase(s) => s.fmt(f),
278            Statement::ShowCreateView(s) => s.fmt(f),
279            Statement::ShowViews(s) => s.fmt(f),
280            Statement::ShowStatus(s) => s.fmt(f),
281            Statement::ShowSearchPath(s) => s.fmt(f),
282            Statement::DescribeTable(s) => s.fmt(f),
283            Statement::Explain(s) => s.fmt(f),
284            Statement::Copy(s) => s.fmt(f),
285            Statement::Tql(s) => s.fmt(f),
286            Statement::TruncateTable(s) => s.fmt(f),
287            Statement::SetVariables(s) => s.fmt(f),
288            Statement::ShowVariables(s) => s.fmt(f),
289            Statement::Comment(s) => s.fmt(f),
290            Statement::ShowCharset(kind) => {
291                write!(f, "SHOW CHARSET {kind}")
292            }
293            Statement::ShowCollation(kind) => {
294                write!(f, "SHOW COLLATION {kind}")
295            }
296            Statement::CreateView(s) => s.fmt(f),
297            Statement::Use(s) => s.fmt(f),
298            Statement::Admin(admin) => admin.fmt(f),
299            Statement::DeclareCursor(s) => s.fmt(f),
300            Statement::FetchCursor(s) => s.fmt(f),
301            Statement::CloseCursor(s) => s.fmt(f),
302            Statement::Kill(k) => k.fmt(f),
303            Statement::ShowProcesslist(s) => s.fmt(f),
304        }
305    }
306}
307
308/// Comment hints from SQL.
309/// It'll be enabled when using `--comment` in mysql client.
310/// Eg: `SELECT * FROM system.number LIMIT 1; -- { ErrorCode 25 }`
311#[derive(Debug, Clone, PartialEq, Eq)]
312pub struct Hint {
313    pub error_code: Option<u16>,
314    pub comment: String,
315    pub prefix: String,
316}
317
318impl TryFrom<&Statement> for DfStatement {
319    type Error = Error;
320
321    fn try_from(s: &Statement) -> Result<Self, Self::Error> {
322        let s = match s {
323            Statement::Query(query) => SpStatement::Query(Box::new(query.inner.clone())),
324            Statement::Insert(insert) => insert.inner.clone(),
325            Statement::Delete(delete) => delete.inner.clone(),
326            _ => {
327                return ConvertToDfStatementSnafu {
328                    statement: format!("{s:?}"),
329                }
330                .fail();
331            }
332        };
333        Ok(DfStatement::Statement(Box::new(s)))
334    }
335}