sql/parsers/
explain_parser.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 snafu::ResultExt;
16use sqlparser::keywords::Keyword;
17
18use crate::error::{self, Result};
19use crate::parser::ParserContext;
20use crate::statements::explain::ExplainStatement;
21use crate::statements::statement::Statement;
22
23/// EXPLAIN statement parser implementation
24impl ParserContext<'_> {
25    /// explain that support use our own parser to parse the inner statement
26    pub(crate) fn parse_explain(&mut self) -> Result<Statement> {
27        let analyze = self.parser.parse_keyword(Keyword::ANALYZE);
28        let verbose = self.parser.parse_keyword(Keyword::VERBOSE);
29        let format =
30            if self.parser.parse_keyword(Keyword::FORMAT) {
31                Some(self.parser.parse_analyze_format().with_context(|_| {
32                    error::UnexpectedSnafu {
33                        expected: "analyze format",
34                        actual: self.peek_token_as_string(),
35                    }
36                })?)
37            } else {
38                None
39            };
40
41        let statement = self.parse_statement()?;
42
43        let explain = ExplainStatement {
44            analyze,
45            verbose,
46            format,
47            statement: Box::new(statement),
48        };
49        Ok(Statement::Explain(Box::new(explain)))
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use sqlparser::ast::helpers::attached_token::AttachedToken;
56    use sqlparser::ast::{GroupByExpr, Query as SpQuery, SelectFlavor, WildcardAdditionalOptions};
57
58    use super::*;
59    use crate::dialect::GreptimeDbDialect;
60    use crate::parser::ParseOptions;
61
62    #[test]
63    pub fn test_explain() {
64        let sql = "EXPLAIN select * from foo";
65        let result =
66            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
67        let stmts = result.unwrap();
68        assert_eq!(1, stmts.len());
69
70        let select = sqlparser::ast::Select {
71            distinct: None,
72            top: None,
73            projection: vec![sqlparser::ast::SelectItem::Wildcard(
74                WildcardAdditionalOptions::default(),
75            )],
76            exclude: None,
77            into: None,
78            from: vec![sqlparser::ast::TableWithJoins {
79                relation: sqlparser::ast::TableFactor::Table {
80                    name: sqlparser::ast::ObjectName::from(vec![sqlparser::ast::Ident::new("foo")]),
81                    alias: None,
82                    args: None,
83                    with_hints: vec![],
84                    partitions: vec![],
85                    version: None,
86                    with_ordinality: false,
87                    json_path: None,
88                    sample: None,
89                    index_hints: vec![],
90                },
91                joins: vec![],
92            }],
93            lateral_views: vec![],
94            selection: None,
95            group_by: GroupByExpr::Expressions(vec![], vec![]),
96            cluster_by: vec![],
97            distribute_by: vec![],
98            sort_by: vec![],
99            having: None,
100            qualify: None,
101            named_window: vec![],
102            value_table_mode: None,
103            top_before_distinct: false,
104            prewhere: None,
105            window_before_qualify: false,
106            connect_by: None,
107            select_token: AttachedToken::empty(),
108            flavor: SelectFlavor::Standard,
109        };
110
111        let sp_query = Box::new(
112            SpQuery {
113                with: None,
114                body: Box::new(sqlparser::ast::SetExpr::Select(Box::new(select))),
115                order_by: None,
116                limit_clause: None,
117                pipe_operators: vec![],
118                fetch: None,
119                locks: vec![],
120                for_clause: None,
121                settings: None,
122                format_clause: None,
123            }
124            .try_into()
125            .unwrap(),
126        );
127
128        let explain = ExplainStatement {
129            analyze: false,
130            verbose: false,
131            format: None,
132            statement: Box::new(Statement::Query(sp_query)),
133        };
134
135        assert_eq!(stmts[0], Statement::Explain(Box::new(explain)))
136    }
137}