Add optional format for explain (#621)

* Add format for explain

* Add comment
This commit is contained in:
Daniël Heres 2022-09-26 13:22:03 +02:00 committed by GitHub
parent 495ab59aad
commit 39761b0599
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 5 deletions

View file

@ -1294,6 +1294,8 @@ pub enum Statement {
verbose: bool, verbose: bool,
/// A SQL query that specifies what to explain /// A SQL query that specifies what to explain
statement: Box<Statement>, statement: Box<Statement>,
/// Optional output format of explain
format: Option<AnalyzeFormat>,
}, },
/// SAVEPOINT -- define a new savepoint within the current transaction /// SAVEPOINT -- define a new savepoint within the current transaction
Savepoint { name: Ident }, Savepoint { name: Ident },
@ -1344,6 +1346,7 @@ impl fmt::Display for Statement {
verbose, verbose,
analyze, analyze,
statement, statement,
format,
} => { } => {
if *describe_alias { if *describe_alias {
write!(f, "DESCRIBE ")?; write!(f, "DESCRIBE ")?;
@ -1359,6 +1362,10 @@ impl fmt::Display for Statement {
write!(f, "VERBOSE ")?; write!(f, "VERBOSE ")?;
} }
if let Some(format) = format {
write!(f, "FORMAT {} ", format)?;
}
write!(f, "{}", statement) write!(f, "{}", statement)
} }
Statement::Query(s) => write!(f, "{}", s), Statement::Query(s) => write!(f, "{}", s),
@ -2489,6 +2496,24 @@ pub struct Function {
pub special: bool, pub special: bool,
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AnalyzeFormat {
TEXT,
GRAPHVIZ,
JSON,
}
impl fmt::Display for AnalyzeFormat {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(match self {
AnalyzeFormat::TEXT => "TEXT",
AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
AnalyzeFormat::JSON => "JSON",
})
}
}
impl fmt::Display for Function { impl fmt::Display for Function {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.special { if self.special {

View file

@ -256,6 +256,7 @@ define_keywords!(
GLOBAL, GLOBAL,
GRANT, GRANT,
GRANTED, GRANTED,
GRAPHVIZ,
GROUP, GROUP,
GROUPING, GROUPING,
GROUPS, GROUPS,
@ -288,6 +289,7 @@ define_keywords!(
ISOYEAR, ISOYEAR,
JAR, JAR,
JOIN, JOIN,
JSON,
JSONFILE, JSONFILE,
JULIAN, JULIAN,
KEY, KEY,

View file

@ -2023,6 +2023,18 @@ impl<'a> Parser<'a> {
} }
} }
pub fn parse_analyze_format(&mut self) -> Result<AnalyzeFormat, ParserError> {
match self.next_token() {
Token::Word(w) => match w.keyword {
Keyword::TEXT => Ok(AnalyzeFormat::TEXT),
Keyword::GRAPHVIZ => Ok(AnalyzeFormat::GRAPHVIZ),
Keyword::JSON => Ok(AnalyzeFormat::JSON),
_ => self.expected("fileformat", Token::Word(w)),
},
unexpected => self.expected("fileformat", unexpected),
}
}
pub fn parse_create_view(&mut self, or_replace: bool) -> Result<Statement, ParserError> { pub fn parse_create_view(&mut self, or_replace: bool) -> Result<Statement, ParserError> {
let materialized = self.parse_keyword(Keyword::MATERIALIZED); let materialized = self.parse_keyword(Keyword::MATERIALIZED);
self.expect_keyword(Keyword::VIEW)?; self.expect_keyword(Keyword::VIEW)?;
@ -3432,6 +3444,10 @@ impl<'a> Parser<'a> {
pub fn parse_explain(&mut self, describe_alias: bool) -> 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 mut format = None;
if self.parse_keyword(Keyword::FORMAT) {
format = Some(self.parse_analyze_format()?);
}
if let Some(statement) = self.maybe_parse(|parser| parser.parse_statement()) { if let Some(statement) = self.maybe_parse(|parser| parser.parse_statement()) {
Ok(Statement::Explain { Ok(Statement::Explain {
@ -3439,6 +3455,7 @@ impl<'a> Parser<'a> {
analyze, analyze,
verbose, verbose,
statement: Box::new(statement), statement: Box::new(statement),
format,
}) })
} else { } else {
let table_name = self.parse_object_name()?; let table_name = self.parse_object_name()?;

View file

@ -2657,16 +2657,23 @@ 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,
expected_format: Option<AnalyzeFormat>,
) {
match verified_stmt(query) { match verified_stmt(query) {
Statement::Explain { Statement::Explain {
describe_alias: _, describe_alias: _,
analyze, analyze,
verbose, verbose,
statement, statement,
format,
} => { } => {
assert_eq!(verbose, expected_verbose); assert_eq!(verbose, expected_verbose);
assert_eq!(analyze, expected_analyze); assert_eq!(analyze, expected_analyze);
assert_eq!(format, expected_format);
assert_eq!("SELECT sqrt(id) FROM foo", statement.to_string()); assert_eq!("SELECT sqrt(id) FROM foo", statement.to_string());
} }
_ => panic!("Unexpected Statement, must be Explain"), _ => panic!("Unexpected Statement, must be Explain"),
@ -2693,15 +2700,47 @@ fn parse_explain_table() {
#[test] #[test]
fn parse_explain_analyze_with_simple_select() { fn parse_explain_analyze_with_simple_select() {
// Describe is an alias for EXPLAIN // Describe is an alias for EXPLAIN
run_explain_analyze("DESCRIBE SELECT sqrt(id) FROM foo", false, false); run_explain_analyze("DESCRIBE SELECT sqrt(id) FROM foo", false, false, None);
run_explain_analyze("EXPLAIN SELECT sqrt(id) FROM foo", false, false); run_explain_analyze("EXPLAIN SELECT sqrt(id) FROM foo", false, false, None);
run_explain_analyze("EXPLAIN VERBOSE SELECT sqrt(id) FROM foo", true, false); run_explain_analyze(
run_explain_analyze("EXPLAIN ANALYZE SELECT sqrt(id) FROM foo", false, true); "EXPLAIN VERBOSE SELECT sqrt(id) FROM foo",
true,
false,
None,
);
run_explain_analyze(
"EXPLAIN ANALYZE SELECT sqrt(id) FROM foo",
false,
true,
None,
);
run_explain_analyze( run_explain_analyze(
"EXPLAIN ANALYZE VERBOSE SELECT sqrt(id) FROM foo", "EXPLAIN ANALYZE VERBOSE SELECT sqrt(id) FROM foo",
true, true,
true, true,
None,
);
run_explain_analyze(
"EXPLAIN ANALYZE FORMAT GRAPHVIZ SELECT sqrt(id) FROM foo",
false,
true,
Some(AnalyzeFormat::GRAPHVIZ),
);
run_explain_analyze(
"EXPLAIN ANALYZE VERBOSE FORMAT JSON SELECT sqrt(id) FROM foo",
true,
true,
Some(AnalyzeFormat::JSON),
);
run_explain_analyze(
"EXPLAIN VERBOSE FORMAT TEXT SELECT sqrt(id) FROM foo",
true,
false,
Some(AnalyzeFormat::TEXT),
); );
} }