Skip to content

Commit ef46680

Browse files
jonathanlehtoalamb
andauthored
Support EXPLAIN / DESCR / DESCRIBE [FORMATTED | EXTENDED] (apache#1156)
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
1 parent 991dbab commit ef46680

5 files changed

Lines changed: 103 additions & 30 deletions

File tree

src/ast/mod.rs

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2436,22 +2436,24 @@ pub enum Statement {
24362436
id: u64,
24372437
},
24382438
/// ```sql
2439-
/// EXPLAIN TABLE
2439+
/// [EXPLAIN | DESC | DESCRIBE] TABLE
24402440
/// ```
24412441
/// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
24422442
ExplainTable {
2443-
/// If true, query used the MySQL `DESCRIBE` alias for explain
2444-
describe_alias: bool,
2443+
/// `EXPLAIN | DESC | DESCRIBE`
2444+
describe_alias: DescribeAlias,
2445+
/// Hive style `FORMATTED | EXTENDED`
2446+
hive_format: Option<HiveDescribeFormat>,
24452447
/// Table name
24462448
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
24472449
table_name: ObjectName,
24482450
},
24492451
/// ```sql
2450-
/// [EXPLAIN | DESCRIBE <select statement>
2452+
/// [EXPLAIN | DESC | DESCRIBE] <statement>
24512453
/// ```
24522454
Explain {
2453-
// If true, query used the MySQL `DESCRIBE` alias for explain
2454-
describe_alias: bool,
2455+
/// `EXPLAIN | DESC | DESCRIBE`
2456+
describe_alias: DescribeAlias,
24552457
/// Carry out the command and show actual run times and other statistics.
24562458
analyze: bool,
24572459
// Display additional information regarding the plan.
@@ -2611,12 +2613,13 @@ impl fmt::Display for Statement {
26112613
}
26122614
Statement::ExplainTable {
26132615
describe_alias,
2616+
hive_format,
26142617
table_name,
26152618
} => {
2616-
if *describe_alias {
2617-
write!(f, "DESCRIBE ")?;
2618-
} else {
2619-
write!(f, "EXPLAIN ")?;
2619+
write!(f, "{describe_alias} ")?;
2620+
2621+
if let Some(format) = hive_format {
2622+
write!(f, "{} ", format)?;
26202623
}
26212624

26222625
write!(f, "{table_name}")
@@ -2628,11 +2631,7 @@ impl fmt::Display for Statement {
26282631
statement,
26292632
format,
26302633
} => {
2631-
if *describe_alias {
2632-
write!(f, "DESCRIBE ")?;
2633-
} else {
2634-
write!(f, "EXPLAIN ")?;
2635-
}
2634+
write!(f, "{describe_alias} ")?;
26362635

26372636
if *analyze {
26382637
write!(f, "ANALYZE ")?;
@@ -4925,6 +4924,44 @@ impl fmt::Display for HiveDelimiter {
49254924
}
49264925
}
49274926

4927+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4928+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4929+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4930+
pub enum HiveDescribeFormat {
4931+
Extended,
4932+
Formatted,
4933+
}
4934+
4935+
impl fmt::Display for HiveDescribeFormat {
4936+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4937+
use HiveDescribeFormat::*;
4938+
f.write_str(match self {
4939+
Extended => "EXTENDED",
4940+
Formatted => "FORMATTED",
4941+
})
4942+
}
4943+
}
4944+
4945+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4946+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4947+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4948+
pub enum DescribeAlias {
4949+
Describe,
4950+
Explain,
4951+
Desc,
4952+
}
4953+
4954+
impl fmt::Display for DescribeAlias {
4955+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4956+
use DescribeAlias::*;
4957+
f.write_str(match self {
4958+
Describe => "DESCRIBE",
4959+
Explain => "EXPLAIN",
4960+
Desc => "DESC",
4961+
})
4962+
}
4963+
}
4964+
49284965
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
49294966
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
49304967
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ define_keywords!(
303303
FORCE_QUOTE,
304304
FOREIGN,
305305
FORMAT,
306+
FORMATTED,
306307
FORWARD,
307308
FRAME_ROW,
308309
FREE,

src/parser/mod.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,9 @@ impl<'a> Parser<'a> {
464464
Token::Word(w) => match w.keyword {
465465
Keyword::KILL => Ok(self.parse_kill()?),
466466
Keyword::FLUSH => Ok(self.parse_flush()?),
467-
Keyword::DESCRIBE => Ok(self.parse_explain(true)?),
468-
Keyword::EXPLAIN => Ok(self.parse_explain(false)?),
467+
Keyword::DESC => Ok(self.parse_explain(DescribeAlias::Desc)?),
468+
Keyword::DESCRIBE => Ok(self.parse_explain(DescribeAlias::Describe)?),
469+
Keyword::EXPLAIN => Ok(self.parse_explain(DescribeAlias::Explain)?),
469470
Keyword::ANALYZE => Ok(self.parse_analyze()?),
470471
Keyword::SELECT | Keyword::WITH | Keyword::VALUES => {
471472
self.prev_token();
@@ -6805,7 +6806,10 @@ impl<'a> Parser<'a> {
68056806
Ok(Statement::Kill { modifier, id })
68066807
}
68076808

6808-
pub fn parse_explain(&mut self, describe_alias: bool) -> Result<Statement, ParserError> {
6809+
pub fn parse_explain(
6810+
&mut self,
6811+
describe_alias: DescribeAlias,
6812+
) -> Result<Statement, ParserError> {
68096813
let analyze = self.parse_keyword(Keyword::ANALYZE);
68106814
let verbose = self.parse_keyword(Keyword::VERBOSE);
68116815
let mut format = None;
@@ -6825,9 +6829,17 @@ impl<'a> Parser<'a> {
68256829
format,
68266830
}),
68276831
_ => {
6832+
let mut hive_format = None;
6833+
match self.parse_one_of_keywords(&[Keyword::EXTENDED, Keyword::FORMATTED]) {
6834+
Some(Keyword::EXTENDED) => hive_format = Some(HiveDescribeFormat::Extended),
6835+
Some(Keyword::FORMATTED) => hive_format = Some(HiveDescribeFormat::Formatted),
6836+
_ => {}
6837+
}
6838+
68286839
let table_name = self.parse_object_name(false)?;
68296840
Ok(Statement::ExplainTable {
68306841
describe_alias,
6842+
hive_format,
68316843
table_name,
68326844
})
68336845
}

tests/sqlparser_common.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3932,19 +3932,32 @@ fn run_explain_analyze(
39323932

39333933
#[test]
39343934
fn parse_explain_table() {
3935-
let validate_explain = |query: &str, expected_describe_alias: bool| match verified_stmt(query) {
3936-
Statement::ExplainTable {
3937-
describe_alias,
3938-
table_name,
3939-
} => {
3940-
assert_eq!(describe_alias, expected_describe_alias);
3941-
assert_eq!("test_identifier", table_name.to_string());
3942-
}
3943-
_ => panic!("Unexpected Statement, must be ExplainTable"),
3944-
};
3935+
let validate_explain =
3936+
|query: &str, expected_describe_alias: DescribeAlias| match verified_stmt(query) {
3937+
Statement::ExplainTable {
3938+
describe_alias,
3939+
hive_format,
3940+
table_name,
3941+
} => {
3942+
assert_eq!(describe_alias, expected_describe_alias);
3943+
assert_eq!(hive_format, None);
3944+
assert_eq!("test_identifier", table_name.to_string());
3945+
}
3946+
_ => panic!("Unexpected Statement, must be ExplainTable"),
3947+
};
3948+
3949+
validate_explain("EXPLAIN test_identifier", DescribeAlias::Explain);
3950+
validate_explain("DESCRIBE test_identifier", DescribeAlias::Describe);
3951+
}
39453952

3946-
validate_explain("EXPLAIN test_identifier", false);
3947-
validate_explain("DESCRIBE test_identifier", true);
3953+
#[test]
3954+
fn explain_describe() {
3955+
verified_stmt("DESCRIBE test.table");
3956+
}
3957+
3958+
#[test]
3959+
fn explain_desc() {
3960+
verified_stmt("DESC test.table");
39483961
}
39493962

39503963
#[test]

tests/sqlparser_hive.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ fn parse_describe() {
4848
generic(None).verified_stmt(describe);
4949
}
5050

51+
#[test]
52+
fn explain_describe_formatted() {
53+
hive().verified_stmt("DESCRIBE FORMATTED test.table");
54+
}
55+
56+
#[test]
57+
fn explain_describe_extended() {
58+
hive().verified_stmt("DESCRIBE EXTENDED test.table");
59+
}
60+
5161
#[test]
5262
fn parse_insert_overwrite() {
5363
let insert_partitions = r#"INSERT OVERWRITE TABLE db.new_table PARTITION (a = '1', b) SELECT a, b, c FROM db.table"#;

0 commit comments

Comments
 (0)