1use alloc::vec::Vec;
14
15use crate::{
16 QualifiedName, SelectExpr, Span, Spanned, TableReference,
17 expression::{Expression, PRIORITY_MAX, parse_expression_unreserved},
18 keywords::{Keyword, Restrict},
19 lexer::Token,
20 parser::{ParseError, Parser},
21 qualified_name::parse_qualified_name_unreserved,
22 select::{OrderFlag, parse_select_expr, parse_table_reference},
23};
24
25#[derive(Clone, Debug)]
27pub enum DeleteFlag {
28 LowPriority(Span),
29 Quick(Span),
30 Ignore(Span),
31}
32
33impl Spanned for DeleteFlag {
34 fn span(&self) -> Span {
35 match &self {
36 DeleteFlag::LowPriority(v) => v.span(),
37 DeleteFlag::Quick(v) => v.span(),
38 DeleteFlag::Ignore(v) => v.span(),
39 }
40 }
41}
42
43#[derive(Clone, Debug)]
68pub struct Delete<'a> {
69 pub delete_span: Span,
71 pub flags: Vec<DeleteFlag>,
73 pub from_span: Span,
75 pub tables: Vec<QualifiedName<'a>>,
77 pub using: Vec<TableReference<'a>>,
79 pub where_: Option<(Expression<'a>, Span)>,
81 pub order_by: Option<(Span, Vec<(Expression<'a>, OrderFlag)>)>,
83 pub limit: Option<(Span, Option<Expression<'a>>, Expression<'a>)>,
85 pub returning: Option<(Span, Vec<SelectExpr<'a>>)>,
87}
88
89impl<'a> Spanned for Delete<'a> {
90 fn span(&self) -> Span {
91 self.delete_span
92 .join_span(&self.flags)
93 .join_span(&self.from_span)
94 .join_span(&self.tables)
95 .join_span(&self.using)
96 .join_span(&self.where_)
97 .join_span(&self.order_by)
98 .join_span(&self.limit)
99 .join_span(&self.returning)
100 }
101}
102
103pub(crate) fn parse_delete<'a>(parser: &mut Parser<'a, '_>) -> Result<Delete<'a>, ParseError> {
104 let delete_span = parser.consume_keyword(Keyword::DELETE)?;
105 let mut flags = Vec::new();
106
107 loop {
108 match &parser.token {
109 Token::Ident(_, Keyword::LOW_PRIORITY) => flags.push(DeleteFlag::LowPriority(
110 parser.consume_keyword(Keyword::LOW_PRIORITY)?,
111 )),
112 Token::Ident(_, Keyword::QUICK) => {
113 flags.push(DeleteFlag::Quick(parser.consume_keyword(Keyword::QUICK)?))
114 }
115 Token::Ident(_, Keyword::IGNORE) => {
116 flags.push(DeleteFlag::Ignore(parser.consume_keyword(Keyword::IGNORE)?))
117 }
118 _ => break,
119 }
120 }
121
122 let mut tables = Vec::new();
123 let mut using = Vec::new();
124 let from_span = if let Some(from_span) = parser.skip_keyword(Keyword::FROM) {
125 loop {
126 tables.push(parse_qualified_name_unreserved(parser)?);
127 if matches!(&parser.token, Token::Ident(_, k) if !k.restricted(parser.reserved() | Restrict::EMPTY))
129 {
130 parser.consume();
131 }
132 if parser.skip_token(Token::Comma).is_none() {
133 break;
134 }
135 }
136 from_span
137 } else {
138 loop {
139 tables.push(parse_qualified_name_unreserved(parser)?);
140 if parser.skip_token(Token::Comma).is_none() {
141 break;
142 }
143 }
144 let from_span = parser.consume_keyword(Keyword::FROM)?;
145 loop {
146 using.push(parse_table_reference(parser, Restrict::EMPTY)?);
147 if parser.skip_token(Token::Comma).is_none() {
148 break;
149 }
150 }
151 from_span
152 };
153
154 if let Some(using_span) = parser.skip_keyword(Keyword::USING) {
158 if !using.is_empty() {
159 parser.err(
160 "Using not allowed in delete with table names before FROM",
161 &using_span,
162 );
163 }
164 loop {
165 using.push(parse_table_reference(parser, Restrict::EMPTY)?);
166 if parser.skip_token(Token::Comma).is_none() {
167 break;
168 }
169 }
170 }
171
172 let where_ = if let Some(span) = parser.skip_keyword(Keyword::WHERE) {
173 Some((parse_expression_unreserved(parser, PRIORITY_MAX)?, span))
174 } else {
175 None
176 };
177
178 let order_by = if let Some(span) = parser.skip_keyword(Keyword::ORDER) {
179 let span = parser.consume_keyword(Keyword::BY)?.join_span(&span);
180 let mut order = Vec::new();
181 loop {
182 let e = parse_expression_unreserved(parser, PRIORITY_MAX)?;
183 let f = match &parser.token {
184 Token::Ident(_, Keyword::ASC) => OrderFlag::Asc(parser.consume()),
185 Token::Ident(_, Keyword::DESC) => OrderFlag::Desc(parser.consume()),
186 _ => OrderFlag::None,
187 };
188 order.push((e, f));
189 if parser.skip_token(Token::Comma).is_none() {
190 break;
191 }
192 }
193 Some((span, order))
194 } else {
195 None
196 };
197
198 let limit = if let Some(span) = parser.skip_keyword(Keyword::LIMIT) {
199 let n = parse_expression_unreserved(parser, PRIORITY_MAX)?;
200 match parser.token {
201 Token::Comma => {
202 parser.consume();
203 Some((
204 span,
205 Some(n),
206 parse_expression_unreserved(parser, PRIORITY_MAX)?,
207 ))
208 }
209 Token::Ident(_, Keyword::OFFSET) => {
210 parser.consume();
211 Some((
212 span,
213 Some(parse_expression_unreserved(parser, PRIORITY_MAX)?),
214 n,
215 ))
216 }
217 _ => Some((span, None, n)),
218 }
219 } else {
220 None
221 };
222
223 let returning = if let Some(returning_span) = parser.skip_keyword(Keyword::RETURNING) {
224 let mut returning_exprs = Vec::new();
225 loop {
226 returning_exprs.push(parse_select_expr(parser)?);
227 if parser.skip_token(Token::Comma).is_none() {
228 break;
229 }
230 }
231 Some((returning_span, returning_exprs))
232 } else {
233 None
234 };
235
236 Ok(Delete {
237 flags,
238 delete_span,
239 tables,
240 using,
241 from_span,
242 where_,
243 order_by,
244 limit,
245 returning,
246 })
247}