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