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::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/// Tokens parsed by `DFParser` are converted into these values.
47#[allow(clippy::large_enum_variant)]
48#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
49pub enum Statement {
50    // Query
51    Query(Box<Query>),
52    // Insert
53    Insert(Box<Insert>),
54    // Delete
55    Delete(Box<Delete>),
56    /// CREATE TABLE
57    CreateTable(CreateTable),
58    // CREATE EXTERNAL TABLE
59    CreateExternalTable(CreateExternalTable),
60    // CREATE TABLE ... LIKE
61    CreateTableLike(CreateTableLike),
62    // CREATE FLOW
63    CreateFlow(CreateFlow),
64    // CREATE VIEW ... AS
65    CreateView(CreateView),
66    // CREATE TRIGGER
67    #[cfg(feature = "enterprise")]
68    CreateTrigger(crate::statements::create::trigger::CreateTrigger),
69    // DROP TABLE
70    DropTable(DropTable),
71    // DROP DATABASE
72    DropDatabase(DropDatabase),
73    // DROP FLOW
74    DropFlow(DropFlow),
75    // DROP Trigger
76    #[cfg(feature = "enterprise")]
77    DropTrigger(crate::statements::drop::trigger::DropTrigger),
78    // DROP View
79    DropView(DropView),
80    // CREATE DATABASE
81    CreateDatabase(CreateDatabase),
82    /// ALTER TABLE
83    AlterTable(AlterTable),
84    /// ALTER DATABASE
85    AlterDatabase(AlterDatabase),
86    /// ALTER TRIGGER
87    #[cfg(feature = "enterprise")]
88    AlterTrigger(crate::statements::alter::trigger::AlterTrigger),
89    // Databases.
90    ShowDatabases(ShowDatabases),
91    // SHOW TABLES
92    ShowTables(ShowTables),
93    // SHOW TABLE STATUS
94    ShowTableStatus(ShowTableStatus),
95    // SHOW COLUMNS
96    ShowColumns(ShowColumns),
97    // SHOW CHARSET or SHOW CHARACTER SET
98    ShowCharset(ShowKind),
99    // SHOW COLLATION
100    ShowCollation(ShowKind),
101    // SHOW INDEX
102    ShowIndex(ShowIndex),
103    // SHOW REGION
104    ShowRegion(ShowRegion),
105    // SHOW CREATE DATABASE
106    ShowCreateDatabase(ShowCreateDatabase),
107    // SHOW CREATE TABLE
108    ShowCreateTable(ShowCreateTable),
109    // SHOW CREATE FLOW
110    ShowCreateFlow(ShowCreateFlow),
111    /// SHOW FLOWS
112    ShowFlows(ShowFlows),
113    // SHOW TRIGGERS
114    #[cfg(feature = "enterprise")]
115    ShowTriggers(crate::statements::show::trigger::ShowTriggers),
116    // SHOW CREATE VIEW
117    ShowCreateView(ShowCreateView),
118    // SHOW STATUS
119    ShowStatus(ShowStatus),
120    // SHOW SEARCH_PATH
121    ShowSearchPath(ShowSearchPath),
122    // SHOW VIEWS
123    ShowViews(ShowViews),
124    // DESCRIBE TABLE
125    DescribeTable(DescribeTable),
126    // EXPLAIN QUERY
127    Explain(Box<Explain>),
128    // COPY
129    Copy(Copy),
130    // Telemetry Query Language
131    Tql(Tql),
132    // TRUNCATE TABLE
133    TruncateTable(TruncateTable),
134    // SET VARIABLES
135    SetVariables(SetVariables),
136    // SHOW VARIABLES
137    ShowVariables(ShowVariables),
138    // USE
139    Use(String),
140    // Admin statement(extension)
141    Admin(Admin),
142    // DECLARE ... CURSOR FOR ...
143    DeclareCursor(DeclareCursor),
144    // FETCH ... FROM ...
145    FetchCursor(FetchCursor),
146    // CLOSE
147    CloseCursor(CloseCursor),
148    // KILL <process>
149    Kill(Kill),
150    // SHOW PROCESSLIST
151    ShowProcesslist(ShowProcessList),
152}
153
154impl Statement {
155    pub fn is_readonly(&self) -> bool {
156        match self {
157            // Read-only operations
158            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            // Write operations
186            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/// Comment hints from SQL.
283/// It'll be enabled when using `--comment` in mysql client.
284/// Eg: `SELECT * FROM system.number LIMIT 1; -- { ErrorCode 25 }`
285#[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}