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 parser.skip_token(Token::Comma).is_none() {
128 break;
129 }
130 }
131 from_span
132 } else {
133 loop {
134 tables.push(parse_qualified_name_unreserved(parser)?);
135 if parser.skip_token(Token::Comma).is_none() {
136 break;
137 }
138 }
139 let from_span = parser.consume_keyword(Keyword::FROM)?;
140 loop {
141 using.push(parse_table_reference(parser, Restrict::EMPTY)?);
142 if parser.skip_token(Token::Comma).is_none() {
143 break;
144 }
145 }
146 from_span
147 };
148
149 if let Some(using_span) = parser.skip_keyword(Keyword::USING) {
153 if !using.is_empty() {
154 parser.err(
155 "Using not allowed in delete with table names before FROM",
156 &using_span,
157 );
158 }
159 loop {
160 using.push(parse_table_reference(parser, Restrict::EMPTY)?);
161 if parser.skip_token(Token::Comma).is_none() {
162 break;
163 }
164 }
165 }
166
167 let where_ = if let Some(span) = parser.skip_keyword(Keyword::WHERE) {
168 Some((parse_expression_unreserved(parser, PRIORITY_MAX)?, span))
169 } else {
170 None
171 };
172
173 let order_by = if let Some(span) = parser.skip_keyword(Keyword::ORDER) {
174 let span = parser.consume_keyword(Keyword::BY)?.join_span(&span);
175 let mut order = Vec::new();
176 loop {
177 let e = parse_expression_unreserved(parser, PRIORITY_MAX)?;
178 let f = match &parser.token {
179 Token::Ident(_, Keyword::ASC) => OrderFlag::Asc(parser.consume()),
180 Token::Ident(_, Keyword::DESC) => OrderFlag::Desc(parser.consume()),
181 _ => OrderFlag::None,
182 };
183 order.push((e, f));
184 if parser.skip_token(Token::Comma).is_none() {
185 break;
186 }
187 }
188 Some((span, order))
189 } else {
190 None
191 };
192
193 let limit = if let Some(span) = parser.skip_keyword(Keyword::LIMIT) {
194 let n = parse_expression_unreserved(parser, PRIORITY_MAX)?;
195 match parser.token {
196 Token::Comma => {
197 parser.consume();
198 Some((
199 span,
200 Some(n),
201 parse_expression_unreserved(parser, PRIORITY_MAX)?,
202 ))
203 }
204 Token::Ident(_, Keyword::OFFSET) => {
205 parser.consume();
206 Some((
207 span,
208 Some(parse_expression_unreserved(parser, PRIORITY_MAX)?),
209 n,
210 ))
211 }
212 _ => Some((span, None, n)),
213 }
214 } else {
215 None
216 };
217
218 let returning = if let Some(returning_span) = parser.skip_keyword(Keyword::RETURNING) {
219 let mut returning_exprs = Vec::new();
220 loop {
221 returning_exprs.push(parse_select_expr(parser)?);
222 if parser.skip_token(Token::Comma).is_none() {
223 break;
224 }
225 }
226 Some((returning_span, returning_exprs))
227 } else {
228 None
229 };
230
231 Ok(Delete {
232 flags,
233 delete_span,
234 tables,
235 using,
236 from_span,
237 where_,
238 order_by,
239 limit,
240 returning,
241 })
242}