Skip to content

Commit 0a90913

Browse files
authored
parser: fix more pg test suite errors part 4 (#523)
1 parent 05d1b73 commit 0a90913

31 files changed

+597
-1434
lines changed

crates/squawk_lexer/src/lib.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -358,13 +358,13 @@ impl Cursor<'_> {
358358
fn double_quoted_string(&mut self) -> bool {
359359
while let Some(c) = self.bump() {
360360
match c {
361-
'"' => {
362-
return true;
363-
}
364-
'\\' if self.first() == '\\' || self.first() == '"' => {
361+
'"' if self.first() == '"' => {
365362
// Bump again to skip escaped character.
366363
self.bump();
367364
}
365+
'"' => {
366+
return true;
367+
}
368368
_ => (),
369369
}
370370
}
@@ -738,6 +738,13 @@ U&"d!0061t!+000061" UESCAPE '!'
738738
739739
740740
"hello-world
741+
"#))
742+
}
743+
744+
#[test]
745+
fn quoted_ident_with_escape_quote() {
746+
assert_debug_snapshot!(lex(r#"
747+
"foo "" bar"
741748
"#))
742749
}
743750
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
source: crates/squawk_lexer/src/lib.rs
3+
expression: "lex(r#\"\n\"foo \"\" bar\"\n\"#)"
4+
---
5+
[
6+
"\n" @ Whitespace,
7+
"\"foo \"\" bar\"" @ QuotedIdent { terminated: true },
8+
"\n" @ Whitespace,
9+
]

crates/squawk_parser/src/grammar.rs

Lines changed: 102 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,32 +2239,7 @@ fn with_query(p: &mut Parser<'_>) -> Option<CompletedMarker> {
22392239
p.eat(MATERIALIZED_KW);
22402240
}
22412241
p.expect(L_PAREN);
2242-
match p.current() {
2243-
DELETE_KW => {
2244-
delete(p, None);
2245-
}
2246-
SELECT_KW | TABLE_KW | VALUES_KW => {
2247-
select(p, None);
2248-
}
2249-
INSERT_KW => {
2250-
insert(p, None);
2251-
}
2252-
UPDATE_KW => {
2253-
update(p, None);
2254-
}
2255-
MERGE_KW => {
2256-
merge(p, None);
2257-
}
2258-
WITH_KW => {
2259-
with(p, None);
2260-
}
2261-
_ => {
2262-
p.error(format!(
2263-
"expected DELETE, SELECT, TABLE, VALUES, INSERT, WITH, or UPDATE, got: {:?}",
2264-
p.current()
2265-
));
2266-
}
2267-
}
2242+
preparable_stmt(p);
22682243
p.expect(R_PAREN);
22692244
// [ SEARCH { BREADTH | DEPTH } FIRST BY column_name [, ...] SET search_seq_col_name ]
22702245
if p.eat(SEARCH_KW) {
@@ -9590,7 +9565,7 @@ fn drop_text_search_parser(p: &mut Parser<'_>) -> CompletedMarker {
95909565
p.bump(SEARCH_KW);
95919566
p.bump(PARSER_KW);
95929567
opt_if_exists(p);
9593-
name_ref(p);
9568+
path_name_ref(p);
95949569
opt_cascade_or_restrict(p);
95959570
m.complete(p, DROP_TEXT_SEARCH_PARSER)
95969571
}
@@ -9609,7 +9584,7 @@ fn drop_text_search_config(p: &mut Parser<'_>) -> CompletedMarker {
96099584
p.bump(SEARCH_KW);
96109585
p.bump(CONFIGURATION_KW);
96119586
opt_if_exists(p);
9612-
name_ref(p);
9587+
path_name_ref(p);
96139588
opt_cascade_or_restrict(p);
96149589
m.complete(p, DROP_TEXT_SEARCH_CONFIG)
96159590
}
@@ -9628,7 +9603,7 @@ fn drop_text_search_dict(p: &mut Parser<'_>) -> CompletedMarker {
96289603
p.bump(SEARCH_KW);
96299604
p.bump(DICTIONARY_KW);
96309605
opt_if_exists(p);
9631-
name_ref(p);
9606+
path_name_ref(p);
96329607
opt_cascade_or_restrict(p);
96339608
m.complete(p, DROP_TEXT_SEARCH_DICT)
96349609
}
@@ -9644,7 +9619,7 @@ fn drop_text_search_template(p: &mut Parser<'_>) -> CompletedMarker {
96449619
p.bump(SEARCH_KW);
96459620
p.bump(TEMPLATE_KW);
96469621
opt_if_exists(p);
9647-
name_ref(p);
9622+
path_name_ref(p);
96489623
opt_cascade_or_restrict(p);
96499624
m.complete(p, DROP_TEXT_SEARCH_TEMPLATE)
96509625
}
@@ -10855,27 +10830,7 @@ fn prepare(p: &mut Parser<'_>) -> CompletedMarker {
1085510830
p.expect(R_PAREN);
1085610831
}
1085710832
p.expect(AS_KW);
10858-
// statement
10859-
// Any SELECT, INSERT, UPDATE, DELETE, MERGE, or VALUES statement.
10860-
let statement = stmt(
10861-
p,
10862-
&StmtRestrictions {
10863-
begin_end_allowed: false,
10864-
},
10865-
);
10866-
if let Some(statement) = statement {
10867-
match statement.kind() {
10868-
SELECT | COMPOUND_SELECT | SELECT_INTO | VALUES | INSERT | UPDATE | DELETE | MERGE => {}
10869-
kind => {
10870-
p.error(format!(
10871-
"expected SELECT, INSERT, UPDATE, DELETE, MERGE, or VALUES statement, got {:?}",
10872-
kind
10873-
));
10874-
}
10875-
}
10876-
} else {
10877-
p.error("expected SELECT, INSERT, UPDATE, DELETE, MERGE, or VALUES statement");
10878-
}
10833+
preparable_stmt(p);
1087910834
m.complete(p, PREPARE)
1088010835
}
1088110836

@@ -11008,8 +10963,25 @@ fn declare(p: &mut Parser<'_>) -> CompletedMarker {
1100810963
p.expect(HOLD_KW);
1100910964
}
1101010965
p.expect(FOR_KW);
11011-
// select_stmt | values_stmt
11012-
query(p);
10966+
// select stmt
10967+
let statement = stmt(
10968+
p,
10969+
&StmtRestrictions {
10970+
begin_end_allowed: false,
10971+
},
10972+
);
10973+
match statement.map(|x| x.kind()) {
10974+
Some(SELECT | SELECT_INTO | COMPOUND_SELECT | TABLE | VALUES) => (),
10975+
Some(kind) => {
10976+
p.error(format!(
10977+
"expected SELECT, TABLE, or VALUES statement, got {:?}",
10978+
kind
10979+
));
10980+
}
10981+
None => {
10982+
p.error("expected SELECT, TABLE, or VALUES statement");
10983+
}
10984+
}
1101310985
m.complete(p, DECLARE)
1101410986
}
1101510987

@@ -11282,6 +11254,51 @@ fn copy_option_list(p: &mut Parser<'_>) {
1128211254
p.expect(R_PAREN);
1128311255
}
1128411256

11257+
fn opt_copy_option_item(p: &mut Parser<'_>) -> bool {
11258+
match p.current() {
11259+
BINARY_KW | FREEZE_KW | CSV_KW | HEADER_KW => {
11260+
p.bump_any();
11261+
}
11262+
DELIMITER_KW | NULL_KW | QUOTE_KW | ESCAPE_KW => {
11263+
p.bump_any();
11264+
p.eat(AS_KW);
11265+
string_literal(p);
11266+
}
11267+
ENCODING_KW => {
11268+
p.bump_any();
11269+
string_literal(p);
11270+
}
11271+
FORCE_KW => {
11272+
p.bump_any();
11273+
match p.current() {
11274+
NOT_KW => {
11275+
p.bump_any();
11276+
p.expect(NULL_KW);
11277+
if !p.eat(STAR) {
11278+
name_ref(p);
11279+
while !p.at(EOF) && p.eat(COMMA) {
11280+
name_ref(p);
11281+
}
11282+
}
11283+
}
11284+
QUOTE_KW | NULL_KW => {
11285+
p.bump_any();
11286+
if !p.eat(STAR) {
11287+
name_ref(p);
11288+
while !p.at(EOF) && p.eat(COMMA) {
11289+
name_ref(p);
11290+
}
11291+
}
11292+
}
11293+
_ => return false,
11294+
}
11295+
}
11296+
11297+
_ => return false,
11298+
}
11299+
true
11300+
}
11301+
1128511302
// COPY table_name [ ( column_name [, ...] ) ]
1128611303
// FROM { 'filename' | PROGRAM 'command' | STDIN }
1128711304
// [ [ WITH ] ( option [, ...] ) ]
@@ -11347,8 +11364,7 @@ fn copy(p: &mut Parser<'_>) -> CompletedMarker {
1134711364
let m = p.start();
1134811365
p.bump(COPY_KW);
1134911366
if p.eat(L_PAREN) {
11350-
// query
11351-
query(p);
11367+
preparable_stmt(p);
1135211368
p.expect(R_PAREN);
1135311369
} else {
1135411370
// table_name
@@ -11372,14 +11388,43 @@ fn copy(p: &mut Parser<'_>) -> CompletedMarker {
1137211388
string_literal(p);
1137311389
}
1137411390
}
11375-
// [ [ WITH ] ( option [, ...] ) ]
11376-
if p.eat(WITH_KW) || p.at(L_PAREN) {
11391+
p.eat(WITH_KW);
11392+
// [ ( option [, ...] ) ]
11393+
if p.at(L_PAREN) {
1137711394
copy_option_list(p);
11395+
} else {
11396+
// old copy option syntax
11397+
while !p.at(EOF) && opt_copy_option_item(p) {}
1137811398
}
1137911399
opt_where_clause(p);
1138011400
m.complete(p, COPY)
1138111401
}
1138211402

11403+
fn preparable_stmt(p: &mut Parser<'_>) {
11404+
let statement = stmt(
11405+
p,
11406+
&StmtRestrictions {
11407+
begin_end_allowed: false,
11408+
},
11409+
);
11410+
match statement.map(|x| x.kind()) {
11411+
// select | insert | update | delete | merge
11412+
Some(
11413+
SELECT | SELECT_INTO | COMPOUND_SELECT | TABLE | VALUES | INSERT | UPDATE | DELETE
11414+
| MERGE,
11415+
) => (),
11416+
Some(kind) => {
11417+
p.error(format!(
11418+
"expected SELECT, TABLE, VALUES, INSERT, UPDATE, DELETE, or MERGE statement, got {:?}",
11419+
kind
11420+
));
11421+
}
11422+
None => {
11423+
p.error("expected SELECT, TABLE, VALUES, INSERT, UPDATE, DELETE, or MERGE statement");
11424+
}
11425+
}
11426+
}
11427+
1138311428
// https://www.postgresql.org/docs/17/sql-call.html
1138411429
// CALL name ( [ argument ] [, ...] )
1138511430
fn call(p: &mut Parser<'_>) -> CompletedMarker {

0 commit comments

Comments
 (0)