diff --git a/Cargo.lock b/Cargo.lock index 315584a..063ba19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "sql-parse" -version = "0.24.0" +version = "0.25.0" diff --git a/Cargo.toml b/Cargo.toml index 5b4439e..dfe2d03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sql-parse" -version = "0.24.0" +version = "0.25.0" edition = "2021" authors = ["Jakob Truelsen "] keywords = [ "mysql", "postgresql", "sql", "lexer", "parser" ] diff --git a/src/alter.rs b/src/alter.rs index 7e085e5..bfa1d9e 100644 --- a/src/alter.rs +++ b/src/alter.rs @@ -757,7 +757,7 @@ fn parse_alter_table<'a>( Token::Ident(_, Keyword::DEFAULT) => { let drop_default_span = parser.consume().join_span(&set_span); AlterColumnAction::DropDefault { - drop_default_span: drop_default_span, + drop_default_span, } } Token::Ident(_, Keyword::NOT) => { diff --git a/src/lexer.rs b/src/lexer.rs index 8b02894..1793ff7 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -216,7 +216,7 @@ impl<'a> Lexer<'a> { } // Data ends at EOF without NL '\' '.' [NL]. let span = start..self.src.len(); - return (self.s(span.clone()), span); + (self.s(span.clone()), span) } pub fn next_token(&mut self) -> (Token<'a>, Span) { diff --git a/src/parser.rs b/src/parser.rs index 531d087..8210865 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -10,7 +10,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use alloc::{borrow::Cow, fmt::Write, format, string::String, vec::Vec}; +use alloc::{borrow::Cow, format, string::String, vec::Vec}; use crate::{ issue::{IssueHandle, Issues}, @@ -75,21 +75,6 @@ pub(crate) fn decode_double_quoted_string(s: &str) -> Cow<'_, str> { } } -pub(crate) struct SingleQuotedString<'a>(pub(crate) &'a str); - -impl<'a> alloc::fmt::Display for SingleQuotedString<'a> { - fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result { - f.write_char('\'')?; - for c in self.0.chars() { - if c == '\'' { - f.write_char('\'')?; - } - f.write_char(c)?; - } - f.write_char('\'') - } -} - impl<'a, 'b> Parser<'a, 'b> { pub(crate) fn new(src: &'a str, issues: &'b mut Issues<'a>, options: &'b ParseOptions) -> Self { let mut lexer = Lexer::new(src); diff --git a/src/span.rs b/src/span.rs index 522ef05..1ec02ec 100644 --- a/src/span.rs +++ b/src/span.rs @@ -16,7 +16,6 @@ use alloc::{boxed::Box, vec::Vec}; pub type Span = core::ops::Range; /// Compute an optional byte span of an ast fragment - pub trait OptSpanned { /// Compute an optional byte span of an ast fragment fn opt_span(&self) -> Option; @@ -123,7 +122,7 @@ impl Spanned for (bool, S) { } } -impl<'a, S: Spanned> Spanned for (&'a str, S) { +impl Spanned for (& str, S) { fn span(&self) -> Span { self.1.span() } diff --git a/src/statement.rs b/src/statement.rs index 99f7704..2ce3b8a 100644 --- a/src/statement.rs +++ b/src/statement.rs @@ -381,6 +381,7 @@ fn parse_signal<'a>(parser: &mut Parser<'a, '_>) -> Result, ParseErro } /// SQL statement +#[allow(clippy::large_enum_variant)] #[derive(Clone, Debug)] pub enum Statement<'a> { CreateIndex(CreateIndex<'a>), diff --git a/src/update.rs b/src/update.rs index b23fcdb..c62aa18 100644 --- a/src/update.rs +++ b/src/update.rs @@ -18,9 +18,9 @@ use crate::{ keywords::Keyword, lexer::Token, parser::{ParseError, Parser}, - select::{parse_table_reference, TableReference}, + select::{parse_select_expr, parse_table_reference, TableReference}, span::OptSpanned, - Identifier, Span, Spanned, + Identifier, SelectExpr, Span, Spanned, }; /// Flags specified after "UPDATE" @@ -71,6 +71,8 @@ pub struct Update<'a> { pub set: Vec<(Vec>, Expression<'a>)>, /// Where expression and span of "WHERE" if specified pub where_: Option<(Expression<'a>, Span)>, + /// Span of "RETURNING" and select expressions after "RETURNING", if "RETURNING" is present + pub returning: Option<(Span, Vec>)>, } impl<'a> Spanned for Update<'a> { @@ -86,6 +88,7 @@ impl<'a> Spanned for Update<'a> { .join_span(&self.set_span) .join_span(&set_span) .join_span(&self.where_) + .join_span(&self.returning) } } @@ -134,6 +137,22 @@ pub(crate) fn parse_update<'a>(parser: &mut Parser<'a, '_>) -> Result None }; + let returning = if let Some(returning_span) = parser.skip_keyword(Keyword::RETURNING) { + let mut returning_exprs = Vec::new(); + loop { + returning_exprs.push(parse_select_expr(parser)?); + if parser.skip_token(Token::Comma).is_none() { + break; + } + } + if !parser.options.dialect.is_postgresql() { + parser.err("Only support by postgesql", &returning_span); + } + Some((returning_span, returning_exprs)) + } else { + None + }; + Ok(Update { flags, update_span, @@ -141,6 +160,7 @@ pub(crate) fn parse_update<'a>(parser: &mut Parser<'a, '_>) -> Result set_span, set, where_, + returning, }) }