Skip to content

Commit 7905fb4

Browse files
authored
Add support of EXPLAIN QUERY PLAN syntax for SQLite dialect (#1458)
1 parent ac956dc commit 7905fb4

File tree

4 files changed

+46
-0
lines changed

4 files changed

+46
-0
lines changed

src/ast/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -3111,6 +3111,11 @@ pub enum Statement {
31113111
analyze: bool,
31123112
// Display additional information regarding the plan.
31133113
verbose: bool,
3114+
/// `EXPLAIN QUERY PLAN`
3115+
/// Display the query plan without running the query.
3116+
///
3117+
/// [SQLite](https://sqlite.org/lang_explain.html)
3118+
query_plan: bool,
31143119
/// A SQL query that specifies what to explain
31153120
statement: Box<Statement>,
31163121
/// Optional output format of explain
@@ -3302,12 +3307,16 @@ impl fmt::Display for Statement {
33023307
describe_alias,
33033308
verbose,
33043309
analyze,
3310+
query_plan,
33053311
statement,
33063312
format,
33073313
options,
33083314
} => {
33093315
write!(f, "{describe_alias} ")?;
33103316

3317+
if *query_plan {
3318+
write!(f, "QUERY PLAN ")?;
3319+
}
33113320
if *analyze {
33123321
write!(f, "ANALYZE ")?;
33133322
}

src/keywords.rs

+1
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ define_keywords!(
572572
PERSISTENT,
573573
PIVOT,
574574
PLACING,
575+
PLAN,
575576
PLANS,
576577
POLICY,
577578
PORTION,

src/parser/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -8662,6 +8662,7 @@ impl<'a> Parser<'a> {
86628662
) -> Result<Statement, ParserError> {
86638663
let mut analyze = false;
86648664
let mut verbose = false;
8665+
let mut query_plan = false;
86658666
let mut format = None;
86668667
let mut options = None;
86678668

@@ -8672,6 +8673,8 @@ impl<'a> Parser<'a> {
86728673
&& self.peek_token().token == Token::LParen
86738674
{
86748675
options = Some(self.parse_utility_options()?)
8676+
} else if self.parse_keywords(&[Keyword::QUERY, Keyword::PLAN]) {
8677+
query_plan = true;
86758678
} else {
86768679
analyze = self.parse_keyword(Keyword::ANALYZE);
86778680
verbose = self.parse_keyword(Keyword::VERBOSE);
@@ -8688,6 +8691,7 @@ impl<'a> Parser<'a> {
86888691
describe_alias,
86898692
analyze,
86908693
verbose,
8694+
query_plan,
86918695
statement: Box::new(statement),
86928696
format,
86938697
options,

tests/sqlparser_common.rs

+32
Original file line numberDiff line numberDiff line change
@@ -4295,6 +4295,7 @@ fn run_explain_analyze(
42954295
describe_alias: _,
42964296
analyze,
42974297
verbose,
4298+
query_plan,
42984299
statement,
42994300
format,
43004301
options,
@@ -4303,6 +4304,7 @@ fn run_explain_analyze(
43034304
assert_eq!(analyze, expected_analyze);
43044305
assert_eq!(format, expected_format);
43054306
assert_eq!(options, exepcted_options);
4307+
assert!(!query_plan);
43064308
assert_eq!("SELECT sqrt(id) FROM foo", statement.to_string());
43074309
}
43084310
_ => panic!("Unexpected Statement, must be Explain"),
@@ -4417,6 +4419,36 @@ fn parse_explain_analyze_with_simple_select() {
44174419
);
44184420
}
44194421

4422+
#[test]
4423+
fn parse_explain_query_plan() {
4424+
match all_dialects().verified_stmt("EXPLAIN QUERY PLAN SELECT sqrt(id) FROM foo") {
4425+
Statement::Explain {
4426+
query_plan,
4427+
analyze,
4428+
verbose,
4429+
statement,
4430+
..
4431+
} => {
4432+
assert!(query_plan);
4433+
assert!(!analyze);
4434+
assert!(!verbose);
4435+
assert_eq!("SELECT sqrt(id) FROM foo", statement.to_string());
4436+
}
4437+
_ => unreachable!(),
4438+
}
4439+
4440+
// omit QUERY PLAN should be good
4441+
all_dialects().verified_stmt("EXPLAIN SELECT sqrt(id) FROM foo");
4442+
4443+
// missing PLAN keyword should return error
4444+
assert_eq!(
4445+
ParserError::ParserError("Expected: end of statement, found: SELECT".to_string()),
4446+
all_dialects()
4447+
.parse_sql_statements("EXPLAIN QUERY SELECT sqrt(id) FROM foo")
4448+
.unwrap_err()
4449+
);
4450+
}
4451+
44204452
#[test]
44214453
fn parse_named_argument_function() {
44224454
let sql = "SELECT FUN(a => '1', b => '2') FROM foo";

0 commit comments

Comments
 (0)