mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-25 08:24:05 +00:00
feat: Support DESCRIBE table_name (#340)
* feat: Support DESCRIBE * feat: Support DESCRIBE table_name * Update src/ast/mod.rs Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org> * Update src/ast/mod.rs Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org> * Update src/ast/mod.rs Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org> Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
d8adb1708c
commit
d2d4fc0c58
3 changed files with 67 additions and 10 deletions
|
@ -764,8 +764,18 @@ pub enum Statement {
|
||||||
data_types: Vec<DataType>,
|
data_types: Vec<DataType>,
|
||||||
statement: Box<Statement>,
|
statement: Box<Statement>,
|
||||||
},
|
},
|
||||||
/// EXPLAIN
|
/// EXPLAIN TABLE
|
||||||
|
/// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
|
||||||
|
ExplainTable {
|
||||||
|
// If true, query used the MySQL `DESCRIBE` alias for explain
|
||||||
|
describe_alias: bool,
|
||||||
|
// Table name
|
||||||
|
table_name: ObjectName,
|
||||||
|
},
|
||||||
|
/// EXPLAIN / DESCRIBE for select_statement
|
||||||
Explain {
|
Explain {
|
||||||
|
// If true, query used the MySQL `DESCRIBE` alias for explain
|
||||||
|
describe_alias: bool,
|
||||||
/// Carry out the command and show actual run times and other statistics.
|
/// Carry out the command and show actual run times and other statistics.
|
||||||
analyze: bool,
|
analyze: bool,
|
||||||
// Display additional information regarding the plan.
|
// Display additional information regarding the plan.
|
||||||
|
@ -781,12 +791,29 @@ impl fmt::Display for Statement {
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
Statement::ExplainTable {
|
||||||
|
describe_alias,
|
||||||
|
table_name,
|
||||||
|
} => {
|
||||||
|
if *describe_alias {
|
||||||
|
write!(f, "DESCRIBE ")?;
|
||||||
|
} else {
|
||||||
|
write!(f, "EXPLAIN ")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "{}", table_name)
|
||||||
|
}
|
||||||
Statement::Explain {
|
Statement::Explain {
|
||||||
|
describe_alias,
|
||||||
verbose,
|
verbose,
|
||||||
analyze,
|
analyze,
|
||||||
statement,
|
statement,
|
||||||
} => {
|
} => {
|
||||||
write!(f, "EXPLAIN ")?;
|
if *describe_alias {
|
||||||
|
write!(f, "DESCRIBE ")?;
|
||||||
|
} else {
|
||||||
|
write!(f, "EXPLAIN ")?;
|
||||||
|
}
|
||||||
|
|
||||||
if *analyze {
|
if *analyze {
|
||||||
write!(f, "ANALYZE ")?;
|
write!(f, "ANALYZE ")?;
|
||||||
|
|
|
@ -141,7 +141,8 @@ impl<'a> Parser<'a> {
|
||||||
pub fn parse_statement(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_statement(&mut self) -> Result<Statement, ParserError> {
|
||||||
match self.next_token() {
|
match self.next_token() {
|
||||||
Token::Word(w) => match w.keyword {
|
Token::Word(w) => match w.keyword {
|
||||||
Keyword::EXPLAIN => Ok(self.parse_explain()?),
|
Keyword::DESCRIBE => Ok(self.parse_explain(true)?),
|
||||||
|
Keyword::EXPLAIN => Ok(self.parse_explain(false)?),
|
||||||
Keyword::ANALYZE => Ok(self.parse_analyze()?),
|
Keyword::ANALYZE => Ok(self.parse_analyze()?),
|
||||||
Keyword::SELECT | Keyword::WITH | Keyword::VALUES => {
|
Keyword::SELECT | Keyword::WITH | Keyword::VALUES => {
|
||||||
self.prev_token();
|
self.prev_token();
|
||||||
|
@ -2218,17 +2219,25 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_explain(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_explain(&mut self, describe_alias: bool) -> Result<Statement, ParserError> {
|
||||||
let analyze = self.parse_keyword(Keyword::ANALYZE);
|
let analyze = self.parse_keyword(Keyword::ANALYZE);
|
||||||
let verbose = self.parse_keyword(Keyword::VERBOSE);
|
let verbose = self.parse_keyword(Keyword::VERBOSE);
|
||||||
|
|
||||||
let statement = Box::new(self.parse_statement()?);
|
if let Some(statement) = self.maybe_parse(|parser| parser.parse_statement()) {
|
||||||
|
Ok(Statement::Explain {
|
||||||
|
describe_alias,
|
||||||
|
analyze,
|
||||||
|
verbose,
|
||||||
|
statement: Box::new(statement),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let table_name = self.parse_object_name()?;
|
||||||
|
|
||||||
Ok(Statement::Explain {
|
Ok(Statement::ExplainTable {
|
||||||
analyze,
|
describe_alias,
|
||||||
verbose,
|
table_name,
|
||||||
statement,
|
})
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a query expression, i.e. a `SELECT` statement optionally
|
/// Parse a query expression, i.e. a `SELECT` statement optionally
|
||||||
|
|
|
@ -1803,6 +1803,7 @@ fn parse_scalar_function_in_projection() {
|
||||||
fn run_explain_analyze(query: &str, expected_verbose: bool, expected_analyze: bool) {
|
fn run_explain_analyze(query: &str, expected_verbose: bool, expected_analyze: bool) {
|
||||||
match verified_stmt(query) {
|
match verified_stmt(query) {
|
||||||
Statement::Explain {
|
Statement::Explain {
|
||||||
|
describe_alias: _,
|
||||||
analyze,
|
analyze,
|
||||||
verbose,
|
verbose,
|
||||||
statement,
|
statement,
|
||||||
|
@ -1815,8 +1816,28 @@ fn run_explain_analyze(query: &str, expected_verbose: bool, expected_analyze: bo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_explain_table() {
|
||||||
|
let validate_explain = |query: &str, expected_describe_alias: bool| match verified_stmt(query) {
|
||||||
|
Statement::ExplainTable {
|
||||||
|
describe_alias,
|
||||||
|
table_name,
|
||||||
|
} => {
|
||||||
|
assert_eq!(describe_alias, expected_describe_alias);
|
||||||
|
assert_eq!("test_identifier", table_name.to_string());
|
||||||
|
}
|
||||||
|
_ => panic!("Unexpected Statement, must be ExplainTable"),
|
||||||
|
};
|
||||||
|
|
||||||
|
validate_explain("EXPLAIN test_identifier", false);
|
||||||
|
validate_explain("DESCRIBE test_identifier", true);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_explain_analyze_with_simple_select() {
|
fn parse_explain_analyze_with_simple_select() {
|
||||||
|
// Describe is an alias for EXPLAIN
|
||||||
|
run_explain_analyze("DESCRIBE SELECT sqrt(id) FROM foo", false, false);
|
||||||
|
|
||||||
run_explain_analyze("EXPLAIN SELECT sqrt(id) FROM foo", false, false);
|
run_explain_analyze("EXPLAIN SELECT sqrt(id) FROM foo", false, false);
|
||||||
run_explain_analyze("EXPLAIN VERBOSE SELECT sqrt(id) FROM foo", true, false);
|
run_explain_analyze("EXPLAIN VERBOSE SELECT sqrt(id) FROM foo", true, false);
|
||||||
run_explain_analyze("EXPLAIN ANALYZE SELECT sqrt(id) FROM foo", false, true);
|
run_explain_analyze("EXPLAIN ANALYZE SELECT sqrt(id) FROM foo", false, true);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue