Skip to content

Commit 37137bc

Browse files
authored
fix: plpglsql cmds (#336)
1 parent 9bc27b7 commit 37137bc

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

crates/pgt_statement_splitter/src/lib.rs

+18
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,24 @@ mod tests {
136136
)]);
137137
}
138138

139+
#[test]
140+
fn command_between_not_starting() {
141+
Tester::from("select 1\n \\com test\nselect 2")
142+
.expect_statements(vec!["select 1", "select 2"]);
143+
}
144+
145+
#[test]
146+
fn command_between() {
147+
Tester::from("select 1\n\\com test\nselect 2")
148+
.expect_statements(vec!["select 1", "select 2"]);
149+
}
150+
151+
#[test]
152+
fn command_standalone() {
153+
Tester::from("select 1\n\n\\com test\n\nselect 2")
154+
.expect_statements(vec!["select 1", "select 2"]);
155+
}
156+
139157
#[test]
140158
fn insert_with_select() {
141159
Tester::from("\ninsert into tbl (id) select 1\n\nselect 3")

crates/pgt_statement_splitter/src/parser.rs

+3
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ impl Parser {
113113
}
114114
}
115115

116+
/// Advances the parser to the next relevant token and returns it.
117+
///
118+
/// NOTE: This will skip irrelevant tokens.
116119
fn advance(&mut self) -> &Token {
117120
// can't reuse any `find_next_relevant` logic because of Mr. Borrow Checker
118121
let (pos, token) = self

crates/pgt_statement_splitter/src/parser/common.rs

+55-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use pgt_lexer::{SyntaxKind, Token, TokenType};
1+
use pgt_lexer::{SyntaxKind, Token, TokenType, WHITESPACE_TOKENS};
22

33
use super::{
44
Parser,
@@ -24,6 +24,12 @@ pub fn source(p: &mut Parser) {
2424
} => {
2525
p.advance();
2626
}
27+
Token {
28+
kind: SyntaxKind::Ascii92,
29+
..
30+
} => {
31+
plpgsql_command(p);
32+
}
2733
_ => {
2834
statement(p);
2935
}
@@ -87,6 +93,24 @@ pub(crate) fn parenthesis(p: &mut Parser) {
8793
}
8894
}
8995

96+
pub(crate) fn plpgsql_command(p: &mut Parser) {
97+
p.expect(SyntaxKind::Ascii92);
98+
99+
loop {
100+
match p.current().kind {
101+
SyntaxKind::Newline => {
102+
p.advance();
103+
break;
104+
}
105+
_ => {
106+
// advance the parser to the next token without ignoring irrelevant tokens
107+
// we would skip a newline with `advance()`
108+
p.current_pos += 1;
109+
}
110+
}
111+
}
112+
}
113+
90114
pub(crate) fn case(p: &mut Parser) {
91115
p.expect(SyntaxKind::Case);
92116

@@ -125,6 +149,36 @@ pub(crate) fn unknown(p: &mut Parser, exclude: &[SyntaxKind]) {
125149
} => {
126150
case(p);
127151
}
152+
Token {
153+
kind: SyntaxKind::Ascii92,
154+
..
155+
} => {
156+
// pgsql commands e.g.
157+
//
158+
// ```
159+
// \if test
160+
// ```
161+
//
162+
// we wait for "\" and check if the previous token is a newline
163+
164+
// newline is a whitespace, but we do not want to ignore it here
165+
let irrelevant = WHITESPACE_TOKENS
166+
.iter()
167+
.filter(|t| **t != SyntaxKind::Newline)
168+
.collect::<Vec<_>>();
169+
170+
// go back from the current position without ignoring irrelevant tokens
171+
if p.tokens
172+
.iter()
173+
.take(p.current_pos)
174+
.rev()
175+
.find(|t| !irrelevant.contains(&&t.kind))
176+
.is_some_and(|t| t.kind == SyntaxKind::Newline)
177+
{
178+
break;
179+
}
180+
p.advance();
181+
}
128182
Token {
129183
kind: SyntaxKind::Ascii40,
130184
..

0 commit comments

Comments
 (0)