Skip to content

Commit

Permalink
Add support of EXPLAIN QUERY PLAN syntax for SQLite dialect (#1458)
Browse files Browse the repository at this point in the history
  • Loading branch information
git-hulk authored Oct 8, 2024
1 parent ac956dc commit 7905fb4
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3111,6 +3111,11 @@ pub enum Statement {
analyze: bool,
// Display additional information regarding the plan.
verbose: bool,
/// `EXPLAIN QUERY PLAN`
/// Display the query plan without running the query.
///
/// [SQLite](https://sqlite.org/lang_explain.html)
query_plan: bool,
/// A SQL query that specifies what to explain
statement: Box<Statement>,
/// Optional output format of explain
Expand Down Expand Up @@ -3302,12 +3307,16 @@ impl fmt::Display for Statement {
describe_alias,
verbose,
analyze,
query_plan,
statement,
format,
options,
} => {
write!(f, "{describe_alias} ")?;

if *query_plan {
write!(f, "QUERY PLAN ")?;
}
if *analyze {
write!(f, "ANALYZE ")?;
}
Expand Down
1 change: 1 addition & 0 deletions src/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ define_keywords!(
PERSISTENT,
PIVOT,
PLACING,
PLAN,
PLANS,
POLICY,
PORTION,
Expand Down
4 changes: 4 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8662,6 +8662,7 @@ impl<'a> Parser<'a> {
) -> Result<Statement, ParserError> {
let mut analyze = false;
let mut verbose = false;
let mut query_plan = false;
let mut format = None;
let mut options = None;

Expand All @@ -8672,6 +8673,8 @@ impl<'a> Parser<'a> {
&& self.peek_token().token == Token::LParen
{
options = Some(self.parse_utility_options()?)
} else if self.parse_keywords(&[Keyword::QUERY, Keyword::PLAN]) {
query_plan = true;
} else {
analyze = self.parse_keyword(Keyword::ANALYZE);
verbose = self.parse_keyword(Keyword::VERBOSE);
Expand All @@ -8688,6 +8691,7 @@ impl<'a> Parser<'a> {
describe_alias,
analyze,
verbose,
query_plan,
statement: Box::new(statement),
format,
options,
Expand Down
32 changes: 32 additions & 0 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4295,6 +4295,7 @@ fn run_explain_analyze(
describe_alias: _,
analyze,
verbose,
query_plan,
statement,
format,
options,
Expand All @@ -4303,6 +4304,7 @@ fn run_explain_analyze(
assert_eq!(analyze, expected_analyze);
assert_eq!(format, expected_format);
assert_eq!(options, exepcted_options);
assert!(!query_plan);
assert_eq!("SELECT sqrt(id) FROM foo", statement.to_string());
}
_ => panic!("Unexpected Statement, must be Explain"),
Expand Down Expand Up @@ -4417,6 +4419,36 @@ fn parse_explain_analyze_with_simple_select() {
);
}

#[test]
fn parse_explain_query_plan() {
match all_dialects().verified_stmt("EXPLAIN QUERY PLAN SELECT sqrt(id) FROM foo") {
Statement::Explain {
query_plan,
analyze,
verbose,
statement,
..
} => {
assert!(query_plan);
assert!(!analyze);
assert!(!verbose);
assert_eq!("SELECT sqrt(id) FROM foo", statement.to_string());
}
_ => unreachable!(),
}

// omit QUERY PLAN should be good
all_dialects().verified_stmt("EXPLAIN SELECT sqrt(id) FROM foo");

// missing PLAN keyword should return error
assert_eq!(
ParserError::ParserError("Expected: end of statement, found: SELECT".to_string()),
all_dialects()
.parse_sql_statements("EXPLAIN QUERY SELECT sqrt(id) FROM foo")
.unwrap_err()
);
}

#[test]
fn parse_named_argument_function() {
let sql = "SELECT FUN(a => '1', b => '2') FROM foo";
Expand Down

0 comments on commit 7905fb4

Please sign in to comment.