Skip to content

Commit 345b1ec

Browse files
committed
feat: add remaining dml statements
1 parent 4e9dc81 commit 345b1ec

File tree

4 files changed

+99
-24
lines changed

4 files changed

+99
-24
lines changed

crates/pg_statement_splitter/src/lib.rs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
///! Postgres Statement Splitter
2-
///!
3-
///! This crate provides a function to split a SQL source string into individual statements.
1+
//! Postgres Statement Splitter
2+
//!
3+
//! This crate provides a function to split a SQL source string into individual statements.
44
mod parser;
55
mod syntax_error;
66

@@ -36,7 +36,13 @@ mod tests {
3636

3737
impl Tester {
3838
fn expect_statements(&self, expected: Vec<&str>) {
39-
assert_eq!(self.parse.ranges.len(), expected.len());
39+
assert_eq!(
40+
self.parse.ranges.len(),
41+
expected.len(),
42+
"Expected {} statements, got {}",
43+
expected.len(),
44+
self.parse.ranges.len()
45+
);
4046

4147
for (range, expected) in self.parse.ranges.iter().zip(expected.iter()) {
4248
assert_eq!(*expected, self.input[*range].to_string());
@@ -65,4 +71,46 @@ mod tests {
6571
"select 3",
6672
]);
6773
}
74+
75+
#[test]
76+
fn insert_into() {
77+
Tester::from("randomness\ninsert into tbl (id) values (1)\nselect 3").expect_statements(
78+
vec!["randomness", "insert into tbl (id) values (1)", "select 3"],
79+
);
80+
}
81+
82+
#[test]
83+
fn update() {
84+
Tester::from("more randomness\nupdate tbl set col = '1'\n\nselect 3").expect_statements(
85+
vec!["more randomness", "update tbl set col = '1'", "select 3"],
86+
);
87+
}
88+
89+
#[test]
90+
fn delete_from() {
91+
Tester::from("more randomness\ndelete from test where id = 1\n\nselect 3")
92+
.expect_statements(vec![
93+
"more randomness",
94+
"delete from test where id = 1",
95+
"select 3",
96+
]);
97+
}
98+
99+
#[test]
100+
fn unknown() {
101+
Tester::from("random stuff\n\nmore randomness\n\nselect 3").expect_statements(vec![
102+
"random stuff",
103+
"more randomness",
104+
"select 3",
105+
]);
106+
}
107+
108+
#[test]
109+
fn unknown_2() {
110+
Tester::from("random stuff\nselect 1\n\nselect 3").expect_statements(vec![
111+
"random stuff",
112+
"select 1",
113+
"select 3",
114+
]);
115+
}
68116
}

crates/pg_statement_splitter/src/parser.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,7 @@ impl Parser {
4040
// we dont care about whitespace tokens, except for double newlines
4141
// to make everything simpler, we just filter them out
4242
// the token holds the text range, so we dont need to worry about that
43-
let tokens = lex(sql)
44-
.iter()
45-
.filter(|t| {
46-
return !WHITESPACE_TOKENS.contains(&t.kind)
47-
|| (t.kind == SyntaxKind::Newline && t.text.chars().count() > 1);
48-
})
49-
.cloned()
50-
.collect::<Vec<_>>();
43+
let tokens = lex(sql);
5144

5245
let eof_token = Token::eof(usize::from(
5346
tokens
@@ -104,9 +97,25 @@ impl Parser {
10497
pub fn close_stmt(&mut self) {
10598
assert!(self.next_pos > 0);
10699

100+
// go back the positions until we find the first relevant token
101+
let mut end_token_pos = self.next_pos - 1;
102+
loop {
103+
let token = self.tokens.get(end_token_pos);
104+
105+
if end_token_pos == 0 || token.is_none() {
106+
break;
107+
}
108+
109+
if !is_irrelevant_token(token.unwrap()) {
110+
break;
111+
}
112+
113+
end_token_pos -= 1;
114+
}
115+
107116
self.ranges.push((
108117
self.current_stmt_start.expect("Expected active statement"),
109-
self.next_pos - 1,
118+
end_token_pos,
110119
));
111120

112121
self.current_stmt_start = None;

crates/pg_statement_splitter/src/parser/common.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use pg_lexer::{SyntaxKind, Token, TokenType};
22

33
use super::{
44
data::at_statement_start,
5-
dml::{cte, select},
5+
dml::{cte, delete, insert, select, update},
66
Parser,
77
};
88

@@ -16,7 +16,9 @@ pub fn source(p: &mut Parser) {
1616
break;
1717
}
1818
Token {
19-
token_type: TokenType::Whitespace | TokenType::NoKeyword,
19+
// we might want to ignore TokenType::NoKeyword here too
20+
// but this will lead to invalid statements to not being picked up
21+
token_type: TokenType::Whitespace,
2022
..
2123
} => {
2224
p.advance();
@@ -38,20 +40,16 @@ pub(crate) fn statement(p: &mut Parser) {
3840
select(p);
3941
}
4042
SyntaxKind::Insert => {
41-
todo!();
42-
// insert(p);
43+
insert(p);
4344
}
4445
SyntaxKind::Update => {
45-
todo!();
46-
// update(p);
46+
update(p);
4747
}
4848
SyntaxKind::DeleteP => {
49-
todo!();
50-
// delete(p);
49+
delete(p);
5150
}
52-
t => {
53-
panic!("stmt: Unknown start token {:?}", t);
54-
// unknown(p);
51+
_ => {
52+
unknown(p);
5553
}
5654
}
5755
p.close_stmt();

crates/pg_statement_splitter/src/parser/dml.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,23 @@ pub(crate) fn select(p: &mut Parser) {
2626

2727
unknown(p);
2828
}
29+
30+
pub(crate) fn insert(p: &mut Parser) {
31+
p.expect(SyntaxKind::Insert);
32+
p.expect(SyntaxKind::Into);
33+
34+
unknown(p);
35+
}
36+
37+
pub(crate) fn update(p: &mut Parser) {
38+
p.expect(SyntaxKind::Update);
39+
40+
unknown(p);
41+
}
42+
43+
pub(crate) fn delete(p: &mut Parser) {
44+
p.expect(SyntaxKind::DeleteP);
45+
p.expect(SyntaxKind::From);
46+
47+
unknown(p);
48+
}

0 commit comments

Comments
 (0)