@@ -266,6 +266,22 @@ impl ParserOptions {
266
266
self.unescape = unescape;
267
267
self
268
268
}
269
+
270
+ /// Set if semicolon statement delimiters are required.
271
+ ///
272
+ /// If this option is `true`, the following SQL will not parse. If the option is `false`, the SQL will parse.
273
+ ///
274
+ /// ```sql
275
+ /// SELECT 1
276
+ /// SELECT 2
277
+ /// ```
278
+ pub fn with_require_semicolon_stmt_delimiter(
279
+ mut self,
280
+ require_semicolon_stmt_delimiter: bool,
281
+ ) -> Self {
282
+ self.require_semicolon_stmt_delimiter = require_semicolon_stmt_delimiter;
283
+ self
284
+ }
269
285
}
270
286
271
287
#[derive(Copy, Clone)]
@@ -362,7 +378,11 @@ impl<'a> Parser<'a> {
362
378
state: ParserState::Normal,
363
379
dialect,
364
380
recursion_counter: RecursionCounter::new(DEFAULT_REMAINING_DEPTH),
365
- options: ParserOptions::new().with_trailing_commas(dialect.supports_trailing_commas()),
381
+ options: ParserOptions::new()
382
+ .with_trailing_commas(dialect.supports_trailing_commas())
383
+ .with_require_semicolon_stmt_delimiter(
384
+ !dialect.supports_statements_without_semicolon_delimiter(),
385
+ ),
366
386
}
367
387
}
368
388
@@ -485,10 +505,10 @@ impl<'a> Parser<'a> {
485
505
match self.peek_token().token {
486
506
Token::EOF => break,
487
507
488
- // end of statement
489
- Token::Word(word ) => {
490
- if expecting_statement_delimiter && word.keyword == Keyword::END {
491
- break ;
508
+ // don't expect a semicolon statement delimiter after a newline when not otherwise required
509
+ Token::Whitespace(Whitespace::Newline ) => {
510
+ if !self.options.require_semicolon_stmt_delimiter {
511
+ expecting_statement_delimiter = false ;
492
512
}
493
513
}
494
514
_ => {}
@@ -500,7 +520,7 @@ impl<'a> Parser<'a> {
500
520
501
521
let statement = self.parse_statement()?;
502
522
stmts.push(statement);
503
- expecting_statement_delimiter = true ;
523
+ expecting_statement_delimiter = self.options.require_semicolon_stmt_delimiter ;
504
524
}
505
525
Ok(stmts)
506
526
}
@@ -4558,6 +4578,9 @@ impl<'a> Parser<'a> {
4558
4578
) -> Result<Vec<Statement>, ParserError> {
4559
4579
let mut values = vec![];
4560
4580
loop {
4581
+ // ignore empty statements (between successive statement delimiters)
4582
+ while self.consume_token(&Token::SemiColon) {}
4583
+
4561
4584
match &self.peek_nth_token_ref(0).token {
4562
4585
Token::EOF => break,
4563
4586
Token::Word(w) => {
@@ -4569,7 +4592,13 @@ impl<'a> Parser<'a> {
4569
4592
}
4570
4593
4571
4594
values.push(self.parse_statement()?);
4572
- self.expect_token(&Token::SemiColon)?;
4595
+
4596
+ if self.options.require_semicolon_stmt_delimiter {
4597
+ self.expect_token(&Token::SemiColon)?;
4598
+ }
4599
+
4600
+ // ignore empty statements (between successive statement delimiters)
4601
+ while self.consume_token(&Token::SemiColon) {}
4573
4602
}
4574
4603
Ok(values)
4575
4604
}
@@ -16464,7 +16493,28 @@ impl<'a> Parser<'a> {
16464
16493
16465
16494
/// Parse [Statement::Return]
16466
16495
fn parse_return(&mut self) -> Result<Statement, ParserError> {
16467
- match self.maybe_parse(|p| p.parse_expr())? {
16496
+ let rs = self.maybe_parse(|p| {
16497
+ let expr = p.parse_expr()?;
16498
+
16499
+ match &expr {
16500
+ Expr::Value(_)
16501
+ | Expr::Function(_)
16502
+ | Expr::UnaryOp { .. }
16503
+ | Expr::BinaryOp { .. }
16504
+ | Expr::Case { .. }
16505
+ | Expr::Cast { .. }
16506
+ | Expr::Convert { .. }
16507
+ | Expr::Subquery(_) => Ok(expr),
16508
+ // todo: how to retstrict to variables?
16509
+ Expr::Identifier(id) if id.value.starts_with('@') => Ok(expr),
16510
+ _ => parser_err!(
16511
+ "Non-returnable expression found following RETURN",
16512
+ p.peek_token().span.start
16513
+ ),
16514
+ }
16515
+ })?;
16516
+
16517
+ match rs {
16468
16518
Some(expr) => Ok(Statement::Return(ReturnStatement {
16469
16519
value: Some(ReturnStatementValue::Expr(expr)),
16470
16520
})),
0 commit comments