Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions crates/pgls_statement_splitter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,41 @@ END;",
}
}

#[test]
fn explain() {
let stmts = vec![
"EXPLAIN SELECT 1;",
"EXPLAIN ANALYZE SELECT 1;",
"EXPLAIN ANALYSE SELECT 1;",
"EXPLAIN VERBOSE SELECT 1;",
"EXPLAIN ANALYZE VERBOSE SELECT 1;",
"EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM my_table;",
"EXPLAIN (FORMAT JSON) SELECT * FROM my_table WHERE id = 1;",
"EXPLAIN INSERT INTO my_table (id) VALUES (1);",
"EXPLAIN ANALYZE UPDATE my_table SET col = 1 WHERE id = 2;",
"EXPLAIN DELETE FROM my_table WHERE id = 1;",
"EXPLAIN WITH cte AS (SELECT 1 AS x) SELECT * FROM cte;",
"EXPLAIN CREATE TABLE my_copy AS SELECT * FROM my_table;",
"explain analyze select 1;",
];

for stmt in stmts {
Tester::from(stmt).expect_statements(vec![stmt]);
}
}

#[test]
fn explain_between_statements() {
Tester::from("EXPLAIN SELECT 1;\nSELECT 2;")
.expect_statements(vec!["EXPLAIN SELECT 1;", "SELECT 2;"]);

Tester::from("explain select 1\n\nselect 2")
.expect_statements(vec!["explain select 1", "select 2"]);

Tester::from("explain select 1\nselect 2")
.expect_statements(vec!["explain select 1", "select 2"]);
}

#[test]
fn revoke() {
Tester::from("revoke delete on table \"public\".\"voice_call\" from \"anon\";")
Expand Down
3 changes: 2 additions & 1 deletion crates/pgls_statement_splitter/src/splitter/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::{
Splitter,
data::at_statement_start,
ddl::{alter, create},
dml::{cte, delete, insert, select, update},
dml::{cte, delete, explain, insert, select, update},
};

#[derive(Debug)]
Expand Down Expand Up @@ -58,6 +58,7 @@ pub(crate) fn statement(p: &mut Splitter) -> SplitterResult {
SyntaxKind::DELETE_KW => delete(p),
SyntaxKind::CREATE_KW => create(p),
SyntaxKind::ALTER_KW => alter(p),
SyntaxKind::EXPLAIN_KW => explain(p),
_ => unknown(p, &[]),
};

Expand Down
31 changes: 31 additions & 0 deletions crates/pgls_statement_splitter/src/splitter/dml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::splitter::common::SplitterResult;
use super::{
Splitter,
common::{parenthesis, unknown},
ddl::create,
};

pub(crate) fn cte(p: &mut Splitter) -> SplitterResult {
Expand Down Expand Up @@ -64,3 +65,33 @@ pub(crate) fn delete(p: &mut Splitter) -> SplitterResult {

unknown(p, &[])
}

/// `EXPLAIN [ ANALYZE ] [ VERBOSE ] statement` and
/// `EXPLAIN ( option [, ...] ) statement`
///
/// The explained statement must not be treated as the start of a new
/// statement, so we consume the EXPLAIN prefix and delegate to the splitter
/// function of the wrapped statement.
pub(crate) fn explain(p: &mut Splitter) -> SplitterResult {
p.expect(SyntaxKind::EXPLAIN_KW)?;

p.eat(SyntaxKind::ANALYZE_KW)?;
p.eat(SyntaxKind::ANALYSE_KW)?;
p.eat(SyntaxKind::VERBOSE_KW)?;

if p.current() == SyntaxKind::L_PAREN {
parenthesis(p)?;
}

match p.current() {
SyntaxKind::WITH_KW => cte(p),
SyntaxKind::SELECT_KW => select(p),
SyntaxKind::INSERT_KW => insert(p),
SyntaxKind::UPDATE_KW => update(p),
SyntaxKind::DELETE_KW => delete(p),
// EXPLAIN CREATE TABLE ... AS / CREATE MATERIALIZED VIEW ... AS
SyntaxKind::CREATE_KW => create(p),
// VALUES, EXECUTE, DECLARE, MERGE
_ => unknown(p, &[]),
}
}
Loading